2727import static com .oracle .svm .core .Uninterruptible .CALLED_FROM_UNINTERRUPTIBLE_CODE ;
2828import static com .oracle .svm .core .option .RuntimeOptionKey .RuntimeOptionKeyFlag .RelevantForCompilationIsolates ;
2929
30- import java .util .ArrayList ;
3130import java .util .Arrays ;
31+ import java .util .List ;
3232
3333import org .graalvm .collections .EconomicMap ;
3434import org .graalvm .nativeimage .CurrentIsolate ;
4646import org .graalvm .word .UnsignedWord ;
4747import org .graalvm .word .WordFactory ;
4848
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 ;
4954import com .oracle .svm .core .c .NonmovableArrays ;
5055import com .oracle .svm .core .code .CodeInfo ;
5156import com .oracle .svm .core .code .CodeInfoAccess ;
5964import com .oracle .svm .core .container .OperatingSystem ;
6065import com .oracle .svm .core .deopt .DeoptimizationSupport ;
6166import com .oracle .svm .core .deopt .Deoptimizer ;
67+ import com .oracle .svm .core .feature .AutomaticallyRegisteredFeature ;
6268import com .oracle .svm .core .feature .AutomaticallyRegisteredImageSingleton ;
69+ import com .oracle .svm .core .feature .InternalFeature ;
6370import com .oracle .svm .core .graal .RuntimeCompilation ;
6471import com .oracle .svm .core .graal .stackvalue .UnsafeStackValue ;
6572import com .oracle .svm .core .heap .Heap ;
8895import com .oracle .svm .core .threadlocal .FastThreadLocalFactory ;
8996import com .oracle .svm .core .threadlocal .VMThreadLocalInfos ;
9097import com .oracle .svm .core .util .CounterSupport ;
98+ import com .oracle .svm .core .util .ImageHeapList ;
9199import com .oracle .svm .core .util .TimeUtils ;
92100import com .oracle .svm .core .util .VMError ;
93101
@@ -679,7 +687,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
679687 }
680688 }
681689
682- private static class DumpDeoptStubPointer extends DiagnosticThunk {
690+ static class DumpDeoptStubPointer extends DiagnosticThunk {
683691 @ Override
684692 public int maxInvocationCount () {
685693 return 1 ;
@@ -796,7 +804,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
796804 }
797805 }
798806
799- private static class DumpCodeCacheHistory extends DiagnosticThunk {
807+ static class DumpCodeCacheHistory extends DiagnosticThunk {
800808 @ Override
801809 public int maxInvocationCount () {
802810 return 2 ;
@@ -810,7 +818,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
810818 }
811819 }
812820
813- private static class DumpRuntimeCodeInfoMemory extends DiagnosticThunk {
821+ static class DumpRuntimeCodeInfoMemory extends DiagnosticThunk {
814822 @ Override
815823 public int maxInvocationCount () {
816824 return 3 ;
@@ -825,7 +833,7 @@ public void printDiagnostics(Log log, ErrorContext context, int maxDiagnosticLev
825833 }
826834 }
827835
828- private static class DumpRecentDeoptimizations extends DiagnosticThunk {
836+ static class DumpRecentDeoptimizations extends DiagnosticThunk {
829837 @ Override
830838 public int maxInvocationCount () {
831839 return 1 ;
@@ -1239,11 +1247,15 @@ public abstract static class DiagnosticThunk {
12391247 }
12401248
12411249 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 );
12431254 private int [] initialInvocationCount ;
12441255
12451256 @ Fold
12461257 public static synchronized DiagnosticThunkRegistry singleton () {
1258+ /* The registry is already used very early during the image build. */
12471259 if (!ImageSingletons .contains (DiagnosticThunkRegistry .class )) {
12481260 ImageSingletons .add (DiagnosticThunkRegistry .class , new DiagnosticThunkRegistry ());
12491261 }
@@ -1252,7 +1264,6 @@ public static synchronized DiagnosticThunkRegistry singleton() {
12521264
12531265 @ Platforms (Platform .HOSTED_ONLY .class )
12541266 DiagnosticThunkRegistry () {
1255- ArrayList <DiagnosticThunk > thunks = new ArrayList <>();
12561267 thunks .add (new DumpRegisters ());
12571268 thunks .add (new DumpInstructions ());
12581269 thunks .add (new DumpTopOfCurrentThreadStack ());
@@ -1272,45 +1283,43 @@ public static synchronized DiagnosticThunkRegistry singleton() {
12721283 if (CounterSupport .isEnabled ()) {
12731284 thunks .add (new DumpCounters ());
12741285 }
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- }
12811286
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 ();
12851289 }
12861290
12871291 @ Platforms (Platform .HOSTED_ONLY .class )
12881292 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+ }
12911296
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 ();
12941303 }
12951304
12961305 @ Platforms (Platform .HOSTED_ONLY .class )
12971306 public synchronized void addAfter (DiagnosticThunk thunk , Class <? extends DiagnosticThunk > before ) {
12981307 int insertPos = indexOf (before ) + 1 ;
1308+ assert insertPos > 0 ;
1309+ thunks .add (insertPos , thunk );
1310+ resizeInitialInvocationCount ();
1311+ }
12991312
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 );
13081317 }
13091318
13101319 @ Platforms (Platform .HOSTED_ONLY .class )
13111320 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 ) {
13141323 return i ;
13151324 }
13161325 }
@@ -1319,11 +1328,11 @@ private int indexOf(Class<? extends DiagnosticThunk> clazz) {
13191328
13201329 @ Fold
13211330 int size () {
1322- return diagnosticThunks . length ;
1331+ return thunks . size () ;
13231332 }
13241333
13251334 DiagnosticThunk getThunk (int index ) {
1326- return diagnosticThunks [ index ] ;
1335+ return thunks . get ( index ) ;
13271336 }
13281337
13291338 int getInitialInvocationCount (int index ) {
@@ -1394,3 +1403,21 @@ public static boolean implicitExceptionWithoutStacktraceIsFatal() {
13941403 }
13951404 }
13961405}
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