|
42 | 42 | import com.oracle.svm.core.hub.DynamicHub;
|
43 | 43 | import com.oracle.svm.core.hub.PredefinedClassesSupport;
|
44 | 44 | import com.oracle.svm.core.hub.RuntimeClassLoading;
|
| 45 | +import com.oracle.svm.core.hub.crema.CremaSupport; |
45 | 46 | import com.oracle.svm.core.jdk.InternalVMMethod;
|
46 | 47 | import com.oracle.svm.core.snippets.SubstrateForeignCallTarget;
|
47 | 48 | import com.oracle.svm.core.stack.StackOverflowCheck;
|
|
54 | 55 |
|
55 | 56 | import jdk.graal.compiler.word.Word;
|
56 | 57 | import jdk.internal.reflect.Reflection;
|
| 58 | +import jdk.vm.ci.meta.ResolvedJavaMethod; |
57 | 59 |
|
58 | 60 | /**
|
59 | 61 | * Information about the runtime class initialization state of a {@link DynamicHub class}, and
|
@@ -86,6 +88,12 @@ public final class ClassInitializationInfo {
|
86 | 88 | private static final ClassInitializationInfo FAILED_NO_CLINIT_NO_TRACKING = new ClassInitializationInfo(InitState.InitializationError, false, false);
|
87 | 89 | private static final ClassInitializationInfo FAILED_HAS_CLINIT_NO_TRACKING = new ClassInitializationInfo(InitState.InitializationError, true, false);
|
88 | 90 |
|
| 91 | + /** |
| 92 | + * Marks that a runtime-loaded class has a class initializer that should be executed in the |
| 93 | + * interpreter. |
| 94 | + */ |
| 95 | + private static final FunctionPointerHolder INTERPRETER_INITIALIZATION_MARKER = new FunctionPointerHolder(null); |
| 96 | + |
89 | 97 | /**
|
90 | 98 | * Function pointer to the class initializer that should be called at run-time. In some cases,
|
91 | 99 | * this may be an arbitrary helper method instead of the {@code <clinit>} of the class. This
|
@@ -188,12 +196,12 @@ private ClassInitializationInfo(CFunctionPointer runtimeClassInitializer, boolea
|
188 | 196 | }
|
189 | 197 |
|
190 | 198 | /** For classes that are loaded at run-time. */
|
191 |
| - private ClassInitializationInfo(boolean typeReachedTracked) { |
| 199 | + private ClassInitializationInfo(boolean typeReachedTracked, boolean hasClassInitializer) { |
192 | 200 | assert RuntimeClassLoading.isSupported();
|
193 | 201 |
|
194 | 202 | this.buildTimeInitialized = false;
|
195 |
| - this.hasInitializer = true; |
196 |
| - this.runtimeClassInitializer = null; |
| 203 | + this.hasInitializer = hasClassInitializer; |
| 204 | + this.runtimeClassInitializer = hasClassInitializer ? INTERPRETER_INITIALIZATION_MARKER : null; |
197 | 205 | this.slowPathRequired = true;
|
198 | 206 | this.initLock = new ReentrantLock();
|
199 | 207 | /* GR-59739: Needs a new state "Loaded". */
|
@@ -224,8 +232,8 @@ public static ClassInitializationInfo forRuntimeTimeInitializedClass(CFunctionPo
|
224 | 232 | return new ClassInitializationInfo(methodPointer, typeReachedTracked);
|
225 | 233 | }
|
226 | 234 |
|
227 |
| - public static ClassInitializationInfo forRuntimeLoadedClass(boolean typeReachedTracked) { |
228 |
| - return new ClassInitializationInfo(typeReachedTracked); |
| 235 | + public static ClassInitializationInfo forRuntimeLoadedClass(boolean typeReachedTracked, boolean hasClassInitializer) { |
| 236 | + return new ClassInitializationInfo(typeReachedTracked, hasClassInitializer); |
229 | 237 | }
|
230 | 238 |
|
231 | 239 | public boolean isBuildTimeInitialized() {
|
@@ -533,7 +541,7 @@ private void tryInitialize0(DynamicHub hub) {
|
533 | 541 | */
|
534 | 542 | Throwable exception = null;
|
535 | 543 | try {
|
536 |
| - invokeClassInitializer(); |
| 544 | + invokeClassInitializer(hub); |
537 | 545 | } catch (Throwable ex) {
|
538 | 546 | exception = ex;
|
539 | 547 | }
|
@@ -694,27 +702,35 @@ private void setInitializationStateAndNotify0(InitState state) {
|
694 | 702 | }
|
695 | 703 |
|
696 | 704 | @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+13/src/hotspot/share/oops/instanceKlass.cpp#L1675-L1715")
|
697 |
| - private void invokeClassInitializer() { |
| 705 | + private void invokeClassInitializer(DynamicHub hub) { |
698 | 706 | if (runtimeClassInitializer == null) {
|
699 | 707 | return;
|
700 | 708 | }
|
701 | 709 |
|
702 |
| - ClassInitializerFunctionPointer functionPointer = (ClassInitializerFunctionPointer) runtimeClassInitializer.functionPointer; |
703 |
| - VMError.guarantee(functionPointer.isNonNull()); |
704 |
| - |
705 | 710 | /* Protect the yellow zone before executing arbitrary Java code. */
|
706 | 711 | if (Platform.includedIn(NATIVE_ONLY.class)) {
|
707 | 712 | StackOverflowCheck.singleton().protectYellowZone();
|
708 | 713 | }
|
709 | 714 | try {
|
710 |
| - functionPointer.invoke(); |
| 715 | + invokeClassInitializer0(hub); |
711 | 716 | } finally {
|
712 | 717 | if (Platform.includedIn(NATIVE_ONLY.class)) {
|
713 | 718 | StackOverflowCheck.singleton().makeYellowZoneAvailable();
|
714 | 719 | }
|
715 | 720 | }
|
716 | 721 | }
|
717 | 722 |
|
| 723 | + private void invokeClassInitializer0(DynamicHub hub) { |
| 724 | + if (RuntimeClassLoading.isSupported() && runtimeClassInitializer == INTERPRETER_INITIALIZATION_MARKER) { |
| 725 | + ResolvedJavaMethod classInitializer = hub.getInterpreterType().getClassInitializer(); |
| 726 | + CremaSupport.singleton().execute(classInitializer, new Object[0]); |
| 727 | + } else { |
| 728 | + ClassInitializerFunctionPointer functionPointer = (ClassInitializerFunctionPointer) runtimeClassInitializer.functionPointer; |
| 729 | + VMError.guarantee(functionPointer.isNonNull()); |
| 730 | + functionPointer.invoke(); |
| 731 | + } |
| 732 | + } |
| 733 | + |
718 | 734 | public enum InitState {
|
719 | 735 | /**
|
720 | 736 | * Successfully linked/verified (but not initialized yet). Linking happens during image
|
|
0 commit comments