27
27
import static com .oracle .svm .core .Uninterruptible .CALLED_FROM_UNINTERRUPTIBLE_CODE ;
28
28
import static com .oracle .svm .core .option .RuntimeOptionKey .RuntimeOptionKeyFlag .RelevantForCompilationIsolates ;
29
29
30
- import java .util .ArrayList ;
31
30
import java .util .Arrays ;
31
+ import java .util .List ;
32
32
33
33
import org .graalvm .collections .EconomicMap ;
34
34
import org .graalvm .nativeimage .CurrentIsolate ;
46
46
import org .graalvm .word .UnsignedWord ;
47
47
import org .graalvm .word .WordFactory ;
48
48
49
+ import com .oracle .svm .core .SubstrateDiagnostics .DiagnosticThunkRegistry ;
50
+ import com .oracle .svm .core .SubstrateDiagnostics .DumpCodeCacheHistory ;
51
+ import com .oracle .svm .core .SubstrateDiagnostics .DumpDeoptStubPointer ;
52
+ import com .oracle .svm .core .SubstrateDiagnostics .DumpRecentDeoptimizations ;
53
+ import com .oracle .svm .core .SubstrateDiagnostics .DumpRuntimeCodeInfoMemory ;
49
54
import com .oracle .svm .core .c .NonmovableArrays ;
50
55
import com .oracle .svm .core .code .CodeInfo ;
51
56
import com .oracle .svm .core .code .CodeInfoAccess ;
59
64
import com .oracle .svm .core .container .OperatingSystem ;
60
65
import com .oracle .svm .core .deopt .DeoptimizationSupport ;
61
66
import com .oracle .svm .core .deopt .Deoptimizer ;
67
+ import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
62
68
import com .oracle .svm .core .feature .AutomaticallyRegisteredImageSingleton ;
69
+ import com .oracle .svm .core .feature .InternalFeature ;
63
70
import com .oracle .svm .core .graal .RuntimeCompilation ;
64
71
import com .oracle .svm .core .graal .stackvalue .UnsafeStackValue ;
65
72
import com .oracle .svm .core .heap .Heap ;
88
95
import com .oracle .svm .core .threadlocal .FastThreadLocalFactory ;
89
96
import com .oracle .svm .core .threadlocal .VMThreadLocalInfos ;
90
97
import com .oracle .svm .core .util .CounterSupport ;
98
+ import com .oracle .svm .core .util .ImageHeapList ;
91
99
import com .oracle .svm .core .util .TimeUtils ;
92
100
import com .oracle .svm .core .util .VMError ;
93
101
@@ -679,7 +687,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
679
687
}
680
688
}
681
689
682
- private static class DumpDeoptStubPointer extends DiagnosticThunk {
690
+ static class DumpDeoptStubPointer extends DiagnosticThunk {
683
691
@ Override
684
692
public int maxInvocationCount () {
685
693
return 1 ;
@@ -796,7 +804,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
796
804
}
797
805
}
798
806
799
- private static class DumpCodeCacheHistory extends DiagnosticThunk {
807
+ static class DumpCodeCacheHistory extends DiagnosticThunk {
800
808
@ Override
801
809
public int maxInvocationCount () {
802
810
return 2 ;
@@ -810,7 +818,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
810
818
}
811
819
}
812
820
813
- private static class DumpRuntimeCodeInfoMemory extends DiagnosticThunk {
821
+ static class DumpRuntimeCodeInfoMemory extends DiagnosticThunk {
814
822
@ Override
815
823
public int maxInvocationCount () {
816
824
return 3 ;
@@ -825,7 +833,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
825
833
}
826
834
}
827
835
828
- private static class DumpRecentDeoptimizations extends DiagnosticThunk {
836
+ static class DumpRecentDeoptimizations extends DiagnosticThunk {
829
837
@ Override
830
838
public int maxInvocationCount () {
831
839
return 1 ;
@@ -1239,11 +1247,15 @@ public abstract static class DiagnosticThunk {
1239
1247
}
1240
1248
1241
1249
public static class DiagnosticThunkRegistry {
1242
- private DiagnosticThunk [] diagnosticThunks ;
1250
+ @ Platforms (Platform .HOSTED_ONLY .class ) //
1251
+ final int runtimeCompilationPosition ;
1252
+
1253
+ private final List <DiagnosticThunk > thunks = ImageHeapList .create (DiagnosticThunk .class );
1243
1254
private int [] initialInvocationCount ;
1244
1255
1245
1256
@ Fold
1246
1257
public static synchronized DiagnosticThunkRegistry singleton () {
1258
+ /* The registry is already used very early during the image build. */
1247
1259
if (!ImageSingletons .contains (DiagnosticThunkRegistry .class )) {
1248
1260
ImageSingletons .add (DiagnosticThunkRegistry .class , new DiagnosticThunkRegistry ());
1249
1261
}
@@ -1252,7 +1264,6 @@ public static synchronized DiagnosticThunkRegistry singleton() {
1252
1264
1253
1265
@ Platforms (Platform .HOSTED_ONLY .class )
1254
1266
DiagnosticThunkRegistry () {
1255
- ArrayList <DiagnosticThunk > thunks = new ArrayList <>();
1256
1267
thunks .add (new DumpRegisters ());
1257
1268
thunks .add (new DumpInstructions ());
1258
1269
thunks .add (new DumpTopOfCurrentThreadStack ());
@@ -1272,45 +1283,43 @@ public static synchronized DiagnosticThunkRegistry singleton() {
1272
1283
if (CounterSupport .isEnabled ()) {
1273
1284
thunks .add (new DumpCounters ());
1274
1285
}
1275
- if (RuntimeCompilation .isEnabled ()) {
1276
- thunks .add (new DumpCodeCacheHistory ());
1277
- thunks .add (new DumpRuntimeCodeInfoMemory ());
1278
- thunks .add (new DumpDeoptStubPointer ());
1279
- thunks .add (new DumpRecentDeoptimizations ());
1280
- }
1281
1286
1282
- this .diagnosticThunks = thunks .toArray (new DiagnosticThunk [0 ]);
1283
- this .initialInvocationCount = new int [diagnosticThunks .length ];
1284
- Arrays .fill (initialInvocationCount , 1 );
1287
+ resizeInitialInvocationCount ();
1288
+ this .runtimeCompilationPosition = thunks .size ();
1285
1289
}
1286
1290
1287
1291
@ Platforms (Platform .HOSTED_ONLY .class )
1288
1292
public synchronized void add (DiagnosticThunk thunk ) {
1289
- diagnosticThunks = Arrays .copyOf (diagnosticThunks , diagnosticThunks .length + 1 );
1290
- diagnosticThunks [diagnosticThunks .length - 1 ] = thunk ;
1293
+ thunks .add (thunk );
1294
+ resizeInitialInvocationCount ();
1295
+ }
1291
1296
1292
- initialInvocationCount = Arrays .copyOf (initialInvocationCount , initialInvocationCount .length + 1 );
1293
- initialInvocationCount [initialInvocationCount .length - 1 ] = 1 ;
1297
+ @ Platforms (Platform .HOSTED_ONLY .class )
1298
+ public synchronized void add (int insertPos , DiagnosticThunk ... extraThunks ) {
1299
+ for (int i = 0 ; i < extraThunks .length ; i ++) {
1300
+ thunks .add (insertPos + i , extraThunks [i ]);
1301
+ }
1302
+ resizeInitialInvocationCount ();
1294
1303
}
1295
1304
1296
1305
@ Platforms (Platform .HOSTED_ONLY .class )
1297
1306
public synchronized void addAfter (DiagnosticThunk thunk , Class <? extends DiagnosticThunk > before ) {
1298
1307
int insertPos = indexOf (before ) + 1 ;
1308
+ assert insertPos > 0 ;
1309
+ thunks .add (insertPos , thunk );
1310
+ resizeInitialInvocationCount ();
1311
+ }
1299
1312
1300
- DiagnosticThunk [] newThunks = new DiagnosticThunk [diagnosticThunks .length + 1 ];
1301
- System .arraycopy (diagnosticThunks , 0 , newThunks , 0 , insertPos );
1302
- newThunks [insertPos ] = thunk ;
1303
- System .arraycopy (diagnosticThunks , insertPos , newThunks , insertPos + 1 , diagnosticThunks .length - insertPos );
1304
- diagnosticThunks = newThunks ;
1305
-
1306
- initialInvocationCount = Arrays .copyOf (initialInvocationCount , initialInvocationCount .length + 1 );
1307
- initialInvocationCount [initialInvocationCount .length - 1 ] = 1 ;
1313
+ @ Platforms (Platform .HOSTED_ONLY .class )
1314
+ private void resizeInitialInvocationCount () {
1315
+ initialInvocationCount = new int [thunks .size ()];
1316
+ Arrays .fill (initialInvocationCount , 1 );
1308
1317
}
1309
1318
1310
1319
@ Platforms (Platform .HOSTED_ONLY .class )
1311
1320
private int indexOf (Class <? extends DiagnosticThunk > clazz ) {
1312
- for (int i = 0 ; i < diagnosticThunks . length ; i ++) {
1313
- if (diagnosticThunks [ i ] .getClass () == clazz ) {
1321
+ for (int i = 0 ; i < thunks . size () ; i ++) {
1322
+ if (thunks . get ( i ) .getClass () == clazz ) {
1314
1323
return i ;
1315
1324
}
1316
1325
}
@@ -1319,11 +1328,11 @@ private int indexOf(Class<? extends DiagnosticThunk> clazz) {
1319
1328
1320
1329
@ Fold
1321
1330
int size () {
1322
- return diagnosticThunks . length ;
1331
+ return thunks . size () ;
1323
1332
}
1324
1333
1325
1334
DiagnosticThunk getThunk (int index ) {
1326
- return diagnosticThunks [ index ] ;
1335
+ return thunks . get ( index ) ;
1327
1336
}
1328
1337
1329
1338
int getInitialInvocationCount (int index ) {
@@ -1394,3 +1403,21 @@ public static boolean implicitExceptionWithoutStacktraceIsFatal() {
1394
1403
}
1395
1404
}
1396
1405
}
1406
+
1407
+ @ AutomaticallyRegisteredFeature
1408
+ class SubstrateDiagnosticsFeature implements InternalFeature {
1409
+ /**
1410
+ * {@link RuntimeCompilation#isEnabled()} can't be executed in the
1411
+ * {@link DiagnosticThunkRegistry} constructor because the feature registration is not
1412
+ * necessarily finished. So, we need to do it at a later point in time.
1413
+ */
1414
+ @ Override
1415
+ public void afterRegistration (AfterRegistrationAccess access ) {
1416
+ DiagnosticThunkRegistry registry = DiagnosticThunkRegistry .singleton ();
1417
+ if (RuntimeCompilation .isEnabled ()) {
1418
+ int pos = registry .runtimeCompilationPosition ;
1419
+ SubstrateDiagnostics .DiagnosticThunk [] thunks = {new DumpCodeCacheHistory (), new DumpRuntimeCodeInfoMemory (), new DumpDeoptStubPointer (), new DumpRecentDeoptimizations ()};
1420
+ registry .add (pos , thunks );
1421
+ }
1422
+ }
1423
+ }
0 commit comments