238
238
import static jdk .graal .compiler .core .common .GraalOptions .StrictDeoptInsertionChecks ;
239
239
import static jdk .graal .compiler .core .common .GraalOptions .TraceInlining ;
240
240
import static jdk .graal .compiler .core .common .type .StampFactory .objectNonNull ;
241
- import static jdk .graal .compiler .debug .GraalError .guarantee ;
242
241
import static jdk .graal .compiler .debug .GraalError .shouldNotReachHereUnexpectedValue ;
243
242
import static jdk .graal .compiler .java .BytecodeParserOptions .InlinePartialIntrinsicExitDuringParsing ;
244
243
import static jdk .graal .compiler .java .BytecodeParserOptions .TraceBytecodeParserLevel ;
@@ -2313,10 +2312,10 @@ static String pluginErrorMessage(InvocationPlugin plugin, String format, Object.
2313
2312
}
2314
2313
2315
2314
/**
2316
- * Contains all the assertion checking logic around the application of an
2317
- * {@link InvocationPlugin}. This class is only loaded when assertions are enabled.
2315
+ * Checks stack and nodes remain consistent before and after the application of an
2316
+ * {@link InvocationPlugin}.
2318
2317
*/
2319
- class InvocationPluginAssertions {
2318
+ class InvocationPluginChecks {
2320
2319
final InvocationPlugin plugin ;
2321
2320
final ValueNode [] args ;
2322
2321
final ResolvedJavaMethod targetMethod ;
@@ -2325,8 +2324,7 @@ class InvocationPluginAssertions {
2325
2324
final int nodeCount ;
2326
2325
final Mark mark ;
2327
2326
2328
- InvocationPluginAssertions (InvocationPlugin plugin , ValueNode [] args , ResolvedJavaMethod targetMethod , JavaKind resultType ) {
2329
- guarantee (Assertions .assertionsEnabled (), "%s should only be loaded and instantiated if assertions are enabled" , getClass ().getSimpleName ());
2327
+ InvocationPluginChecks (InvocationPlugin plugin , ValueNode [] args , ResolvedJavaMethod targetMethod , JavaKind resultType ) {
2330
2328
this .plugin = plugin ;
2331
2329
this .targetMethod = targetMethod ;
2332
2330
this .args = args ;
@@ -2340,17 +2338,31 @@ String error(String format, Object... a) {
2340
2338
return pluginErrorMessage (plugin , format , a );
2341
2339
}
2342
2340
2343
- boolean check (boolean pluginResult ) {
2341
+ boolean checkStackConsistency (boolean pluginResult ) {
2344
2342
if (pluginResult ) {
2343
+ int expectedStackSize = beforeStackSize + resultType .getSlotCount ();
2344
+ JavaKind peekKind = frameState .peekKind ();
2345
+
2345
2346
/*
2346
2347
* If lastInstr is null, even if this method has a non-void return type, the method
2347
2348
* doesn't return a value, it probably throws an exception.
2349
+ *
2350
+ * We also generate various invocation plugins that return VM specific data
2351
+ * structure types, e.g., KlassPointer and Word. The former will be treated as
2352
+ * JavaKind.Illegal and the latter as JavaKind.Long. These plugins will break the
2353
+ * result type check, and can be filtered out with InvocationPlugin.isGraalOnly().
2348
2354
*/
2349
- int expectedStackSize = beforeStackSize + resultType .getSlotCount ();
2350
- assert lastInstr == null || plugin .isDecorator () || expectedStackSize == frameState .stackSize () : error ("plugin manipulated the stack incorrectly: expected=%d, actual=%d" ,
2351
- expectedStackSize ,
2352
- frameState .stackSize ());
2355
+ if (lastInstr != null && !plugin .isDecorator () && (expectedStackSize != frameState .stackSize () ||
2356
+ (!plugin .isGraalOnly () && resultType != JavaKind .Void && resultType .getStackKind () != peekKind .getStackKind ()))) {
2357
+ throw new GraalError (error ("plugin manipulated the stack incorrectly: expected=%d, actual=%d, resultType=%s stackKind=%s" ,
2358
+ expectedStackSize , frameState .stackSize (), resultType .getJavaName (), peekKind .getJavaName ()));
2359
+ }
2360
+ }
2361
+ return true ;
2362
+ }
2353
2363
2364
+ boolean checkNodeConsistency (boolean pluginResult ) {
2365
+ if (pluginResult ) {
2354
2366
NodeIterable <Node > newNodes = graph .getNewNodes (mark );
2355
2367
for (Node n : newNodes ) {
2356
2368
if (n instanceof StateSplit ) {
@@ -2473,7 +2485,7 @@ protected boolean applyInvocationPlugin(InvokeKind invokeKind, ValueNode[] args,
2473
2485
InvocationPluginReceiver pluginReceiver = invocationPluginReceiver .init (targetMethod , args );
2474
2486
assert invokeKind .isDirect () : "Cannot apply invocation plugin on an indirect call site." ;
2475
2487
2476
- InvocationPluginAssertions assertions = Assertions . assertionsEnabled () ? new InvocationPluginAssertions (plugin , args , targetMethod , resultType ) : null ;
2488
+ InvocationPluginChecks checks = new InvocationPluginChecks (plugin , args , targetMethod , resultType );
2477
2489
boolean needsReceiverNullCheck = !(plugin instanceof GeneratedInvocationPlugin ) && !targetMethod .isStatic () && args [0 ].getStackKind () == JavaKind .Object ;
2478
2490
try (DebugCloseable context = openNodeContext (targetMethod ); InvocationPluginScope pluginScope = new InvocationPluginScope (invokeKind , args , targetMethod , resultType , plugin )) {
2479
2491
Mark mark = graph .getMark ();
@@ -2485,10 +2497,14 @@ protected boolean applyInvocationPlugin(InvokeKind invokeKind, ValueNode[] args,
2485
2497
targetMethod .format ("%H.%n(%p)" ),
2486
2498
args [0 ]));
2487
2499
}
2488
- assert assertions .check (true );
2500
+ // Check stack consistency even without assert, to prevent silent invalid
2501
+ // intrinsification. This may happen when JDK changes the return type of
2502
+ // an intrinsic candidate.
2503
+ checks .checkStackConsistency (true );
2504
+ assert checks .checkNodeConsistency (true );
2489
2505
return true ;
2490
2506
} else {
2491
- assert assertions . check (false );
2507
+ assert checks . checkNodeConsistency (false );
2492
2508
}
2493
2509
}
2494
2510
return false ;
0 commit comments