Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3999122

Browse files
[GR-70201] [GR-68576] Crema: Add support for invokedynamic.
PullRequest: graal/22357
2 parents 98cca29 + 32ae962 commit 3999122

File tree

40 files changed

+1669
-198
lines changed

40 files changed

+1669
-198
lines changed

‎substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/crema/CremaSupport.java‎

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,15 @@
3232

3333
import com.oracle.svm.core.hub.DynamicHub;
3434
import com.oracle.svm.core.hub.registry.SymbolsSupport;
35+
import com.oracle.svm.core.invoke.Target_java_lang_invoke_MemberName;
3536
import com.oracle.svm.espresso.classfile.ParserKlass;
3637
import com.oracle.svm.espresso.classfile.descriptors.ByteSequence;
38+
import com.oracle.svm.espresso.classfile.descriptors.Signature;
3739
import com.oracle.svm.espresso.classfile.descriptors.Symbol;
3840
import com.oracle.svm.espresso.classfile.descriptors.Type;
3941

4042
import jdk.vm.ci.meta.JavaType;
43+
import jdk.vm.ci.meta.ResolvedJavaField;
4144
import jdk.vm.ci.meta.ResolvedJavaMethod;
4245
import jdk.vm.ci.meta.ResolvedJavaType;
4346

@@ -47,6 +50,20 @@ public interface CremaSupport {
4750

4851
int getAfterFieldsOffset(DynamicHub hub);
4952

53+
Target_java_lang_invoke_MemberName resolveMemberName(Target_java_lang_invoke_MemberName mn, Class<?> caller);
54+
55+
Object invokeBasic(Target_java_lang_invoke_MemberName memberName, Object methodHandle, Object[] args);
56+
57+
Object linkToVirtual(Object[] args);
58+
59+
Object linkToStatic(Object[] args);
60+
61+
Object linkToSpecial(Object[] args);
62+
63+
Object linkToInterface(Object[] args);
64+
65+
Object getStaticStorage(ResolvedJavaField resolved);
66+
5067
interface CremaDispatchTable {
5168
int vtableLength();
5269

@@ -97,6 +114,8 @@ default Class<?> findLoadedClass(JavaType unresolvedJavaType, ResolvedJavaType a
97114

98115
Object getStaticStorage(Class<?> cls, boolean primitives, int layerNum);
99116

117+
ResolvedJavaMethod findMethodHandleIntrinsic(ResolvedJavaMethod signaturePolymorphicMethod, Symbol<Signature> signature);
118+
100119
static CremaSupport singleton() {
101120
return ImageSingletons.lookup(CremaSupport.class);
102121
}

‎substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/AbstractRuntimeClassRegistry.java‎

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -175,20 +175,17 @@ private static boolean isParallelClassLoader(ClassLoader loader) {
175175
protected abstract boolean loaderIsBootOrPlatform();
176176

177177
public final Class<?> defineClass(Symbol<Type> typeOrNull, byte[] b, int off, int len, ClassDefinitionInfo info) {
178-
if (isParallelClassLoader()) {
178+
// GR-62338: for parallel class loaders this synchronization should be skipped.
179+
Object syncObject = getClassLoader();
180+
if (syncObject == null) {
181+
syncObject = this;
182+
}
183+
synchronized (syncObject) {
179184
return defineClassInner(typeOrNull, b, off, len, info);
180-
} else {
181-
synchronized (getClassLoader()) {
182-
return defineClassInner(typeOrNull, b, off, len, info);
183-
}
184185
}
185186
}
186187

187188
private Class<?> defineClassInner(Symbol<Type> typeOrNull, byte[] b, int off, int len, ClassDefinitionInfo info) {
188-
if (isParallelClassLoader() || getClassLoader() == null) {
189-
// GR-62338
190-
throw VMError.unimplemented("Parallel class loading:" + getClassLoader());
191-
}
192189
byte[] data = b;
193190
if (off != 0 || b.length != len) {
194191
if (len < 0) {
@@ -201,7 +198,7 @@ private Class<?> defineClassInner(Symbol<Type> typeOrNull, byte[] b, int off, in
201198
}
202199
ParserKlass parsed = parseClass(typeOrNull, info, data);
203200
Symbol<Type> type = typeOrNull == null ? parsed.getType() : typeOrNull;
204-
assert typeOrNull == null || type == parsed.getType();
201+
assert typeOrNull == null || type == parsed.getType() : typeOrNull + " vs. " + parsed.getType();
205202
if (info.addedToRegistry() && findLoadedClass(type) != null) {
206203
String kind;
207204
if (Modifier.isInterface(parsed.getFlags())) {

‎substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/interpreter/InterpreterSupport.java‎

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,16 +64,14 @@ public static InterpreterSupport singleton() {
6464
return ImageSingletons.lookup(InterpreterSupport.class);
6565
}
6666

67-
/*
68-
* Check if a given argument matches the inner class Interpreter.Root (holder of the interpreter
69-
* dispatch loop).
67+
/**
68+
* Check if a given frame should be processed by {@link #getInterpretedMethodFrameInfo}.
7069
*/
71-
public abstract boolean isInterpreterRoot(Class<?> clazz);
70+
public abstract boolean isInterpreterRoot(FrameInfoQueryResultframeInfo);
7271

7372
/**
74-
* Transforms an interpreter (root) frame into a frame of the interpreted method. The passed
75-
* frame must be an interpreter root e.g. {@code isInterpreterRoot(frameInfo.getSourceClass())}
76-
* otherwise a fatal exception is thrown.
73+
* Transforms an interpreter (root) frame into a frame of the interpreted method. An error is
74+
* thrown if the passed frame is not an {@link #isInterpreterRoot interpreter root}.
7775
*
7876
* @param frameInfo interpreter root frame
7977
* @param sp stack pointer of the interpreter frame

‎substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/invoke/MethodHandleUtils.java‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.lang.invoke.MethodHandle;
3030

3131
import com.oracle.svm.core.AlwaysInline;
32+
import com.oracle.svm.core.hub.RuntimeClassLoading;
3233

3334
import sun.invoke.util.Wrapper;
3435

@@ -127,4 +128,15 @@ public static short shortUnbox(Object retVal, Class<?> returnType) {
127128
throw shouldNotReachHere("Unexpected type for unbox function");
128129
}
129130
}
131+
132+
/**
133+
* Returns the resolved member if runtime class loading is enabled. Otherwise, always returns
134+
* {@code null}.
135+
*/
136+
public static ResolvedMember getResolvedMember(Target_java_lang_invoke_MemberName memberName) {
137+
if (RuntimeClassLoading.isSupported()) {
138+
return memberName.resolved;
139+
}
140+
return null;
141+
}
130142
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.invoke;
26+
27+
/**
28+
* This interface should be implemented by the possible resolution results of member names.
29+
*
30+
* @see Target_java_lang_invoke_MemberName#resolved
31+
*/
32+
public interface ResolvedMember {
33+
}

‎substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/invoke/Target_java_lang_invoke_MemberName.java‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
import com.oracle.svm.core.annotate.RecomputeFieldValue;
3535
import com.oracle.svm.core.annotate.Substitute;
3636
import com.oracle.svm.core.annotate.TargetClass;
37+
import com.oracle.svm.core.annotate.TargetElement;
38+
import com.oracle.svm.core.hub.RuntimeClassLoading.WithRuntimeClassLoading;
3739
import com.oracle.svm.core.methodhandles.Target_java_lang_invoke_MethodHandleNatives;
3840
import com.oracle.svm.core.util.BasedOnJDKFile;
3941
import com.oracle.svm.core.util.VMError;
@@ -46,7 +48,16 @@ public final class Target_java_lang_invoke_MemberName {
4648
@Inject @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)//
4749
public MethodHandleIntrinsic intrinsic;
4850

51+
/**
52+
* This is used by crema to store metadata for the resolved field or method.
53+
*/
54+
@Inject @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)//
55+
@TargetElement(onlyWith = WithRuntimeClassLoading.class)//
56+
public ResolvedMember resolved;
57+
58+
@Alias public Class<?> clazz;
4959
@Alias public String name;
60+
@Alias public Object type;
5061
@Alias public int flags;
5162
@Alias public Object resolution;
5263

‎substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_ClassLoader.java‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,8 @@ private static Class<?> defineClass0(ClassLoader loader, Class<?> lookup, String
353353
@SuppressWarnings("unused") boolean initialize, int flags, Object classData) {
354354
// Note that if name is not null, it is a binary name in either / or .-form
355355
String actualName = name;
356-
if (LambdaUtils.isLambdaClassName(name)) {
356+
assert !(PredefinedClassesSupport.hasBytecodeClasses() && RuntimeClassLoading.isSupported());
357+
if (!RuntimeClassLoading.isSupported() && LambdaUtils.isLambdaClassName(name)) {
357358
actualName += Digest.digest(b);
358359
}
359360
boolean isNestMate = (flags & ClassLoaderHelper.NESTMATE_CLASS) != 0;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.methodhandles;
26+
27+
import java.lang.invoke.MethodHandle;
28+
29+
import com.oracle.svm.core.SubstrateUtil;
30+
import com.oracle.svm.core.invoke.Target_java_lang_invoke_MemberName;
31+
32+
public final class MethodHandleInterpreterUtils {
33+
private MethodHandleInterpreterUtils() {
34+
}
35+
36+
public static Target_java_lang_invoke_MemberName extractVMEntry(MethodHandle handle) {
37+
Target_java_lang_invoke_LambdaForm lform = SubstrateUtil.cast(handle, Target_java_lang_invoke_MethodHandle.class).internalForm();
38+
return lform.vmentry;
39+
}
40+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
* Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package com.oracle.svm.core.methodhandles;
26+
27+
import static com.oracle.svm.core.util.VMError.unsupportedFeature;
28+
29+
import java.lang.invoke.MethodHandle;
30+
import java.lang.invoke.MethodHandles;
31+
32+
import com.oracle.svm.core.annotate.Substitute;
33+
import com.oracle.svm.core.annotate.TargetClass;
34+
import com.oracle.svm.core.hub.RuntimeClassLoading.WithRuntimeClassLoading;
35+
import com.oracle.svm.core.util.BasedOnJDKFile;
36+
37+
/**
38+
* This is used in a special case of {@code BootstrapMethodInvoker.invoke} (See
39+
* {@code @BasedOnJDKFile} annotation on this class) which is not currently used in SVM.
40+
* <p>
41+
* These substitutions cut paths that would lead to useless code being included and some deleted
42+
* methods being reached.
43+
*/
44+
@TargetClass(className = "java.lang.invoke.BootstrapMethodInvoker", innerClass = "VM_BSCI", onlyWith = WithRuntimeClassLoading.class)
45+
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+36/src/java.base/share/classes/java/lang/invoke/BootstrapMethodInvoker.java#L113-L126")
46+
final class Target_java_lang_invoke_BootstrapMethodInvoker_VM_BSCI {
47+
@Substitute
48+
@SuppressWarnings("unused")
49+
Target_java_lang_invoke_BootstrapMethodInvoker_VM_BSCI(MethodHandle bsm, String name, Object type, MethodHandles.Lookup lookup, int[] indexInfo) {
50+
throw unsupportedFeature("BootstrapMethodInvoker$VM_BSCI");
51+
}
52+
53+
@Substitute
54+
@SuppressWarnings({"unused", "static-method"})
55+
Object fillCache(int i) {
56+
throw unsupportedFeature("BootstrapMethodInvoker$VM_BSCI.fillCache");
57+
}
58+
59+
@Substitute
60+
@SuppressWarnings({"unused", "static-method"})
61+
public int copyConstants(int start, int end, Object[] buf, int pos) {
62+
throw unsupportedFeature("BootstrapMethodInvoker$VM_BSCI.copyConstants");
63+
}
64+
}

‎substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/methodhandles/Target_java_lang_invoke_BoundMethodHandle.java‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import com.oracle.svm.core.annotate.TargetClass;
3939
import com.oracle.svm.core.annotate.TargetElement;
4040
import com.oracle.svm.core.fieldvaluetransformer.NewEmptyArrayFieldValueTransformer;
41+
import com.oracle.svm.core.hub.RuntimeClassLoading.NoRuntimeClassLoading;
4142

4243
/**
4344
* In the JDK implementation of method handles, each bound method handle is an instance of a
@@ -73,7 +74,7 @@ final class Target_java_lang_invoke_BoundMethodHandle {
7374
* We hijack the species with no bound parameters for our implementation since it already inherits
7475
* from BoundMethodHandle and doesn't contain any superfluous members.
7576
*/
76-
@TargetClass(className = "java.lang.invoke.SimpleMethodHandle")
77+
@TargetClass(className = "java.lang.invoke.SimpleMethodHandle", onlyWith = NoRuntimeClassLoading.class)
7778
final class Target_java_lang_invoke_SimpleMethodHandle {
7879
/*
7980
* Since we represent all the bound method handle species with the basic one, the species data
@@ -130,7 +131,7 @@ Target_java_lang_invoke_BoundMethodHandle copyWith(MethodType type, Target_java_
130131
}
131132

132133
/* Hardcoded species, needs a special case to avoid initialization */
133-
@TargetClass(className = "java.lang.invoke.BoundMethodHandle", innerClass = "Species_L")
134+
@TargetClass(className = "java.lang.invoke.BoundMethodHandle", innerClass = "Species_L", onlyWith = NoRuntimeClassLoading.class)
134135
final class Target_java_lang_invoke_BoundMethodHandle_Species_L {
135136
@Substitute
136137
static Target_java_lang_invoke_BoundMethodHandle make(MethodType mt, Target_java_lang_invoke_LambdaForm lf, Object argL0) {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /