Skip to content

Commit 38d2cca

Browse files
committed
Adopt ConstantPoolBuilder.
1 parent 23f5cb7 commit 38d2cca

File tree

3 files changed

+301
-139
lines changed

3 files changed

+301
-139
lines changed

substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/BuildTimeConstantPool.java

Lines changed: 27 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,7 @@
4242
import static com.oracle.svm.interpreter.metadata.Bytecodes.PUTFIELD;
4343
import static com.oracle.svm.interpreter.metadata.Bytecodes.PUTSTATIC;
4444

45-
import java.util.ArrayList;
46-
import java.util.HashMap;
4745
import java.util.List;
48-
import java.util.Map;
4946

5047
import org.graalvm.nativeimage.Platform;
5148
import org.graalvm.nativeimage.Platforms;
@@ -56,12 +53,9 @@
5653
import com.oracle.svm.core.meta.MethodPointer;
5754
import com.oracle.svm.core.util.UserError;
5855
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;
6256
import com.oracle.svm.hosted.meta.HostedMethod;
6357
import com.oracle.svm.hosted.meta.HostedUniverse;
64-
import com.oracle.svm.interpreter.classfile.ClassFile;
58+
import com.oracle.svm.interpreter.constantpool.ConstantPoolBuilder;
6559
import com.oracle.svm.interpreter.metadata.BytecodeStream;
6660
import com.oracle.svm.interpreter.metadata.Bytecodes;
6761
import com.oracle.svm.interpreter.metadata.InterpreterConstantPool;
@@ -97,176 +91,78 @@ final class BuildTimeConstantPool {
9791

9892
private static final ExceptionHandler[] EMPTY_EXCEPTION_HANDLERS = new ExceptionHandler[0];
9993

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;
11095

11196
/**
11297
* Creates runtime-ready constant pool for the interpreter.
11398
*/
11499
public InterpreterConstantPool snapshot() {
115100
// 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();
185102
}
186103

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;
189109
}
190110

191111
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);
198114
}
199115

200116
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);
205119
}
206120

207121
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);
212124
}
213125

214126
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);
221129
}
222130

223131
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);
228134
}
229135

230136
public int typeConstant(JavaType type) {
231137
if (!(type instanceof InterpreterResolvedJavaType || type instanceof UnresolvedJavaType)) {
232138
throw new IllegalArgumentException("Type must be either InterpreterResolvedJavaType or UnresolvedJavaType");
233139
}
234-
return typeCPI.computeIfAbsent(type, key -> {
235-
return appendConstant(Tag.CLASS, type);
236-
});
140+
return poolBuilder.appendCachedType(type);
237141
}
238142

239143
public int method(JavaMethod method) {
240144
if (!(method instanceof InterpreterResolvedJavaMethod || method instanceof UnresolvedJavaMethod)) {
241145
throw new IllegalArgumentException("Type must be either InterpreterResolvedJavaMethod or UnresolvedJavaMethod");
242146
}
243-
return methodCPI.computeIfAbsent(method, (key) -> {
244-
return appendConstant(Tag.METHOD_REF, method);
245-
});
147+
return poolBuilder.appendCachedMethod(false, method);
246148
}
247149

248150
public int field(JavaField field) {
249151
if (!(field instanceof InterpreterResolvedJavaField || field instanceof UnresolvedJavaField)) {
250152
throw new IllegalArgumentException("Type must be either InterpreterResolvedJavaField or UnresolvedJavaField");
251153
}
252-
return fieldCPI.computeIfAbsent(field, (key) -> {
253-
return appendConstant(Tag.FIELD_REF, field);
254-
});
154+
return poolBuilder.appendCachedField(field);
255155
}
256156

257157
private int appendixConstant(JavaConstant appendix) {
258158
assert appendix instanceof ReferenceConstant || appendix.isNull();
259-
return appendixCPI.computeIfAbsent(appendix, key -> {
260-
return appendConstant(Tag.INVOKEDYNAMIC, appendix);
261-
});
159+
return poolBuilder.appendCachedAppendix(appendix);
262160
}
263161

264162
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);
270166
}
271167

272168
private int ldcConstant(Object javaConstantOrType) {
@@ -292,8 +188,8 @@ private int ldcConstant(Object javaConstantOrType) {
292188
throw VMError.shouldNotReachHereUnexpectedInput(javaConstantOrType);
293189
}
294190

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);
297193
btcp.hydrate(type);
298194
return btcp;
299195
}

substratevm/src/com.oracle.svm.interpreter/src/com/oracle/svm/interpreter/BuildTimeInterpreterUniverse.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import java.util.function.Function;
4444
import java.util.stream.Collectors;
4545

46+
import com.oracle.svm.interpreter.classfile.ClassFile;
4647
import org.graalvm.nativeimage.Platform;
4748
import org.graalvm.nativeimage.Platforms;
4849

@@ -121,7 +122,7 @@ public static void freshSingletonInstance() {
121122
private final Map<ResolvedJavaMethod, InterpreterResolvedJavaMethod> methods;
122123
private final Map<String, InterpreterUnresolvedSignature> signatures;
123124
private final Map<Number, PrimitiveConstant> primitiveConstants;
124-
private final Map<String, ReferenceConstant<String>> strings;
125+
private final Map<String, String> strings;
125126
private final Map<ImageHeapConstant, ReferenceConstant<?>> objectConstants;
126127

127128
private final Map<ExceptionHandler, ExceptionHandler> exceptionHandlers;
@@ -567,24 +568,24 @@ public JavaConstant weakObjectConstant(ImageHeapConstant imageHeapConstant) {
567568
return objectConstants.computeIfAbsent(imageHeapConstant, (key) -> ReferenceConstant.createFromImageHeapConstant(imageHeapConstant));
568569
}
569570

570-
public JavaConstant primitiveConstant(int value) {
571+
public PrimitiveConstant primitiveConstant(int value) {
571572
return primitiveConstants.computeIfAbsent(value, (key) -> JavaConstant.forInt(value));
572573
}
573574

574-
public JavaConstant primitiveConstant(long value) {
575+
public PrimitiveConstant primitiveConstant(long value) {
575576
return primitiveConstants.computeIfAbsent(value, (key) -> JavaConstant.forLong(value));
576577
}
577578

578-
public JavaConstant primitiveConstant(float value) {
579+
public PrimitiveConstant primitiveConstant(float value) {
579580
return primitiveConstants.computeIfAbsent(value, (key) -> JavaConstant.forFloat(value));
580581
}
581582

582-
public JavaConstant primitiveConstant(double value) {
583+
public PrimitiveConstant primitiveConstant(double value) {
583584
return primitiveConstants.computeIfAbsent(value, (key) -> JavaConstant.forDouble(value));
584585
}
585586

586-
public JavaConstant stringConstant(String value) {
587-
return strings.computeIfAbsent(value, (key) -> ReferenceConstant.createFromNonNullReference(Objects.requireNonNull(value)));
587+
public String stringConstant(String value) {
588+
return strings.computeIfAbsent(value, Function.identity());
588589
}
589590

590591
public JavaType primitiveOrUnresolvedType(JavaType type) {
@@ -693,7 +694,8 @@ public void createConstantPools(HostedUniverse hUniverse) {
693694

694695
for (InterpreterResolvedJavaType type : types.values()) {
695696
if (type instanceof InterpreterResolvedObjectType referenceType) {
696-
BuildTimeConstantPool buildTimeConstantPool = BuildTimeConstantPool.create(referenceType);
697+
// TODO(peterssen): GR-68564 Obtain proper major/minor version for this type.
698+
BuildTimeConstantPool buildTimeConstantPool = BuildTimeConstantPool.create(referenceType, ClassFile.MAJOR_VERSION, ClassFile.MINOR_VERSION);
697699
referenceType.setConstantPool(buildTimeConstantPool.snapshot());
698700
}
699701
}

0 commit comments

Comments
 (0)