|
70 | 70 | import jdk.graal.compiler.core.common.type.StampFactory;
|
71 | 71 | import jdk.graal.compiler.core.common.type.StampPair;
|
72 | 72 | import jdk.graal.compiler.core.common.type.TypeReference;
|
| 73 | +import jdk.graal.compiler.core.common.util.CompilationAlarm; |
73 | 74 | import jdk.graal.compiler.debug.Assertions;
|
74 | 75 | import jdk.graal.compiler.debug.CounterKey;
|
75 | 76 | import jdk.graal.compiler.debug.DebugCloseable;
|
@@ -528,6 +529,15 @@ protected SnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, Lo
|
528 | 529 | this.type = type;
|
529 | 530 | }
|
530 | 531 |
|
| 532 | + public boolean isPrivateLocation(LocationIdentity identity) { |
| 533 | + for (LocationIdentity i : privateLocations) { |
| 534 | + if (i.equals(identity)) { |
| 535 | + return true; |
| 536 | + } |
| 537 | + } |
| 538 | + return false; |
| 539 | + } |
| 540 | + |
531 | 541 | public ResolvedJavaMethod getMethod() {
|
532 | 542 | return method;
|
533 | 543 | }
|
@@ -983,7 +993,8 @@ public SnippetTemplate template(CoreProviders context, ValueNode replacee, final
|
983 | 993 | try (DebugContext debug = context.getReplacements().openSnippetDebugContext("SnippetTemplate_", args.cacheKey.method, outer, options)) {
|
984 | 994 | try (DebugCloseable a = SnippetTemplateCreationTime.start(outer);
|
985 | 995 | DebugCloseable a2 = args.info.creationTimer.start(outer);
|
986 |
| - DebugContext.Scope s = debug.scope("SnippetSpecialization", args.info.method)) { |
| 996 | + DebugContext.Scope s = debug.scope("SnippetSpecialization", args.info.method); |
| 997 | + CompilationAlarm alarm = CompilationAlarm.disable()) { |
987 | 998 | SnippetTemplates.increment(outer);
|
988 | 999 | args.info.creationCounter.increment(outer);
|
989 | 1000 | OptionValues snippetOptions = new OptionValues(options, GraalOptions.TraceInlining, GraalOptions.TraceInliningForStubsAndSnippets.getValue(options),
|
@@ -1062,7 +1073,7 @@ protected SnippetTemplate(OptionValues options,
|
1062 | 1073 | SnippetReflectionProvider snippetReflection,
|
1063 | 1074 | Arguments args,
|
1064 | 1075 | boolean trackNodeSourcePosition,
|
1065 |
| - Node replacee, |
| 1076 | + ValueNode replacee, |
1066 | 1077 | PhaseSuite<CoreProviders> midTierPreLoweringPhases,
|
1067 | 1078 | PhaseSuite<CoreProviders> midTierPostLoweringPhases) {
|
1068 | 1079 | this.snippetReflection = snippetReflection;
|
@@ -1236,10 +1247,9 @@ protected SnippetTemplate(OptionValues options,
|
1236 | 1247 | boolean needsCE = false;
|
1237 | 1248 | LoweringTool.LoweringStage loweringStage = args.cacheKey.loweringStage;
|
1238 | 1249 | for (Node n : snippetCopy.getNodes()) {
|
1239 |
| - if (n instanceof AbstractNewObjectNode || n instanceof AbstractBoxingNode) { |
| 1250 | + if (!needsPEA && (n instanceof AbstractNewObjectNode || n instanceof AbstractBoxingNode)) { |
1240 | 1251 | needsPEA = true;
|
1241 |
| - break; |
1242 |
| - } else if (n instanceof LogicNode) { |
| 1252 | + } else if (!needsCE && n instanceof LogicNode) { |
1243 | 1253 | needsCE = true;
|
1244 | 1254 | }
|
1245 | 1255 | }
|
@@ -1328,11 +1338,18 @@ protected SnippetTemplate(OptionValues options,
|
1328 | 1338 |
|
1329 | 1339 | if (node instanceof StateSplit) {
|
1330 | 1340 | StateSplit stateSplit = (StateSplit) node;
|
1331 |
| - FrameState frameState = stateSplit.stateAfter(); |
1332 |
| - if (stateSplit.hasSideEffect()) { |
| 1341 | + |
| 1342 | + // The normal side effect check doesn't understand private locations, so |
| 1343 | + // explicitly filter those accesses from the side effects. |
| 1344 | + boolean hasSideEffect = stateSplit.hasSideEffect(); |
| 1345 | + if (hasSideEffect && stateSplit instanceof MemoryAccess && MemoryKill.isSingleMemoryKill(stateSplit.asNode())) { |
| 1346 | + hasSideEffect = !info.isPrivateLocation(((SingleMemoryKill) stateSplit).getKilledLocationIdentity()); |
| 1347 | + } |
| 1348 | + if (hasSideEffect) { |
1333 | 1349 | curSideEffectNodes.add((StateSplit) node);
|
1334 | 1350 | }
|
1335 | 1351 | if (info.type == SnippetType.INLINED_SNIPPET) {
|
| 1352 | + FrameState frameState = stateSplit.stateAfter(); |
1336 | 1353 | if (frameState != null) {
|
1337 | 1354 | stateSplit.setStateAfter(null);
|
1338 | 1355 | }
|
@@ -1495,6 +1512,10 @@ protected SnippetTemplate(OptionValues options,
|
1495 | 1512 | }
|
1496 | 1513 | }
|
1497 | 1514 |
|
| 1515 | + if (!curSideEffectNodes.isEmpty()) { |
| 1516 | + checkSideEffects(replacee); |
| 1517 | + } |
| 1518 | + |
1498 | 1519 | debug.dump(DebugContext.INFO_LEVEL, snippet, "SnippetTemplate final state");
|
1499 | 1520 | assert snippet.verify();
|
1500 | 1521 | this.snippet.freeze();
|
@@ -2129,21 +2150,7 @@ public UnmodifiableEconomicMap<Node, Node> instantiate(MetaAccessProvider metaAc
|
2129 | 2150 | FixedNode firstCFGNodeDuplicate = (FixedNode) duplicates.get(firstCFGNode);
|
2130 | 2151 | replacee.replaceAtPredecessor(firstCFGNodeDuplicate);
|
2131 | 2152 |
|
2132 |
| - if (replacee.graph().getGuardsStage().areFrameStatesAtSideEffects()) { |
2133 |
| - boolean replaceeHasSideEffect = replacee instanceof StateSplit && ((StateSplit) replacee).hasSideEffect(); |
2134 |
| - boolean replacementHasSideEffect = !sideEffectNodes.isEmpty(); |
2135 |
| - |
2136 |
| - /* |
2137 |
| - * Following cases are allowed: Either the replacee and replacement don't have |
2138 |
| - * side-effects or the replacee has and the replacement hasn't (lowered to something |
2139 |
| - * without a side-effect which is fine regarding correctness) or both have |
2140 |
| - * side-effects, under which conditions also merges should have states. |
2141 |
| - */ |
2142 |
| - |
2143 |
| - if (replacementHasSideEffect) { |
2144 |
| - GraalError.guarantee(replaceeHasSideEffect, "Lowering node %s without side-effect to snippet %s with sideeffects=%s", replacee, info, this.sideEffectNodes); |
2145 |
| - } |
2146 |
| - } |
| 2153 | + checkSideEffects(replacee); |
2147 | 2154 |
|
2148 | 2155 | updateStamps(replacee, duplicates);
|
2149 | 2156 |
|
@@ -2316,6 +2323,22 @@ public static FixedNode walkBackToExceptionEdgeStart(FixedNode start) {
|
2316 | 2323 | return null;
|
2317 | 2324 | }
|
2318 | 2325 |
|
| 2326 | + /** |
| 2327 | + * Check that either the replacee and replacement don't have side effects or the replacee does |
| 2328 | + * and the replacement doesn't (lowered to something without a side effect which is fine |
| 2329 | + * regarding correctness) or both have side effects, under which conditions also merges should |
| 2330 | + * have states. |
| 2331 | + */ |
| 2332 | + private void checkSideEffects(ValueNode replacee) { |
| 2333 | + if (replacee.graph().getGuardsStage().areFrameStatesAtSideEffects()) { |
| 2334 | + boolean replaceeHasSideEffect = replacee instanceof StateSplit && ((StateSplit) replacee).hasSideEffect(); |
| 2335 | + boolean replacementHasSideEffect = !sideEffectNodes.isEmpty(); |
| 2336 | + if (replacementHasSideEffect) { |
| 2337 | + GraalError.guarantee(replaceeHasSideEffect, "Lowering node %s without side effect to snippet %s with side effects=%s", replacee, info, this.sideEffectNodes); |
| 2338 | + } |
| 2339 | + } |
| 2340 | + } |
| 2341 | + |
2319 | 2342 | /**
|
2320 | 2343 | * Searches for {@link WithExceptionNode} reachable from the {@link UnwindNode} and marks them
|
2321 | 2344 | * as {@linkplain WithExceptionNode#replaceWithNonThrowing() non-throwing}.
|
|
0 commit comments