Skip to content

Commit baaf81c

Browse files
committed
[GR-70903] Migrate DebuggerFeature from core reflection to JVMCI
PullRequest: graal/22419
2 parents b4916b7 + 032309d commit baaf81c

File tree

7 files changed

+284
-73
lines changed

7 files changed

+284
-73
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,10 @@ public void rescanRoot(Field reflectionField, ScanReason rescanReason) {
703703
});
704704
}
705705

706+
public void rescanField(Object receiver, Field reflectionField, ScanReason reason) {
707+
rescanField(receiver, metaAccess.lookupJavaField(reflectionField), reason);
708+
}
709+
706710
/**
707711
* Trigger rescanning of an instance field. If the receiver value or field value were not
708712
* scanned before they will first be scanned and added to the shadow heap, then the value will
@@ -711,11 +715,10 @@ public void rescanRoot(Field reflectionField, ScanReason rescanReason) {
711715
* type ({@code Object[]}, {{@link Collection}, {@link Map} or {@link EconomicMap}} then its
712716
* elements will be rescanned too.
713717
*/
714-
public void rescanField(Object receiver, Field reflectionField, ScanReason reason) {
718+
public void rescanField(Object receiver, AnalysisField field, ScanReason reason) {
715719
maybeRunInExecutor(unused -> {
716-
AnalysisType type = metaAccess.lookupJavaType(reflectionField.getDeclaringClass());
720+
AnalysisType type = field.getType();
717721
if (type.isReachable()) {
718-
AnalysisField field = metaAccess.lookupJavaField(reflectionField);
719722
assert !field.isStatic() : field;
720723
if (!field.isReachable()) {
721724
return;

substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/macho/MachORelocationElement.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@
3030
import java.util.Set;
3131
import java.util.TreeMap;
3232

33-
import jdk.graal.compiler.core.common.NumUtil;
34-
3533
import com.oracle.objectfile.BuildDependency;
3634
import com.oracle.objectfile.LayoutDecisionMap;
3735
import com.oracle.objectfile.ObjectFile;
@@ -45,6 +43,8 @@
4543
import com.oracle.objectfile.io.OutputAssembler;
4644
import com.oracle.objectfile.macho.MachOObjectFile.MachOSection;
4745
import com.oracle.objectfile.macho.MachOObjectFile.Segment64Command;
46+
47+
import jdk.graal.compiler.core.common.NumUtil;
4848
import jdk.graal.compiler.debug.GraalError;
4949

5050
class MachORelocationElement extends MachOObjectFile.LinkEditElement {
@@ -268,7 +268,9 @@ private MachORelocationInfo(MachORelocationElement containingElement, MachOSecti
268268
// FIXME: also allow section numbers here, for non-extern symbols
269269
// FIXME: encode R_ABS symbol number
270270
this.sym = symtab.getSymbol(symbolName);
271-
assert this.sym != null : "could not find symbol " + symbolName;
271+
if (this.sym == null) {
272+
throw new IllegalArgumentException("Could not find symbol " + symbolName);
273+
}
272274
// if the symbol is defined in the same file, i.e. locally, we have a target section
273275
assert !asLocalReloc || this.sym.isDefined();
274276
this.targetSection = asLocalReloc ? (MachOSection) this.sym.getDefinedSection() : null;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@
4343
import com.oracle.svm.core.graal.meta.SubstrateRegisterConfig;
4444
import com.oracle.svm.core.util.VMError;
4545
import com.oracle.svm.hosted.image.NativeImage;
46+
import com.oracle.svm.hosted.meta.HostedMethod;
4647
import com.oracle.svm.interpreter.metadata.InterpreterResolvedJavaMethod;
4748

4849
import jdk.graal.compiler.asm.Assembler;
4950
import jdk.graal.compiler.asm.Label;
5051
import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler;
5152
import jdk.graal.compiler.core.common.LIRKind;
5253
import jdk.vm.ci.code.Register;
53-
import jdk.vm.ci.meta.ResolvedJavaMethod;
5454

5555
public class AArch64InterpreterStubSection extends InterpreterStubSection {
5656
public AArch64InterpreterStubSection() {
@@ -159,7 +159,7 @@ private void recordEnterStubForPatching(Assembler.CodeAnnotation a) {
159159

160160
@Platforms(Platform.HOSTED_ONLY.class)
161161
@Override
162-
protected void markEnterStubPatch(ObjectFile.ProgbitsSectionImpl pltBuffer, ResolvedJavaMethod enterStub) {
162+
protected void markEnterStubPatch(ObjectFile.ProgbitsSectionImpl pltBuffer, HostedMethod enterStub) {
163163
pltBuffer.markRelocationSite(resolverPatchOffset, AARCH64_R_AARCH64_ADR_PREL_PG_HI21, NativeImage.localSymbolNameForMethod(enterStub), 0);
164164
pltBuffer.markRelocationSite(resolverPatchOffset + 4, AARCH64_R_AARCH64_ADD_ABS_LO12_NC, NativeImage.localSymbolNameForMethod(enterStub), 0);
165165
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import com.oracle.svm.core.graal.meta.SubstrateRegisterConfig;
4141
import com.oracle.svm.core.util.VMError;
4242
import com.oracle.svm.hosted.image.NativeImage;
43+
import com.oracle.svm.hosted.meta.HostedMethod;
4344
import com.oracle.svm.interpreter.metadata.InterpreterResolvedJavaMethod;
4445

4546
import jdk.graal.compiler.asm.Assembler;
@@ -48,7 +49,6 @@
4849
import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler;
4950
import jdk.graal.compiler.core.common.LIRKind;
5051
import jdk.graal.compiler.core.common.NumUtil;
51-
import jdk.vm.ci.meta.ResolvedJavaMethod;
5252

5353
public class AMD64InterpreterStubSection extends InterpreterStubSection {
5454
public AMD64InterpreterStubSection() {
@@ -144,7 +144,7 @@ private void recordEnterStubForPatching(Assembler.CodeAnnotation a) {
144144

145145
@Platforms(Platform.HOSTED_ONLY.class)
146146
@Override
147-
protected void markEnterStubPatch(ObjectFile.ProgbitsSectionImpl pltBuffer, ResolvedJavaMethod enterStub) {
147+
protected void markEnterStubPatch(ObjectFile.ProgbitsSectionImpl pltBuffer, HostedMethod enterStub) {
148148
pltBuffer.markRelocationSite(resolverPatchOffset, resolverPatchRelocationKind, NativeImage.localSymbolNameForMethod(enterStub), resolverKindAddend);
149149
}
150150
}

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

Lines changed: 53 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,6 @@
3636
import static com.oracle.svm.interpreter.metadata.InterpreterUniverseImpl.toHexString;
3737

3838
import java.io.IOException;
39-
import java.lang.reflect.Constructor;
40-
import java.lang.reflect.Field;
41-
import java.lang.reflect.Method;
4239
import java.lang.reflect.Modifier;
4340
import java.nio.charset.StandardCharsets;
4441
import java.nio.file.FileSystems;
@@ -67,8 +64,8 @@
6764
import com.oracle.graal.pointsto.ObjectScanner.ScanReason;
6865
import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException;
6966
import com.oracle.graal.pointsto.heap.ImageHeapConstant;
70-
import com.oracle.svm.util.OriginalClassProvider;
7167
import com.oracle.graal.pointsto.meta.AnalysisField;
68+
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
7269
import com.oracle.graal.pointsto.meta.AnalysisMethod;
7370
import com.oracle.graal.pointsto.meta.AnalysisType;
7471
import com.oracle.svm.core.BuildArtifacts;
@@ -111,7 +108,7 @@
111108
import com.oracle.svm.interpreter.metadata.ReferenceConstant;
112109
import com.oracle.svm.interpreter.metadata.serialization.SerializationContext;
113110
import com.oracle.svm.interpreter.metadata.serialization.Serializers;
114-
import com.oracle.svm.util.ReflectionUtil;
111+
import com.oracle.svm.util.JVMCIReflectionUtil;
115112

116113
import jdk.graal.compiler.api.replacements.SnippetReflectionProvider;
117114
import jdk.graal.compiler.core.common.SuppressFBWarnings;
@@ -130,6 +127,7 @@
130127
import jdk.vm.ci.meta.PrimitiveConstant;
131128
import jdk.vm.ci.meta.ResolvedJavaField;
132129
import jdk.vm.ci.meta.ResolvedJavaMethod;
130+
import jdk.vm.ci.meta.ResolvedJavaType;
133131
import jdk.vm.ci.meta.UnresolvedJavaMethod;
134132

135133
/**
@@ -144,9 +142,9 @@
144142
@Platforms(Platform.HOSTED_ONLY.class)
145143
@AutomaticallyRegisteredFeature
146144
public class DebuggerFeature implements InternalFeature {
147-
private Method enterInterpreterMethod;
145+
private AnalysisMethod enterInterpreterMethod;
148146
private InterpreterStubTable enterStubTable = null;
149-
private final List<Class<?>> classesUsedByInterpreter = new ArrayList<>();
147+
private final List<ResolvedJavaType> classesUsedByInterpreter = new ArrayList<>();
150148
private Set<AnalysisMethod> methodsProcessedDuringAnalysis;
151149
private InvocationPlugins invocationPlugins;
152150
private static final String SYNTHETIC_ASSERTIONS_DISABLED_FIELD_NAME = "$assertionsDisabled";
@@ -165,9 +163,9 @@ public List<Class<? extends Feature>> getRequiredFeatures() {
165163
SymbolsFeature.class);
166164
}
167165

168-
private static Class<?> getArgumentClass(GraphBuilderContext b, ResolvedJavaMethod targetMethod, int parameterIndex, ValueNode arg) {
166+
private static ResolvedJavaType getArgumentType(GraphBuilderContext b, ResolvedJavaMethod targetMethod, int parameterIndex, ValueNode arg) {
169167
SubstrateGraphBuilderPlugins.checkParameterUsage(arg.isConstant(), b, targetMethod, parameterIndex, "parameter is not a compile time constant");
170-
return OriginalClassProvider.getJavaClass(b.getConstantReflection().asJavaType(arg.asJavaConstant()));
168+
return b.getConstantReflection().asJavaType(arg.asJavaConstant());
171169
}
172170

173171
@Override
@@ -178,9 +176,9 @@ public void registerInvocationPlugins(Providers providers, GraphBuilderConfigura
178176
r.register(new InvocationPlugin.RequiredInvocationPlugin("markKlass", Class.class) {
179177
@Override
180178
public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg1) {
181-
Class<?> targetKlass = getArgumentClass(b, targetMethod, 1, arg1);
182-
InterpreterUtil.log("[invocation plugin] Adding %s", targetKlass);
183-
classesUsedByInterpreter.add(targetKlass);
179+
ResolvedJavaType targetType = getArgumentType(b, targetMethod, 1, arg1);
180+
InterpreterUtil.log("[invocation plugin] Adding %s", targetType.getUnqualifiedName());
181+
classesUsedByInterpreter.add(targetType);
184182

185183
/* no-op in compiled code */
186184
return true;
@@ -198,33 +196,32 @@ public void afterRegistration(AfterRegistrationAccess access) {
198196
@Override
199197
public void beforeAnalysis(BeforeAnalysisAccess access) {
200198
FeatureImpl.BeforeAnalysisAccessImpl accessImpl = (FeatureImpl.BeforeAnalysisAccessImpl) access;
199+
AnalysisMetaAccess metaAccess = accessImpl.getMetaAccess();
201200

202-
try {
203-
enterInterpreterMethod = InterpreterStubSection.class.getMethod("enterMethodInterpreterStub", int.class, Pointer.class);
204-
accessImpl.registerAsRoot(enterInterpreterMethod, true, "stub for interpreter");
201+
AnalysisType aInterpreterStubSection = metaAccess.lookupJavaType(InterpreterStubSection.class);
202+
enterInterpreterMethod = (AnalysisMethod) JVMCIReflectionUtil.getDeclaredMethod(metaAccess, aInterpreterStubSection, "enterMethodInterpreterStub", int.class, Pointer.class);
203+
accessImpl.registerAsRoot(enterInterpreterMethod, true, "stub for interpreter");
205204

206-
// Holds references that must be kept alive in the image heap.
207-
access.registerAsAccessed(DebuggerSupport.class.getDeclaredField("referencesInImage"));
208-
access.registerAsAccessed(DebuggerSupport.class.getDeclaredField("methodPointersInImage"));
205+
// Holds references that must be kept alive in the image heap.
206+
AnalysisType aDebuggerSupport = metaAccess.lookupJavaType(DebuggerSupport.class);
207+
accessImpl.registerAsAccessed((AnalysisField) JVMCIReflectionUtil.getDeclaredField(aDebuggerSupport, "referencesInImage"),
208+
"Holds references that must be kept alive in the image heap.");
209+
accessImpl.registerAsAccessed((AnalysisField) JVMCIReflectionUtil.getDeclaredField(aDebuggerSupport, "methodPointersInImage"),
210+
"Holds references that must be kept alive in the image heap.");
209211

210-
accessImpl.registerAsRoot(System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class), true,
211-
"Allow interpreting methods that call System.arraycopy");
212-
} catch (NoSuchMethodException | NoSuchFieldException e) {
213-
throw VMError.shouldNotReachHere(e);
214-
}
212+
AnalysisType aSystem = metaAccess.lookupJavaType(System.class);
213+
accessImpl.registerAsRoot((AnalysisMethod) JVMCIReflectionUtil.getDeclaredMethod(metaAccess, aSystem, "arraycopy", Object.class, int.class, Object.class, int.class, int.class),
214+
true, "Allow interpreting methods that call System.arraycopy");
215215

216216
registerStringConcatenation(accessImpl);
217217

218218
// GR-53734: Known issues around reachability
219-
try {
220-
// JDK code introduced a new optional intrinsic:
221-
// https://github.com/openjdk/jdk22u/commit/a4e9168bab1c2872ce2dbc7971a45c259270271f
222-
// consider DualPivotQuicksort.java:268, int.class is not needed if the sort helper
223-
// is inlined, therefore it's not needed. Still needed for interpreter execution.
224-
access.registerAsAccessed(Integer.class.getField("TYPE"));
225-
} catch (NoSuchFieldException e) {
226-
throw VMError.shouldNotReachHere(e);
227-
}
219+
// JDK code introduced a new optional intrinsic:
220+
// https://github.com/openjdk/jdk22u/commit/a4e9168bab1c2872ce2dbc7971a45c259270271f
221+
// consider DualPivotQuicksort.java:268, int.class is not needed if the sort helper
222+
// is inlined, therefore it's not needed. Still needed for interpreter execution.
223+
AnalysisType aInteger = metaAccess.lookupJavaType(Integer.class);
224+
accessImpl.registerAsAccessed((AnalysisField) JVMCIReflectionUtil.getDeclaredField(aInteger, "TYPE"), "Read by the interpreter");
228225

229226
methodsProcessedDuringAnalysis = new HashSet<>();
230227

@@ -247,20 +244,18 @@ private static void registerStringConcatenation(FeatureImpl.BeforeAnalysisAccess
247244
* These registrations enable the interpreter to "interpret" StringBuilder-based String
248245
* concatenation optimized away by the compiler.
249246
*/
250-
try {
251-
List<Method> appendMethods = Arrays.stream(StringBuilder.class.getDeclaredMethods())
252-
.filter(m -> "append".equals(m.getName()))
253-
.collect(Collectors.toList());
254-
for (Method m : appendMethods) {
255-
accessImpl.registerAsRoot(m, false, "string concat in interpreter");
256-
}
257-
for (Constructor<?> c : StringBuilder.class.getDeclaredConstructors()) {
258-
accessImpl.registerAsRoot(c, true, "string concat in interpreter");
259-
}
260-
accessImpl.registerAsRoot(StringBuilder.class.getConstructor(), true, "string concat in interpreter");
261-
} catch (NoSuchMethodException e) {
262-
throw new RuntimeException(e);
247+
AnalysisMetaAccess metaAccess = accessImpl.getMetaAccess();
248+
AnalysisType aStringBuilder = metaAccess.lookupJavaType(StringBuilder.class);
249+
List<AnalysisMethod> appendMethods = Arrays.stream(aStringBuilder.getDeclaredMethods(false))
250+
.filter(m -> "append".equals(m.getName())).toList();
251+
for (AnalysisMethod m : appendMethods) {
252+
accessImpl.registerAsRoot(m, false, "string concat in interpreter");
253+
}
254+
for (AnalysisMethod c : aStringBuilder.getDeclaredConstructors(false)) {
255+
accessImpl.registerAsRoot(c, true, "string concat in interpreter");
263256
}
257+
AnalysisMethod aMethod = (AnalysisMethod) JVMCIReflectionUtil.getDeclaredConstructor(metaAccess, aStringBuilder);
258+
accessImpl.registerAsRoot(aMethod, true, "string concat in interpreter");
264259
}
265260

266261
static boolean isReachable(AnalysisMethod m) {
@@ -299,13 +294,13 @@ public void duringAnalysis(DuringAnalysisAccess access) {
299294

300295
if (!classesUsedByInterpreter.isEmpty()) {
301296
access.requireAnalysisIteration();
302-
for (Class<?> k : classesUsedByInterpreter) {
303-
accessImpl.registerAsUsed(k);
304-
Arrays.stream(k.getDeclaredMethods()).filter(m -> m.getName().startsWith("test")).forEach(m -> {
305-
AnalysisMethod aMethod = accessImpl.getMetaAccess().lookupJavaMethod(m);
297+
for (ResolvedJavaType k : classesUsedByInterpreter) {
298+
AnalysisType aType = k instanceof AnalysisType analysisType ? analysisType : accessImpl.getUniverse().lookup(k);
299+
accessImpl.registerAsUsed(aType, "used by interpreter");
300+
Arrays.stream(aType.getDeclaredMethods(false)).filter(m -> m.getName().startsWith("test")).forEach(aMethod -> {
306301
VMError.guarantee(!aMethod.isConstructor());
307302
accessImpl.registerAsRoot(aMethod, aMethod.isConstructor(), "reached due to interpreter directive");
308-
InterpreterUtil.log("[during analysis] Adding method %s", m);
303+
InterpreterUtil.log("[during analysis] Adding method %s", aMethod);
309304
});
310305
}
311306
classesUsedByInterpreter.clear();
@@ -440,7 +435,7 @@ public void beforeCompilation(BeforeCompilationAccess access) {
440435
FeatureImpl.BeforeCompilationAccessImpl accessImpl = (FeatureImpl.BeforeCompilationAccessImpl) access;
441436
HostedUniverse hUniverse = accessImpl.getUniverse();
442437
HostedMetaAccess hMetaAccess = accessImpl.getMetaAccess();
443-
MetaAccessProvider aMetaAccess = hMetaAccess.getWrapped();
438+
AnalysisMetaAccess aMetaAccess = (AnalysisMetaAccess) hMetaAccess.getWrapped();
444439
BuildTimeInterpreterUniverse iUniverse = BuildTimeInterpreterUniverse.singleton();
445440

446441
for (HostedType hType : hUniverse.getTypes()) {
@@ -501,20 +496,18 @@ public void beforeCompilation(BeforeCompilationAccess access) {
501496

502497
iUniverse.purgeUnreachable(hMetaAccess);
503498

504-
Field vtableHolderField = ReflectionUtil.lookupField(InterpreterResolvedObjectType.class, "vtableHolder");
499+
AnalysisField vtableHolderField = (AnalysisField) JVMCIReflectionUtil.getDeclaredField(aMetaAccess.lookupJavaType(InterpreterResolvedObjectType.class), "vtableHolder");
505500
ScanReason reason = new OtherReason("Manual rescan triggered before compilation from " + DebuggerFeature.class);
506501
for (HostedType hostedType : hUniverse.getTypes()) {
507502
iUniverse.mirrorSVMVTable(hostedType, objectType -> accessImpl.getHeapScanner().rescanField(objectType, vtableHolderField, reason));
508503
}
509504

510505
// Allow methods that call System.arraycopy to be interpreted.
511-
try {
512-
HostedMethod arraycopy = hMetaAccess.lookupJavaMethod(
513-
System.class.getDeclaredMethod("arraycopy", Object.class, int.class, Object.class, int.class, int.class));
514-
SubstrateCompilationDirectives.singleton().registerForcedCompilation(arraycopy);
515-
} catch (NoSuchMethodException e) {
516-
throw new RuntimeException(e);
517-
}
506+
507+
HostedType systemClass = hMetaAccess.lookupJavaType(System.class);
508+
AnalysisMethod arraycopy = (AnalysisMethod) JVMCIReflectionUtil.getDeclaredMethod(aMetaAccess,
509+
systemClass.getWrapped(), "arraycopy", Object.class, int.class, Object.class, int.class, int.class);
510+
SubstrateCompilationDirectives.singleton().registerForcedCompilation(arraycopy);
518511
}
519512

520513
@Override
@@ -768,7 +761,7 @@ public void beforeImageWrite(BeforeImageWriteAccess access) {
768761

769762
InterpreterStubSection stubSection = ImageSingletons.lookup(InterpreterStubSection.class);
770763

771-
stubSection.markEnterStubPatch(accessImpl.getHostedMetaAccess().lookupJavaMethod(enterInterpreterMethod));
764+
stubSection.markEnterStubPatch(accessImpl.getHostedUniverse().lookup(enterInterpreterMethod));
772765
enterStubTable.writeMetadataHashString(hashString.getBytes(StandardCharsets.UTF_8));
773766
}
774767

0 commit comments

Comments
 (0)