1
1
/*
2
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
25
25
*/
26
26
package jdk .internal .classfile .impl ;
27
27
28
- import java .lang .constant .ClassDesc ;
29
- import java .lang .constant .MethodTypeDesc ;
30
- import java .nio .ByteBuffer ;
31
- import java .util .BitSet ;
32
- import java .util .LinkedHashMap ;
33
- import java .util .List ;
34
- import java .util .stream .Collectors ;
35
28
import java .lang .classfile .TypeKind ;
36
29
import java .lang .classfile .constantpool .ConstantDynamicEntry ;
37
30
import java .lang .classfile .constantpool .DynamicConstantPoolEntry ;
38
31
import java .lang .classfile .constantpool .MemberRefEntry ;
39
- import static java .lang .classfile .ClassFile .*;
32
+ import java .lang .constant .MethodTypeDesc ;
33
+ import java .nio .ByteBuffer ;
34
+ import java .util .ArrayDeque ;
35
+ import java .util .BitSet ;
36
+ import java .util .List ;
37
+ import java .util .Queue ;
40
38
39
+ import static java .lang .classfile .ClassFile .*;
41
40
42
41
public final class StackCounter {
43
42
43
+ private record Target (int bci , int stack ) {}
44
+
44
45
static StackCounter of (DirectCodeBuilder dcb , BufWriterImpl buf ) {
45
46
return new StackCounter (
46
47
dcb ,
47
- buf .thisClass ().asSymbol (),
48
48
dcb .methodInfo .methodName ().stringValue (),
49
49
dcb .methodInfo .methodTypeSymbol (),
50
50
(dcb .methodInfo .methodFlags () & ACC_STATIC ) != 0 ,
@@ -59,12 +59,12 @@ static StackCounter of(DirectCodeBuilder dcb, BufWriterImpl buf) {
59
59
private final String methodName ;
60
60
private final MethodTypeDesc methodDesc ;
61
61
private final SplitConstantPool cp ;
62
- private final LinkedHashMap < Integer , Integer > map ;
62
+ private final Queue < Target > targets ;
63
63
private final BitSet visited ;
64
64
65
65
private void jump (int targetBci ) {
66
66
if (!visited .get (targetBci )) {
67
- map . put ( targetBci , stack );
67
+ targets . add ( new Target ( targetBci , stack ) );
68
68
}
69
69
}
70
70
@@ -78,13 +78,11 @@ private void ensureLocalSlot(int index) {
78
78
}
79
79
80
80
private boolean next () {
81
- var it = map .entrySet ().iterator ();
82
- while (it .hasNext ()) {
83
- var en = it .next ();
84
- it .remove ();
85
- if (!visited .get (en .getKey ())) {
86
- bcs .nextBci = en .getKey ();
87
- stack = en .getValue ();
81
+ Target en ;
82
+ while ((en = targets .poll ()) != null ) {
83
+ if (!visited .get (en .bci )) {
84
+ bcs .nextBci = en .bci ;
85
+ stack = en .stack ;
88
86
return true ;
89
87
}
90
88
}
@@ -93,7 +91,6 @@ private boolean next() {
93
91
}
94
92
95
93
public StackCounter (LabelContext labelContext ,
96
- ClassDesc thisClass ,
97
94
String methodName ,
98
95
MethodTypeDesc methodDesc ,
99
96
boolean isStatic ,
@@ -103,16 +100,14 @@ public StackCounter(LabelContext labelContext,
103
100
this .methodName = methodName ;
104
101
this .methodDesc = methodDesc ;
105
102
this .cp = cp ;
106
- map = new LinkedHashMap <>();
103
+ targets = new ArrayDeque <>();
107
104
maxStack = stack = rets = 0 ;
108
- for (var h : handlers ) map . put ( labelContext .labelToBci (h .handler ), 1 );
105
+ for (var h : handlers ) targets . add ( new Target ( labelContext .labelToBci (h .handler ), 1 ) );
109
106
maxLocals = isStatic ? 0 : 1 ;
110
- for (var cd : methodDesc .parameterList ()) {
111
- maxLocals += Util .slotSize (cd );
112
- }
107
+ maxLocals += Util .parameterSlots (methodDesc );
113
108
bcs = new RawBytecodeHelper (bytecode );
114
109
visited = new BitSet (bcs .endBci );
115
- map . put ( 0 , 0 );
110
+ targets . add ( new Target ( 0 , 0 ) );
116
111
while (next ()) {
117
112
while (!bcs .isLastBytecode ()) {
118
113
bcs .rawNext ();
@@ -307,14 +302,11 @@ public StackCounter(LabelContext labelContext,
307
302
case INVOKEVIRTUAL , INVOKESPECIAL , INVOKESTATIC , INVOKEINTERFACE , INVOKEDYNAMIC -> {
308
303
var cpe = cp .entryByIndex (bcs .getIndexU2 ());
309
304
var nameAndType = opcode == INVOKEDYNAMIC ? ((DynamicConstantPoolEntry )cpe ).nameAndType () : ((MemberRefEntry )cpe ).nameAndType ();
310
- var mDesc = MethodTypeDesc .ofDescriptor (nameAndType .type ().stringValue ());
311
- for (var arg : mDesc .parameterList ()) {
312
- addStackSlot (-TypeKind .from (arg ).slotSize ());
313
- }
305
+ var mtd = Util .methodTypeSymbol (nameAndType );
306
+ addStackSlot (Util .slotSize (mtd .returnType ()) - Util .parameterSlots (mtd ));
314
307
if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC ) {
315
308
addStackSlot (-1 );
316
309
}
317
- addStackSlot (TypeKind .from (mDesc .returnType ()).slotSize ());
318
310
}
319
311
case MULTIANEWARRAY ->
320
312
addStackSlot (1 - bcs .getU1 (bcs .bci + 3 ));
0 commit comments