42
42
import static com .oracle .svm .interpreter .metadata .Bytecodes .PUTFIELD ;
43
43
import static com .oracle .svm .interpreter .metadata .Bytecodes .PUTSTATIC ;
44
44
45
- import java .util .ArrayList ;
46
- import java .util .HashMap ;
47
45
import java .util .List ;
48
- import java .util .Map ;
49
46
50
47
import org .graalvm .nativeimage .Platform ;
51
48
import org .graalvm .nativeimage .Platforms ;
56
53
import com .oracle .svm .core .meta .MethodPointer ;
57
54
import com .oracle .svm .core .util .UserError ;
58
55
import com .oracle .svm .core .util .VMError ;
59
- import com .oracle .svm .espresso .classfile .ConstantPool .Tag ;
60
- import com .oracle .svm .espresso .classfile .ParserConstantPool ;
61
- import com .oracle .svm .espresso .classfile .descriptors .Symbol ;
62
56
import com .oracle .svm .hosted .meta .HostedMethod ;
63
57
import com .oracle .svm .hosted .meta .HostedUniverse ;
64
- import com .oracle .svm .interpreter .classfile . ClassFile ;
58
+ import com .oracle .svm .interpreter .constantpool . ConstantPoolBuilder ;
65
59
import com .oracle .svm .interpreter .metadata .BytecodeStream ;
66
60
import com .oracle .svm .interpreter .metadata .Bytecodes ;
67
61
import com .oracle .svm .interpreter .metadata .InterpreterConstantPool ;
@@ -97,176 +91,78 @@ final class BuildTimeConstantPool {
97
91
98
92
private static final ExceptionHandler [] EMPTY_EXCEPTION_HANDLERS = new ExceptionHandler [0 ];
99
93
100
- private final InterpreterResolvedObjectType holder ;
101
-
102
- private final Map <Object , Integer > constantCPI ;
103
- private final Map <JavaConstant , Integer > appendixCPI ;
104
- private final Map <JavaField , Integer > fieldCPI ;
105
- private final Map <JavaType , Integer > typeCPI ;
106
- private final Map <JavaMethod , Integer > methodCPI ;
107
-
108
- final ArrayList <Object > entries ;
109
- final ArrayList <Tag > tags ;
94
+ private final ConstantPoolBuilder poolBuilder ;
110
95
111
96
/**
112
97
* Creates runtime-ready constant pool for the interpreter.
113
98
*/
114
99
public InterpreterConstantPool snapshot () {
115
100
// Contains a partial parser/symbolic constant pool.
116
- return InterpreterConstantPool .create (holder , buildParserConstantPool (), entries .toArray ());
117
- }
118
-
119
- /**
120
- * Currently, it's not possible to derive a perfect parser/symbolic CP representation from JVMCI
121
- * data-structures, for types serialized at build-time only primitive entries are stored.
122
- */
123
- private ParserConstantPool buildParserConstantPool () {
124
- int length = entries .size ();
125
-
126
- byte [] byteTags = new byte [length ];
127
- for (int i = 0 ; i < length ; ++i ) {
128
- Tag tag = tags .get (i );
129
- if (tag == null ) {
130
- tag = Tag .INVALID ;
131
- }
132
- byteTags [i ] = tag .getValue ();
133
- }
134
-
135
- int [] primitiveEntries = new int [length ];
136
- for (int i = 0 ; i < length ; ++i ) {
137
- Tag tag = tags .get (i );
138
- if (tag == null ) {
139
- continue ;
140
- }
141
- switch (tag ) {
142
- case INTEGER -> {
143
- int intValue = ((PrimitiveConstant ) entries .get (i )).asInt ();
144
- primitiveEntries [i ] = intValue ;
145
- }
146
- case FLOAT -> {
147
- float floatValue = ((PrimitiveConstant ) entries .get (i )).asFloat ();
148
- primitiveEntries [i ] = Float .floatToRawIntBits (floatValue );
149
- }
150
- case DOUBLE -> {
151
- double doubleValue = ((PrimitiveConstant ) entries .get (i )).asDouble ();
152
- long doubleBits = Double .doubleToRawLongBits (doubleValue );
153
- primitiveEntries [i ] = (int ) (doubleBits >> 32 );
154
- primitiveEntries [i + 1 ] = (int ) (doubleBits & 0xFFFFFFFFL );
155
- }
156
- case LONG -> {
157
- long longValue = ((PrimitiveConstant ) entries .get (i )).asLong ();
158
- primitiveEntries [i ] = (int ) (longValue >> 32 );
159
- primitiveEntries [i + 1 ] = (int ) (longValue & 0xFFFFFFFFL );
160
- }
161
- }
162
- }
163
-
164
- // TODO(peterssen): GR-68564 Obtain proper major/minor version for this type.
165
- return new ParserConstantPool (byteTags , primitiveEntries , Symbol .EMPTY_ARRAY , ClassFile .MAJOR_VERSION , ClassFile .MINOR_VERSION );
166
- }
167
-
168
- private int appendConstant (Tag tag , Object value ) {
169
- assert entries .size () == tags .size ();
170
- entries .add (value );
171
- tags .add (tag );
172
- return entries .size () - 1 ;
173
- }
174
-
175
- BuildTimeConstantPool (InterpreterResolvedObjectType holder ) {
176
- this .holder = holder ;
177
- this .entries = new ArrayList <>(32 );
178
- this .tags = new ArrayList <>(32 );
179
- appendConstant (Tag .INVALID , null ); // index 0 always contains illegal entry
180
- this .constantCPI = new HashMap <>();
181
- this .fieldCPI = new HashMap <>();
182
- this .typeCPI = new HashMap <>();
183
- this .methodCPI = new HashMap <>();
184
- this .appendixCPI = new HashMap <>();
101
+ return poolBuilder .build ();
185
102
}
186
103
187
- public int length () {
188
- return entries .size ();
104
+ private BuildTimeConstantPool (InterpreterResolvedObjectType holder , int majorVersion , int minorVersion ) {
105
+ this .poolBuilder = new ConstantPoolBuilder (holder , majorVersion , minorVersion );
106
+ // index 0 always contains an invalid entry
107
+ int invalidIndex = this .poolBuilder .appendInvalid ();
108
+ assert invalidIndex == 0 ;
189
109
}
190
110
191
111
public int longConstant (long value ) {
192
- return constantCPI .computeIfAbsent (value , key -> {
193
- JavaConstant javaConstant = BuildTimeInterpreterUniverse .singleton ().primitiveConstant (value );
194
- int cpi = appendConstant (Tag .LONG , javaConstant );
195
- appendConstant (Tag .INVALID , null );
196
- return cpi ;
197
- });
112
+ PrimitiveConstant primitiveConstant = BuildTimeInterpreterUniverse .singleton ().primitiveConstant (value );
113
+ return poolBuilder .appendPrimitiveConstant (primitiveConstant );
198
114
}
199
115
200
116
public int intConstant (int value ) {
201
- return constantCPI .computeIfAbsent (value , key -> {
202
- JavaConstant javaConstant = BuildTimeInterpreterUniverse .singleton ().primitiveConstant (value );
203
- return appendConstant (Tag .INTEGER , javaConstant );
204
- });
117
+ PrimitiveConstant primitiveConstant = BuildTimeInterpreterUniverse .singleton ().primitiveConstant (value );
118
+ return poolBuilder .appendPrimitiveConstant (primitiveConstant );
205
119
}
206
120
207
121
public int floatConstant (float value ) {
208
- return constantCPI .computeIfAbsent (value , key -> {
209
- JavaConstant javaConstant = BuildTimeInterpreterUniverse .singleton ().primitiveConstant (value );
210
- return appendConstant (Tag .FLOAT , javaConstant );
211
- });
122
+ PrimitiveConstant primitiveConstant = BuildTimeInterpreterUniverse .singleton ().primitiveConstant (value );
123
+ return poolBuilder .appendPrimitiveConstant (primitiveConstant );
212
124
}
213
125
214
126
public int doubleConstant (double value ) {
215
- return constantCPI .computeIfAbsent (value , key -> {
216
- JavaConstant javaConstant = BuildTimeInterpreterUniverse .singleton ().primitiveConstant (value );
217
- int cpi = appendConstant (Tag .DOUBLE , javaConstant );
218
- appendConstant (Tag .INVALID , null );
219
- return cpi ;
220
- });
127
+ PrimitiveConstant primitiveConstant = BuildTimeInterpreterUniverse .singleton ().primitiveConstant (value );
128
+ return poolBuilder .appendPrimitiveConstant (primitiveConstant );
221
129
}
222
130
223
131
public int stringConstant (String value ) {
224
- return constantCPI .computeIfAbsent (value , key -> {
225
- JavaConstant javaConstant = BuildTimeInterpreterUniverse .singleton ().stringConstant (value );
226
- return appendConstant (Tag .STRING , javaConstant );
227
- });
132
+ String string = BuildTimeInterpreterUniverse .singleton ().stringConstant (value );
133
+ return poolBuilder .appendCachedString (string );
228
134
}
229
135
230
136
public int typeConstant (JavaType type ) {
231
137
if (!(type instanceof InterpreterResolvedJavaType || type instanceof UnresolvedJavaType )) {
232
138
throw new IllegalArgumentException ("Type must be either InterpreterResolvedJavaType or UnresolvedJavaType" );
233
139
}
234
- return typeCPI .computeIfAbsent (type , key -> {
235
- return appendConstant (Tag .CLASS , type );
236
- });
140
+ return poolBuilder .appendCachedType (type );
237
141
}
238
142
239
143
public int method (JavaMethod method ) {
240
144
if (!(method instanceof InterpreterResolvedJavaMethod || method instanceof UnresolvedJavaMethod )) {
241
145
throw new IllegalArgumentException ("Type must be either InterpreterResolvedJavaMethod or UnresolvedJavaMethod" );
242
146
}
243
- return methodCPI .computeIfAbsent (method , (key ) -> {
244
- return appendConstant (Tag .METHOD_REF , method );
245
- });
147
+ return poolBuilder .appendCachedMethod (false , method );
246
148
}
247
149
248
150
public int field (JavaField field ) {
249
151
if (!(field instanceof InterpreterResolvedJavaField || field instanceof UnresolvedJavaField )) {
250
152
throw new IllegalArgumentException ("Type must be either InterpreterResolvedJavaField or UnresolvedJavaField" );
251
153
}
252
- return fieldCPI .computeIfAbsent (field , (key ) -> {
253
- return appendConstant (Tag .FIELD_REF , field );
254
- });
154
+ return poolBuilder .appendCachedField (field );
255
155
}
256
156
257
157
private int appendixConstant (JavaConstant appendix ) {
258
158
assert appendix instanceof ReferenceConstant || appendix .isNull ();
259
- return appendixCPI .computeIfAbsent (appendix , key -> {
260
- return appendConstant (Tag .INVOKEDYNAMIC , appendix );
261
- });
159
+ return poolBuilder .appendCachedAppendix (appendix );
262
160
}
263
161
264
162
public int weakObjectConstant (ImageHeapConstant imageHeapConstant ) {
265
- return constantCPI .computeIfAbsent (imageHeapConstant , key -> {
266
- JavaConstant javaConstant = BuildTimeInterpreterUniverse .singleton ().weakObjectConstant (imageHeapConstant );
267
- // Can't put arbitrary objects on the CP, (ab)used INVOKEDYNAMIC tag as a workaround.
268
- return appendConstant (Tag .INVOKEDYNAMIC , javaConstant );
269
- });
163
+ JavaConstant javaConstant = BuildTimeInterpreterUniverse .singleton ().weakObjectConstant (imageHeapConstant );
164
+ // Can't put arbitrary objects on the CP, (ab)used INVOKEDYNAMIC tag as a workaround.
165
+ return poolBuilder .appendCachedAppendix (javaConstant );
270
166
}
271
167
272
168
private int ldcConstant (Object javaConstantOrType ) {
@@ -292,8 +188,8 @@ private int ldcConstant(Object javaConstantOrType) {
292
188
throw VMError .shouldNotReachHereUnexpectedInput (javaConstantOrType );
293
189
}
294
190
295
- public static BuildTimeConstantPool create (InterpreterResolvedObjectType type ) {
296
- BuildTimeConstantPool btcp = new BuildTimeConstantPool (type );
191
+ public static BuildTimeConstantPool create (InterpreterResolvedObjectType type , int majorVersion , int minorVersion ) {
192
+ BuildTimeConstantPool btcp = new BuildTimeConstantPool (type , majorVersion , minorVersion );
297
193
btcp .hydrate (type );
298
194
return btcp ;
299
195
}
0 commit comments