33
33
import java .util .List ;
34
34
35
35
import org .graalvm .compiler .word .Word ;
36
+ import org .graalvm .nativeimage .CurrentIsolate ;
36
37
import org .graalvm .nativeimage .ImageSingletons ;
38
+ import org .graalvm .nativeimage .Isolate ;
37
39
import org .graalvm .nativeimage .Platform ;
38
40
import org .graalvm .nativeimage .Platforms ;
39
41
import org .graalvm .nativeimage .VMRuntime ;
47
49
import org .graalvm .word .UnsignedWord ;
48
50
import org .graalvm .word .WordFactory ;
49
51
50
- import com .oracle .svm .core .annotate .AlwaysInline ;
51
52
import com .oracle .svm .core .annotate .Uninterruptible ;
52
53
import com .oracle .svm .core .c .CGlobalData ;
53
54
import com .oracle .svm .core .c .CGlobalDataFactory ;
54
55
import com .oracle .svm .core .c .function .CEntryPointActions ;
55
56
import com .oracle .svm .core .c .function .CEntryPointCreateIsolateParameters ;
56
57
import com .oracle .svm .core .c .function .CEntryPointErrors ;
57
58
import com .oracle .svm .core .c .function .CEntryPointOptions ;
59
+ import com .oracle .svm .core .c .function .CEntryPointOptions .NoEpilogue ;
60
+ import com .oracle .svm .core .c .function .CEntryPointOptions .NoPrologue ;
61
+ import com .oracle .svm .core .c .function .CEntryPointSetup ;
58
62
import com .oracle .svm .core .jdk .InternalVMMethod ;
59
63
import com .oracle .svm .core .jdk .RuntimeSupport ;
60
64
import com .oracle .svm .core .log .Log ;
61
65
import com .oracle .svm .core .thread .JavaThreads ;
62
66
import com .oracle .svm .core .thread .PlatformThreads ;
67
+ import com .oracle .svm .core .thread .VMThreads ;
63
68
import com .oracle .svm .core .util .Counter ;
69
+ import com .oracle .svm .core .util .VMError ;
64
70
65
71
import jdk .vm .ci .code .Architecture ;
66
72
@@ -119,17 +125,20 @@ public List<String> getInputArguments() {
119
125
}
120
126
}
121
127
128
+ @ Uninterruptible (reason = "The caller initialized the thread state, so the callees do not need to be uninterruptible." , calleeMustBe = false )
129
+ private static int runCore () {
130
+ return runCore0 ();
131
+ }
132
+
122
133
/**
123
134
* Used by JavaMainWrapper and any user supplied main entry point (from
124
135
* {@link org.graalvm.nativeimage.hosted.Feature.AfterRegistrationAccess}).
125
136
*/
126
- @ AlwaysInline (value = "Single callee from the main entry point." )
127
- public static int runCore () {
137
+ private static int runCore0 () {
128
138
Architecture imageArchitecture = ImageSingletons .lookup (SubstrateTargetDescription .class ).arch ;
129
139
CPUFeatureAccess cpuFeatureAccess = ImageSingletons .lookup (CPUFeatureAccess .class );
130
140
cpuFeatureAccess .verifyHostSupportsArchitecture (imageArchitecture );
131
141
132
- int exitCode ;
133
142
try {
134
143
if (SubstrateOptions .ParseRuntimeOptions .getValue ()) {
135
144
/*
@@ -147,10 +156,7 @@ public static int runCore() {
147
156
*/
148
157
JavaMainSupport mainSupport = ImageSingletons .lookup (JavaMainSupport .class );
149
158
mainSupport .javaMainHandle .invokeExact (mainSupport .mainArgs );
150
-
151
- /* The application terminated normally. */
152
- exitCode = 0 ;
153
-
159
+ return 0 ;
154
160
} catch (Throwable ex ) {
155
161
JavaThreads .dispatchUncaughtException (Thread .currentThread (), ex );
156
162
@@ -159,30 +165,54 @@ public static int runCore() {
159
165
* if an uncaught exception handler is registered. This behavior is the same on the Java
160
166
* HotSpot VM.
161
167
*/
162
- exitCode = 1 ;
163
-
168
+ return 1 ;
164
169
} finally {
165
- /*
166
- * Shutdown sequence: First wait for all non-daemon threads to exit.
167
- */
168
- PlatformThreads .singleton ().joinAllNonDaemons ();
169
- /*
170
- * Run shutdown hooks (both our own hooks and application-registered hooks. Note that
171
- * this can start new non-daemon threads. We are not responsible to wait until they have
172
- * exited.
173
- */
174
- RuntimeSupport .getRuntimeSupport ().shutdown ();
175
-
176
- Counter .logValues (Log .log ());
170
+ PlatformThreads .exit (Thread .currentThread ());
177
171
}
178
- return exitCode ;
179
172
}
180
173
174
+ @ Uninterruptible (reason = "The caller initialized the thread state, so the callees do not need to be uninterruptible." , calleeMustBe = false )
175
+ private static void runShutdown () {
176
+ runShutdown0 ();
177
+ }
178
+
179
+ private static void runShutdown0 () {
180
+ PlatformThreads .ensureCurrentAssigned ("DestroyJavaVM" , null , false );
181
+
182
+ // Shutdown sequence: First wait for all non-daemon threads to exit.
183
+ PlatformThreads .singleton ().joinAllNonDaemons ();
184
+
185
+ /*
186
+ * Run shutdown hooks (both our own hooks and application-registered hooks. Note that this
187
+ * can start new non-daemon threads. We are not responsible to wait until they have exited.
188
+ */
189
+ RuntimeSupport .getRuntimeSupport ().shutdown ();
190
+
191
+ Counter .logValues (Log .log ());
192
+ }
193
+
194
+ @ Uninterruptible (reason = "Thread state not set up yet." )
181
195
@ CEntryPoint (include = CEntryPoint .NotIncludedAutomatically .class )
182
- @ CEntryPointOptions (prologue = EnterCreateIsolateWithCArgumentsPrologue .class )
183
- @ SuppressWarnings ("unused" )
196
+ @ CEntryPointOptions (prologue = NoPrologue .class , epilogue = NoEpilogue .class )
184
197
public static int run (int argc , CCharPointerPointer argv ) {
185
- return runCore ();
198
+ try {
199
+ // Create the isolate and attach the current C thread as the main Java thread.
200
+ EnterCreateIsolateWithCArgumentsPrologue .enter (argc , argv );
201
+ assert !VMThreads .wasStartedByCurrentIsolate (CurrentIsolate .getCurrentThread ()) : "re-attach would cause issues otherwise" ;
202
+
203
+ Isolate isolate = CurrentIsolate .getIsolate ();
204
+ int exitCode = runCore ();
205
+ CEntryPointSetup .LeaveDetachThreadEpilogue .leave ();
206
+
207
+ // Re-attach the same C thread as another Java thread.
208
+ EnterAttachThreadForShutdown .enter (isolate );
209
+ runShutdown ();
210
+ CEntryPointSetup .LeaveDetachThreadEpilogue .leave ();
211
+
212
+ return exitCode ;
213
+ } catch (Throwable e ) {
214
+ throw VMError .shouldNotReachHere (e );
215
+ }
186
216
}
187
217
188
218
private static boolean isArgumentBlockSupported () {
@@ -283,4 +313,17 @@ public static void enter(int paramArgc, CCharPointerPointer paramArgv) {
283
313
}
284
314
}
285
315
}
316
+
317
+ public static class EnterAttachThreadForShutdown implements CEntryPointOptions .Prologue {
318
+ private static final CGlobalData <CCharPointer > errorMessage = CGlobalDataFactory .createCString (
319
+ "Failed to re-attach the main thread for shutting down the main isolate." );
320
+
321
+ @ Uninterruptible (reason = "prologue" )
322
+ static void enter (Isolate isolate ) {
323
+ int code = CEntryPointActions .enterAttachThread (isolate , false );
324
+ if (code != CEntryPointErrors .NO_ERROR ) {
325
+ CEntryPointActions .failFatally (code , errorMessage .get ());
326
+ }
327
+ }
328
+ }
286
329
}
0 commit comments