|
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