Skip to content

Commit 0b843a9

Browse files
committed
[GR-61460] Reload PolymorphicSignature methods
PullRequest: graal/19970
2 parents a1a7f6f + 9ffe380 commit 0b843a9

File tree

7 files changed

+216
-13
lines changed

7 files changed

+216
-13
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/MethodHandlePlugin.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,14 @@ protected MacroInvokable createMethodHandleNode(GraphBuilderContext b, ResolvedJ
6565
return new MethodHandleNode(intrinsicMethod, MacroNode.MacroParams.of(invokeKind, b.getMethod(), method, b.bci(), invokeReturnStamp, args));
6666
}
6767

68+
/**
69+
* Hook to add custom code on creation of MethodHandleNodes.
70+
*/
71+
@SuppressWarnings("unused")
72+
protected void onCreateHook(MacroInvokable methodHandleNode, GraphBuilderContext b) {
73+
/* Nothing to do here */
74+
}
75+
6876
@Override
6977
public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
7078
IntrinsicMethod intrinsicMethod = methodHandleAccess.lookupMethodHandleIntrinsic(method);
@@ -87,6 +95,7 @@ public <T extends ValueNode> T add(T node) {
8795
Invoke invoke = MethodHandleNode.tryResolveTargetInvoke(adder, this::createInvoke, methodHandleAccess, intrinsicMethod, method, b.bci(), invokeReturnStamp, args);
8896
if (invoke == null) {
8997
MacroInvokable methodHandleNode = createMethodHandleNode(b, method, args, intrinsicMethod, invokeKind, invokeReturnStamp);
98+
onCreateHook(methodHandleNode, b);
9099
if (invokeReturnStamp.getTrustedStamp().getStackKind() == JavaKind.Void) {
91100
b.add(methodHandleNode.asNode());
92101
} else {

substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ struct PersistedAnalysisMethod {
116116
declaringClassName @37 :Text;
117117
argumentTypeNames @38 :List(Text);
118118
}
119+
polymorphicSignature :group {
120+
callers @38 :List(MethodId);
121+
}
119122
}
120123
}
121124

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@
236236
import com.oracle.svm.hosted.meta.HostedSnippetReflectionProvider;
237237
import com.oracle.svm.hosted.meta.HostedUniverse;
238238
import com.oracle.svm.hosted.meta.UniverseBuilder;
239+
import com.oracle.svm.hosted.methodhandles.SVMMethodHandleWithExceptionPlugin;
239240
import com.oracle.svm.hosted.option.HostedOptionProvider;
240241
import com.oracle.svm.hosted.phases.CInterfaceInvocationPlugin;
241242
import com.oracle.svm.hosted.phases.ConstantFoldLoadFieldPlugin;
@@ -304,7 +305,6 @@
304305
import jdk.graal.compiler.phases.tiers.Suites;
305306
import jdk.graal.compiler.phases.util.Providers;
306307
import jdk.graal.compiler.printer.GraalDebugHandlersFactory;
307-
import jdk.graal.compiler.replacements.MethodHandleWithExceptionPlugin;
308308
import jdk.graal.compiler.replacements.NodeIntrinsificationProvider;
309309
import jdk.graal.compiler.replacements.TargetGraphBuilderPlugins;
310310
import jdk.graal.compiler.word.WordOperationPlugin;
@@ -1371,7 +1371,7 @@ public static void registerGraphBuilderPlugins(FeatureHandler featureHandler, Ru
13711371
plugins.appendInlineInvokePlugin(replacements);
13721372

13731373
if (reason.duringAnalysis()) {
1374-
plugins.appendNodePlugin(new MethodHandleWithExceptionPlugin(providers.getConstantReflection().getMethodHandleAccess(), false));
1374+
plugins.appendNodePlugin(new SVMMethodHandleWithExceptionPlugin(providers.getConstantReflection().getMethodHandleAccess(), false));
13751375
}
13761376
plugins.appendNodePlugin(new DeletedFieldsPlugin());
13771377
plugins.appendNodePlugin(new InjectedAccessorsPlugin());

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java

Lines changed: 50 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,14 @@
127127
import jdk.graal.compiler.core.common.NumUtil;
128128
import jdk.graal.compiler.core.common.SuppressFBWarnings;
129129
import jdk.graal.compiler.debug.GraalError;
130+
import jdk.graal.compiler.graph.Node;
130131
import jdk.graal.compiler.graph.iterators.NodeIterable;
131132
import jdk.graal.compiler.java.BytecodeParser;
132133
import jdk.graal.compiler.nodes.ConstantNode;
133134
import jdk.graal.compiler.nodes.EncodedGraph;
134135
import jdk.graal.compiler.nodes.StructuredGraph;
135136
import jdk.graal.compiler.options.OptionValues;
137+
import jdk.graal.compiler.replacements.nodes.MethodHandleNode;
136138
import jdk.graal.compiler.util.ObjectCopier;
137139
import jdk.internal.reflect.ReflectionFactory;
138140
import jdk.vm.ci.meta.JavaConstant;
@@ -171,6 +173,7 @@ public class SVMImageLayerLoader extends ImageLayerLoader {
171173
protected final Map<Integer, Long> objectOffsets = new ConcurrentHashMap<>();
172174
protected final Map<AnalysisField, Integer> fieldLocations = new ConcurrentHashMap<>();
173175
private final Map<Class<?>, Boolean> capturingClasses = new ConcurrentHashMap<>();
176+
private final Map<ResolvedJavaMethod, Boolean> methodHandleCallers = new ConcurrentHashMap<>();
174177

175178
/** Map from {@link SVMImageLayerSnapshotUtil#getTypeDescriptor} to base layer type ids. */
176179
private final Map<String, Integer> typeDescriptorToBaseLayerId = new HashMap<>();
@@ -399,6 +402,7 @@ protected boolean delegateLoadType(PersistedAnalysisType.Reader typeData) {
399402
String capturingClassName = wrappedType.getLambda().getCapturingClass().toString();
400403
Class<?> capturingClass = imageLayerBuildingSupport.lookupClass(false, capturingClassName);
401404
loadLambdaTypes(capturingClass);
405+
return types.containsKey(typeData.getId());
402406
} else if (wrappedType.isProxyType()) {
403407
Class<?>[] interfaces = Stream.of(typeData.getInterfaces()).flatMapToInt(r -> IntStream.range(0, r.size()).map(r::get))
404408
.mapToObj(i -> getAnalysisTypeForBaseLayerId(i).getJavaClass()).toArray(Class<?>[]::new);
@@ -425,23 +429,46 @@ private void loadLambdaTypes(Class<?> capturingClass) {
425429
}
426430

427431
private static void loadLambdaTypes(ResolvedJavaMethod m, BigBang bigBang) {
432+
StructuredGraph graph = getMethodGraph(m, bigBang);
433+
if (graph != null) {
434+
NodeIterable<ConstantNode> constantNodes = ConstantNode.getConstantNodes(graph);
435+
436+
for (ConstantNode cNode : constantNodes) {
437+
Class<?> lambdaClass = getLambdaClassFromConstantNode(cNode);
438+
439+
if (lambdaClass != null) {
440+
bigBang.getMetaAccess().lookupJavaType(lambdaClass);
441+
}
442+
}
443+
}
444+
}
445+
446+
private void loadMethodHandleTargets(ResolvedJavaMethod m, BigBang bigBang) {
447+
methodHandleCallers.computeIfAbsent(m, method -> {
448+
StructuredGraph graph = getMethodGraph(m, bigBang);
449+
if (graph != null) {
450+
for (Node node : graph.getNodes()) {
451+
if (node instanceof MethodHandleNode methodHandleNode) {
452+
bigBang.getUniverse().lookup(methodHandleNode.getTargetMethod());
453+
}
454+
}
455+
}
456+
return true;
457+
});
458+
}
459+
460+
private static StructuredGraph getMethodGraph(ResolvedJavaMethod m, BigBang bigBang) {
461+
if (m instanceof BaseLayerMethod) {
462+
return null;
463+
}
428464
StructuredGraph graph;
429465
try {
430466
graph = createMethodGraph(m, bigBang.getOptions());
431467
} catch (NoClassDefFoundError | BytecodeParser.BytecodeParserError e) {
432468
/* Skip the method if it refers to a missing class */
433-
return;
434-
}
435-
436-
NodeIterable<ConstantNode> constantNodes = ConstantNode.getConstantNodes(graph);
437-
438-
for (ConstantNode cNode : constantNodes) {
439-
Class<?> lambdaClass = getLambdaClassFromConstantNode(cNode);
440-
441-
if (lambdaClass != null) {
442-
bigBang.getMetaAccess().lookupJavaType(lambdaClass);
443-
}
469+
return null;
444470
}
471+
return graph;
445472
}
446473

447474
private ResolvedJavaType getResolvedJavaTypeForBaseLayerId(int tid) {
@@ -746,6 +773,18 @@ protected boolean delegateLoadMethod(PersistedAnalysisMethod.Reader methodData)
746773
JNIAccessFeature.singleton().addMethod(member, (FeatureImpl.DuringAnalysisAccessImpl) universe.getConcurrentAnalysisAccess());
747774
}
748775
return true;
776+
} else if (wrappedMethod.isPolymorphicSignature()) {
777+
int id = methodData.getId();
778+
WrappedMethod.PolymorphicSignature.Reader ps = wrappedMethod.getPolymorphicSignature();
779+
var callers = ps.getCallers();
780+
for (int i = 0; i < callers.size(); ++i) {
781+
loadMethodHandleTargets(getAnalysisMethodForBaseLayerId(callers.get(i)).wrapped, universe.getBigbang());
782+
if (methods.containsKey(id)) {
783+
return true;
784+
}
785+
}
786+
LogUtils.warning("The PolymorphicSignature method %s.%s could not get loaded", methodData.getClassName().toString(), methodData.getName().toString());
787+
return false;
749788
}
750789
return false;
751790
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,8 @@
151151
import com.oracle.svm.hosted.reflect.ReflectionExpandSignatureMethod;
152152
import com.oracle.svm.hosted.reflect.proxy.ProxyRenamingSubstitutionProcessor;
153153
import com.oracle.svm.hosted.reflect.proxy.ProxySubstitutionType;
154+
import com.oracle.svm.hosted.substitute.PolymorphicSignatureWrapperMethod;
155+
import com.oracle.svm.hosted.substitute.SubstitutionMethod;
154156
import com.oracle.svm.util.FileDumpingUtil;
155157
import com.oracle.svm.util.LogUtils;
156158
import com.oracle.svm.util.ModuleSupport;
@@ -181,6 +183,7 @@ public class SVMImageLayerWriter extends ImageLayerWriter {
181183
private Map<ImageHeapConstant, ConstantParent> constantsMap;
182184
private final Map<String, MethodGraphsInfo> methodsMap = new ConcurrentHashMap<>();
183185
private final Map<InitialLayerOnlyImageSingleton, Integer> initialLayerOnlySingletonMap = new ConcurrentHashMap<>();
186+
private final Map<AnalysisMethod, Set<AnalysisMethod>> polymorphicSignatureCallers = new ConcurrentHashMap<>();
184187
private FileInfo fileInfo;
185188
private GraphsOutput graphsOutput;
186189
private final boolean useSharedLayerGraphs;
@@ -189,6 +192,8 @@ public class SVMImageLayerWriter extends ImageLayerWriter {
189192
private NativeImageHeap nativeImageHeap;
190193
private HostedUniverse hUniverse;
191194

195+
private boolean polymorphicSignatureSealed = false;
196+
192197
private record ConstantParent(int constantId, int index) {
193198
static ConstantParent NONE = new ConstantParent(UNDEFINED_CONSTANT_ID, UNDEFINED_FIELD_INDEX);
194199
}
@@ -339,6 +344,8 @@ public void persistAnalysisInfo() {
339344
snapshotBuilder.setNextFieldId(aUniverse.getNextFieldId());
340345
snapshotBuilder.setNextConstantId(ImageHeapConstant.getCurrentId());
341346

347+
polymorphicSignatureSealed = true;
348+
342349
List<AnalysisType> typesToPersist = aUniverse.getTypes().stream().filter(AnalysisType::isTrackedAcrossLayers).toList();
343350
List<AnalysisMethod> methodsToPersist = aUniverse.getMethods().stream().filter(AnalysisMethod::isTrackedAcrossLayers).toList();
344351
List<AnalysisField> fieldsToPersist = aUniverse.getFields().stream().filter(AnalysisField::isTrackedAcrossLayers).toList();
@@ -603,6 +610,15 @@ protected void delegatePersistMethod(AnalysisMethod method, PersistedAnalysisMet
603610
b.setJavaCallVariantWrapper(Void.VOID);
604611
Executable executable = jniJavaCallVariantWrapperMethod.getMember();
605612
persistMethodWrappedMember(b, executable);
613+
} else if (method.wrapped instanceof SubstitutionMethod substitutionMethod && substitutionMethod.getAnnotated() instanceof PolymorphicSignatureWrapperMethod) {
614+
WrappedMethod.PolymorphicSignature.Builder b = builder.getWrappedMethod().initPolymorphicSignature();
615+
Set<AnalysisMethod> callers = polymorphicSignatureCallers.get(method);
616+
var callersBuilder = b.initCallers(callers.size());
617+
int i = 0;
618+
for (AnalysisMethod caller : callers) {
619+
callersBuilder.set(i, caller.getId());
620+
i++;
621+
}
606622
}
607623
}
608624

@@ -993,6 +1009,11 @@ private static boolean contains(byte[] data, byte[] seq) {
9931009
return false;
9941010
}
9951011

1012+
public void addPolymorphicSignatureCaller(AnalysisMethod polymorphicSignature, AnalysisMethod caller) {
1013+
AnalysisError.guarantee(!polymorphicSignatureSealed, "The caller %s for method %s was added after the methods were persisted", caller, polymorphicSignature);
1014+
polymorphicSignatureCallers.computeIfAbsent(polymorphicSignature, (m) -> ConcurrentHashMap.newKeySet()).add(caller);
1015+
}
1016+
9961017
record SingletonPersistInfo(LayeredImageSingleton.PersistFlags flags, int id, EconomicMap<String, Object> keyStore) {
9971018
}
9981019

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1416,6 +1416,7 @@ public Which which() {
14161416
case 2 : return Which.OUTLINED_S_B;
14171417
case 3 : return Which.C_ENTRY_POINT_CALL_STUB;
14181418
case 4 : return Which.WRAPPED_MEMBER;
1419+
case 5 : return Which.POLYMORPHIC_SIGNATURE;
14191420
default: return Which._NOT_IN_SCHEMA;
14201421
}
14211422
}
@@ -1489,6 +1490,18 @@ public final WrappedMember.Builder initWrappedMember() {
14891490
return new PersistedAnalysisMethod.WrappedMethod.WrappedMember.Builder(segment, data, pointers, dataSize, pointerCount);
14901491
}
14911492

1493+
public final boolean isPolymorphicSignature() {
1494+
return which() == PersistedAnalysisMethod.WrappedMethod.Which.POLYMORPHIC_SIGNATURE;
1495+
}
1496+
public final PolymorphicSignature.Builder getPolymorphicSignature() {
1497+
return new PersistedAnalysisMethod.WrappedMethod.PolymorphicSignature.Builder(segment, data, pointers, dataSize, pointerCount);
1498+
}
1499+
public final PolymorphicSignature.Builder initPolymorphicSignature() {
1500+
_setShortField(11, (short)PersistedAnalysisMethod.WrappedMethod.Which.POLYMORPHIC_SIGNATURE.ordinal());
1501+
_clearPointerField(10);
1502+
return new PersistedAnalysisMethod.WrappedMethod.PolymorphicSignature.Builder(segment, data, pointers, dataSize, pointerCount);
1503+
}
1504+
14921505
}
14931506

14941507
public static final class Reader extends org.capnproto.StructReader {
@@ -1503,6 +1516,7 @@ public Which which() {
15031516
case 2 : return Which.OUTLINED_S_B;
15041517
case 3 : return Which.C_ENTRY_POINT_CALL_STUB;
15051518
case 4 : return Which.WRAPPED_MEMBER;
1519+
case 5 : return Which.POLYMORPHIC_SIGNATURE;
15061520
default: return Which._NOT_IN_SCHEMA;
15071521
}
15081522
}
@@ -1543,6 +1557,13 @@ public WrappedMember.Reader getWrappedMember() {
15431557
return new PersistedAnalysisMethod.WrappedMethod.WrappedMember.Reader(segment, data, pointers, dataSize, pointerCount, nestingLimit);
15441558
}
15451559

1560+
public final boolean isPolymorphicSignature() {
1561+
return which() == PersistedAnalysisMethod.WrappedMethod.Which.POLYMORPHIC_SIGNATURE;
1562+
}
1563+
public PolymorphicSignature.Reader getPolymorphicSignature() {
1564+
return new PersistedAnalysisMethod.WrappedMethod.PolymorphicSignature.Reader(segment, data, pointers, dataSize, pointerCount, nestingLimit);
1565+
}
1566+
15461567
}
15471568

15481569
public enum Which {
@@ -1551,6 +1572,7 @@ public enum Which {
15511572
OUTLINED_S_B,
15521573
C_ENTRY_POINT_CALL_STUB,
15531574
WRAPPED_MEMBER,
1575+
POLYMORPHIC_SIGNATURE,
15541576
_NOT_IN_SCHEMA,
15551577
}
15561578
public static class FactoryMethod {
@@ -1933,6 +1955,65 @@ public enum Which {
19331955
}
19341956

19351957

1958+
public static class PolymorphicSignature {
1959+
public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)5,(short)13);
1960+
public static final class Factory extends org.capnproto.StructFactory<Builder, Reader> {
1961+
public Factory() {
1962+
}
1963+
public final Reader constructReader(org.capnproto.SegmentReader segment, int data,int pointers, int dataSize, short pointerCount, int nestingLimit) {
1964+
return new Reader(segment,data,pointers,dataSize,pointerCount,nestingLimit);
1965+
}
1966+
public final Builder constructBuilder(org.capnproto.SegmentBuilder segment, int data,int pointers, int dataSize, short pointerCount) {
1967+
return new Builder(segment, data, pointers, dataSize, pointerCount);
1968+
}
1969+
public final org.capnproto.StructSize structSize() {
1970+
return PersistedAnalysisMethod.WrappedMethod.PolymorphicSignature.STRUCT_SIZE;
1971+
}
1972+
public final Reader asReader(Builder builder) {
1973+
return builder.asReader();
1974+
}
1975+
}
1976+
public static final Factory factory = new Factory();
1977+
public static final org.capnproto.StructList.Factory<Builder,Reader> listFactory =
1978+
new org.capnproto.StructList.Factory<Builder, Reader>(factory);
1979+
public static final class Builder extends org.capnproto.StructBuilder {
1980+
Builder(org.capnproto.SegmentBuilder segment, int data, int pointers,int dataSize, short pointerCount){
1981+
super(segment, data, pointers, dataSize, pointerCount);
1982+
}
1983+
public final Reader asReader() {
1984+
return new Reader(segment, data, pointers, dataSize, pointerCount, 0x7fffffff);
1985+
}
1986+
public final boolean hasCallers() {
1987+
return !_pointerFieldIsNull(10);
1988+
}
1989+
public final org.capnproto.PrimitiveList.Int.Builder getCallers() {
1990+
return _getPointerField(org.capnproto.PrimitiveList.Int.factory, 10, null, 0);
1991+
}
1992+
public final void setCallers(org.capnproto.PrimitiveList.Int.Reader value) {
1993+
_setPointerField(org.capnproto.PrimitiveList.Int.factory, 10, value);
1994+
}
1995+
public final org.capnproto.PrimitiveList.Int.Builder initCallers(int size) {
1996+
return _initPointerField(org.capnproto.PrimitiveList.Int.factory, 10, size);
1997+
}
1998+
}
1999+
2000+
public static final class Reader extends org.capnproto.StructReader {
2001+
Reader(org.capnproto.SegmentReader segment, int data, int pointers,int dataSize, short pointerCount, int nestingLimit){
2002+
super(segment, data, pointers, dataSize, pointerCount, nestingLimit);
2003+
}
2004+
2005+
public final boolean hasCallers() {
2006+
return !_pointerFieldIsNull(10);
2007+
}
2008+
public final org.capnproto.PrimitiveList.Int.Reader getCallers() {
2009+
return _getPointerField(org.capnproto.PrimitiveList.Int.factory, 10, null, 0);
2010+
}
2011+
2012+
}
2013+
2014+
}
2015+
2016+
19362017
}
19372018

19382019

0 commit comments

Comments
 (0)