001/* 002 * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.replacements; 024 025import static com.oracle.graal.java.BytecodeParser.Options.*; 026import static jdk.internal.jvmci.common.JVMCIError.*; 027 028import java.util.*; 029 030import jdk.internal.jvmci.code.*; 031import com.oracle.graal.debug.*; 032import jdk.internal.jvmci.meta.*; 033import jdk.internal.jvmci.options.*; 034 035import com.oracle.graal.compiler.common.type.*; 036import com.oracle.graal.graph.*; 037import com.oracle.graal.graph.spi.*; 038import com.oracle.graal.graphbuilderconf.*; 039import com.oracle.graal.graphbuilderconf.InlineInvokePlugin.InlineInfo; 040import com.oracle.graal.graphbuilderconf.InvocationPlugins.InvocationPluginReceiver; 041import com.oracle.graal.java.*; 042import com.oracle.graal.nodeinfo.*; 043import com.oracle.graal.nodes.*; 044import com.oracle.graal.nodes.CallTargetNode.InvokeKind; 045import com.oracle.graal.nodes.extended.*; 046import com.oracle.graal.nodes.java.*; 047import com.oracle.graal.nodes.spi.*; 048import com.oracle.graal.phases.common.inlining.*; 049 050/** 051 * A graph decoder that performs partial evaluation, i.e., that performs method inlining and 052 * canonicalization/simplification of nodes during decoding. 053 * 054 * Inlining and loop explosion are configured via the plugin mechanism also used by the 055 * {@link GraphBuilderPhase}. However, not all callback methods defined in 056 * {@link GraphBuilderContext} are available since decoding is more limited than graph building. 057 * 058 * The standard {@link Canonicalizable#canonical node canonicalization} interface is used to 059 * canonicalize nodes during decoding. Additionally, {@link IfNode branches} and 060 * {@link IntegerSwitchNode switches} with constant conditions are simplified. 061 */ 062public abstract class PEGraphDecoder extends SimplifyingGraphDecoder { 063 064 public static class Options { 065 @Option(help = "Maximum inlining depth during partial evaluation before reporting an infinite recursion")// 066 public static final OptionValue<Integer> InliningDepthError = new OptionValue<>(200); 067 } 068 069 protected class PEMethodScope extends MethodScope { 070 /** The state of the caller method. Only non-null during method inlining. */ 071 protected final PEMethodScope caller; 072 protected final LoopScope callerLoopScope; 073 protected final ResolvedJavaMethod method; 074 protected final InvokeData invokeData; 075 protected final int inliningDepth; 076 077 protected final LoopExplosionPlugin loopExplosionPlugin; 078 protected final InvocationPlugins invocationPlugins; 079 protected final InlineInvokePlugin[] inlineInvokePlugins; 080 protected final ParameterPlugin parameterPlugin; 081 protected final ValueNode[] arguments; 082 083 protected FrameState outerState; 084 protected FrameState exceptionState; 085 protected ExceptionPlaceholderNode exceptionPlaceholderNode; 086 protected BytecodePosition bytecodePosition; 087 088 protected PEMethodScope(StructuredGraph targetGraph, PEMethodScope caller, LoopScope callerLoopScope, EncodedGraph encodedGraph, ResolvedJavaMethod method, InvokeData invokeData, 089 int inliningDepth, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins, ParameterPlugin parameterPlugin, 090 ValueNode[] arguments) { 091 super(targetGraph, encodedGraph, loopExplosionKind(method, loopExplosionPlugin)); 092 093 this.caller = caller; 094 this.callerLoopScope = callerLoopScope; 095 this.method = method; 096 this.invokeData = invokeData; 097 this.inliningDepth = inliningDepth; 098 this.loopExplosionPlugin = loopExplosionPlugin; 099 this.invocationPlugins = invocationPlugins; 100 this.inlineInvokePlugins = inlineInvokePlugins; 101 this.parameterPlugin = parameterPlugin; 102 this.arguments = arguments; 103 } 104 105 public boolean isInlinedMethod() { 106 return caller != null; 107 } 108 109 public BytecodePosition getBytecodePosition() { 110 if (bytecodePosition == null) { 111 ensureOuterStateDecoded(this); 112 ensureExceptionStateDecoded(this); 113 bytecodePosition = InliningUtil.processBytecodePosition(invokeData.invoke, null); 114 } 115 return bytecodePosition; 116 } 117 } 118 119 protected class PENonAppendGraphBuilderContext implements GraphBuilderContext { 120 protected final PEMethodScope methodScope; 121 protected final Invoke invoke; 122 123 public PENonAppendGraphBuilderContext(PEMethodScope methodScope, Invoke invoke) { 124 this.methodScope = methodScope; 125 this.invoke = invoke; 126 } 127 128 @Override 129 public BailoutException bailout(String string) { 130 throw new BailoutException(string); 131 } 132 133 @Override 134 public StampProvider getStampProvider() { 135 return stampProvider; 136 } 137 138 @Override 139 public MetaAccessProvider getMetaAccess() { 140 return metaAccess; 141 } 142 143 @Override 144 public ConstantReflectionProvider getConstantReflection() { 145 return constantReflection; 146 } 147 148 @Override 149 public StructuredGraph getGraph() { 150 return methodScope.graph; 151 } 152 153 @Override 154 public int getDepth() { 155 return methodScope.inliningDepth; 156 } 157 158 @Override 159 public IntrinsicContext getIntrinsic() { 160 return null; 161 } 162 163 @Override 164 public <T extends ValueNode> T append(T value) { 165 throw unimplemented(); 166 } 167 168 @Override 169 public <T extends ValueNode> T recursiveAppend(T value) { 170 throw unimplemented(); 171 } 172 173 @Override 174 public void push(Kind kind, ValueNode value) { 175 throw unimplemented(); 176 } 177 178 @Override 179 public void handleReplacedInvoke(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, boolean inlineEverything) { 180 throw unimplemented(); 181 } 182 183 @Override 184 public void intrinsify(ResolvedJavaMethod targetMethod, ResolvedJavaMethod substitute, ValueNode[] args) { 185 throw unimplemented(); 186 } 187 188 @Override 189 public void setStateAfter(StateSplit stateSplit) { 190 throw unimplemented(); 191 } 192 193 @Override 194 public GraphBuilderContext getParent() { 195 throw unimplemented(); 196 } 197 198 @Override 199 public ResolvedJavaMethod getMethod() { 200 throw unimplemented(); 201 } 202 203 @Override 204 public int bci() { 205 return invoke.bci(); 206 } 207 208 @Override 209 public InvokeKind getInvokeKind() { 210 throw unimplemented(); 211 } 212 213 @Override 214 public JavaType getInvokeReturnType() { 215 throw unimplemented(); 216 } 217 } 218 219 protected class PEAppendGraphBuilderContext extends PENonAppendGraphBuilderContext { 220 protected FixedWithNextNode lastInstr; 221 protected ValueNode pushedNode; 222 223 public PEAppendGraphBuilderContext(PEMethodScope inlineScope, FixedWithNextNode lastInstr) { 224 super(inlineScope, inlineScope.invokeData.invoke); 225 this.lastInstr = lastInstr; 226 } 227 228 @Override 229 public void push(Kind kind, ValueNode value) { 230 if (pushedNode != null) { 231 throw unimplemented("Only one push is supported"); 232 } 233 pushedNode = value; 234 } 235 236 @Override 237 public void setStateAfter(StateSplit stateSplit) { 238 Node stateAfter = decodeFloatingNode(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId); 239 getGraph().add(stateAfter); 240 FrameState fs = (FrameState) handleFloatingNodeAfterAdd(methodScope.caller, methodScope.callerLoopScope, stateAfter); 241 stateSplit.setStateAfter(fs); 242 } 243 244 @Override 245 public <T extends ValueNode> T append(T v) { 246 if (v.graph() != null) { 247 return v; 248 } 249 T added = getGraph().addOrUnique(v); 250 if (added == v) { 251 updateLastInstruction(v); 252 } 253 return added; 254 } 255 256 @Override 257 public <T extends ValueNode> T recursiveAppend(T v) { 258 if (v.graph() != null) { 259 return v; 260 } 261 T added = getGraph().addOrUniqueWithInputs(v); 262 if (added == v) { 263 updateLastInstruction(v); 264 } 265 return added; 266 } 267 268 private <T extends ValueNode> void updateLastInstruction(T v) { 269 if (v instanceof FixedNode) { 270 FixedNode fixedNode = (FixedNode) v; 271 lastInstr.setNext(fixedNode); 272 if (fixedNode instanceof FixedWithNextNode) { 273 FixedWithNextNode fixedWithNextNode = (FixedWithNextNode) fixedNode; 274 assert fixedWithNextNode.next() == null : "cannot append instruction to instruction which isn't end"; 275 lastInstr = fixedWithNextNode; 276 } else { 277 lastInstr = null; 278 } 279 } 280 } 281 } 282 283 @NodeInfo 284 static class ExceptionPlaceholderNode extends ValueNode { 285 public static final NodeClass<ExceptionPlaceholderNode> TYPE = NodeClass.create(ExceptionPlaceholderNode.class); 286 287 public ExceptionPlaceholderNode() { 288 super(TYPE, StampFactory.object()); 289 } 290 } 291 292 public PEGraphDecoder(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, StampProvider stampProvider, Architecture architecture) { 293 super(metaAccess, constantReflection, stampProvider, true, architecture); 294 } 295 296 protected static LoopExplosionKind loopExplosionKind(ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin) { 297 if (loopExplosionPlugin == null) { 298 return LoopExplosionKind.NONE; 299 } else if (loopExplosionPlugin.shouldMergeExplosions(method)) { 300 return LoopExplosionKind.MERGE_EXPLODE; 301 } else if (loopExplosionPlugin.shouldExplodeLoops(method)) { 302 return LoopExplosionKind.FULL_EXPLODE; 303 } else { 304 return LoopExplosionKind.NONE; 305 } 306 } 307 308 public void decode(StructuredGraph targetGraph, ResolvedJavaMethod method, LoopExplosionPlugin loopExplosionPlugin, InvocationPlugins invocationPlugins, InlineInvokePlugin[] inlineInvokePlugins, 309 ParameterPlugin parameterPlugin) { 310 PEMethodScope methodScope = new PEMethodScope(targetGraph, null, null, lookupEncodedGraph(method, false), method, null, 0, loopExplosionPlugin, invocationPlugins, inlineInvokePlugins, 311 parameterPlugin, null); 312 decode(methodScope, null); 313 cleanupGraph(methodScope, null); 314 methodScope.graph.verify(); 315 } 316 317 @Override 318 protected void checkLoopExplosionIteration(MethodScope s, LoopScope loopScope) { 319 PEMethodScope methodScope = (PEMethodScope) s; 320 321 if (loopScope.loopIteration > MaximumLoopExplosionCount.getValue()) { 322 String message = "too many loop explosion iterations - does the explosion not terminate for method " + methodScope.method + "?"; 323 if (FailedLoopExplosionIsFatal.getValue()) { 324 throw new RuntimeException(message); 325 } else { 326 throw new BailoutException(message); 327 } 328 } 329 } 330 331 @Override 332 protected void handleInvoke(MethodScope s, LoopScope loopScope, InvokeData invokeData) { 333 PEMethodScope methodScope = (PEMethodScope) s; 334 335 /* 336 * Decode the call target, but do not add it to the graph yet. This avoids adding usages for 337 * all the arguments, which are expensive to remove again when we can inline the method. 338 */ 339 assert invokeData.invoke.callTarget() == null : "callTarget edge is ignored during decoding of Invoke"; 340 CallTargetNode callTarget = (CallTargetNode) decodeFloatingNode(methodScope, loopScope, invokeData.callTargetOrderId); 341 if (!(callTarget instanceof MethodCallTargetNode) || !trySimplifyInvoke(methodScope, loopScope, invokeData, (MethodCallTargetNode) callTarget)) { 342 343 /* We know that we need an invoke, so now we can add the call target to the graph. */ 344 methodScope.graph.add(callTarget); 345 registerNode(loopScope, invokeData.callTargetOrderId, callTarget, false, false); 346 super.handleInvoke(methodScope, loopScope, invokeData); 347 } 348 } 349 350 protected boolean trySimplifyInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) { 351 // attempt to devirtualize the call 352 ResolvedJavaMethod specialCallTarget = MethodCallTargetNode.findSpecialCallTarget(callTarget.invokeKind(), callTarget.receiver(), callTarget.targetMethod(), invokeData.contextType); 353 if (specialCallTarget != null) { 354 callTarget.setTargetMethod(specialCallTarget); 355 callTarget.setInvokeKind(InvokeKind.Special); 356 } 357 358 if (tryInvocationPlugin(methodScope, loopScope, invokeData, callTarget)) { 359 return true; 360 } 361 if (tryInline(methodScope, loopScope, invokeData, callTarget)) { 362 return true; 363 } 364 365 for (InlineInvokePlugin plugin : methodScope.inlineInvokePlugins) { 366 plugin.notifyNotInlined(new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke), callTarget.targetMethod(), invokeData.invoke); 367 } 368 return false; 369 } 370 371 protected boolean tryInvocationPlugin(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) { 372 if (methodScope.invocationPlugins == null) { 373 return false; 374 } 375 376 Invoke invoke = invokeData.invoke; 377 378 ResolvedJavaMethod targetMethod = callTarget.targetMethod(); 379 InvocationPlugin invocationPlugin = methodScope.invocationPlugins.lookupInvocation(targetMethod); 380 if (invocationPlugin == null) { 381 return false; 382 } 383 384 ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[0]); 385 FixedWithNextNode invokePredecessor = (FixedWithNextNode) invoke.asNode().predecessor(); 386 387 /* Remove invoke from graph so that invocation plugin can append nodes to the predecessor. */ 388 invoke.asNode().replaceAtPredecessor(null); 389 390 PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, loopScope, null, targetMethod, invokeData, methodScope.inliningDepth + 1, methodScope.loopExplosionPlugin, 391 methodScope.invocationPlugins, methodScope.inlineInvokePlugins, null, arguments); 392 PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, invokePredecessor); 393 InvocationPluginReceiver invocationPluginReceiver = new InvocationPluginReceiver(graphBuilderContext); 394 395 if (invocationPlugin.execute(graphBuilderContext, targetMethod, invocationPluginReceiver.init(targetMethod, arguments), arguments)) { 396 397 if (graphBuilderContext.lastInstr != null) { 398 registerNode(loopScope, invokeData.invokeOrderId, graphBuilderContext.pushedNode, true, true); 399 invoke.asNode().replaceAtUsages(graphBuilderContext.pushedNode); 400 graphBuilderContext.lastInstr.setNext(nodeAfterInvoke(methodScope, loopScope, invokeData, AbstractBeginNode.prevBegin(graphBuilderContext.lastInstr))); 401 } else { 402 assert graphBuilderContext.pushedNode == null : "Why push a node when the invoke does not return anyway?"; 403 invoke.asNode().replaceAtUsages(null); 404 } 405 406 deleteInvoke(invoke); 407 return true; 408 409 } else { 410 /* Intrinsification failed, restore original state: invoke is in Graph. */ 411 invokePredecessor.setNext(invoke.asNode()); 412 return false; 413 } 414 } 415 416 protected boolean tryInline(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, MethodCallTargetNode callTarget) { 417 if (!callTarget.invokeKind().isDirect()) { 418 return false; 419 } 420 421 ResolvedJavaMethod targetMethod = callTarget.targetMethod(); 422 if (!targetMethod.canBeInlined()) { 423 return false; 424 } 425 426 ValueNode[] arguments = callTarget.arguments().toArray(new ValueNode[0]); 427 GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, invokeData.invoke); 428 429 for (InlineInvokePlugin plugin : methodScope.inlineInvokePlugins) { 430 InlineInfo inlineInfo = plugin.shouldInlineInvoke(graphBuilderContext, targetMethod, arguments, callTarget.returnType()); 431 if (inlineInfo != null) { 432 if (inlineInfo.getMethodToInline() == null) { 433 return false; 434 } else { 435 return doInline(methodScope, loopScope, invokeData, inlineInfo, arguments); 436 } 437 } 438 } 439 return false; 440 } 441 442 protected boolean doInline(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, InlineInfo inlineInfo, ValueNode[] arguments) { 443 ResolvedJavaMethod inlineMethod = inlineInfo.getMethodToInline(); 444 EncodedGraph graphToInline = lookupEncodedGraph(inlineMethod, inlineInfo.isIntrinsic()); 445 if (graphToInline == null) { 446 return false; 447 } 448 449 if (methodScope.inliningDepth > Options.InliningDepthError.getValue()) { 450 throw tooDeepInlining(methodScope); 451 } 452 453 for (InlineInvokePlugin plugin : methodScope.inlineInvokePlugins) { 454 plugin.notifyBeforeInline(inlineMethod); 455 } 456 457 Invoke invoke = invokeData.invoke; 458 FixedNode invokeNode = invoke.asNode(); 459 FixedWithNextNode predecessor = (FixedWithNextNode) invokeNode.predecessor(); 460 invokeNode.replaceAtPredecessor(null); 461 462 PEMethodScope inlineScope = new PEMethodScope(methodScope.graph, methodScope, loopScope, graphToInline, inlineMethod, invokeData, methodScope.inliningDepth + 1, 463 methodScope.loopExplosionPlugin, methodScope.invocationPlugins, methodScope.inlineInvokePlugins, null, arguments); 464 /* Do the actual inlining by decoding the inlineMethod */ 465 decode(inlineScope, predecessor); 466 467 ValueNode exceptionValue = null; 468 if (inlineScope.unwindNode != null) { 469 exceptionValue = inlineScope.unwindNode.exception(); 470 } 471 UnwindNode unwindNode = inlineScope.unwindNode; 472 473 if (invoke instanceof InvokeWithExceptionNode) { 474 InvokeWithExceptionNode invokeWithException = ((InvokeWithExceptionNode) invoke); 475 assert invokeWithException.next() == null; 476 assert invokeWithException.exceptionEdge() == null; 477 478 if (unwindNode != null) { 479 assert unwindNode.predecessor() != null; 480 Node n = makeStubNode(methodScope, loopScope, invokeData.exceptionNextOrderId); 481 unwindNode.replaceAndDelete(n); 482 } 483 484 } else { 485 if (unwindNode != null && !unwindNode.isDeleted()) { 486 DeoptimizeNode deoptimizeNode = methodScope.graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateRecompile, DeoptimizationReason.NotCompiledExceptionHandler)); 487 unwindNode.replaceAndDelete(deoptimizeNode); 488 } 489 } 490 491 assert invoke.next() == null; 492 493 ValueNode returnValue; 494 List<ReturnNode> returnNodes = inlineScope.returnNodes; 495 if (!returnNodes.isEmpty()) { 496 if (returnNodes.size() == 1) { 497 ReturnNode returnNode = returnNodes.get(0); 498 returnValue = returnNode.result(); 499 FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, AbstractBeginNode.prevBegin(returnNode)); 500 returnNode.replaceAndDelete(n); 501 } else { 502 AbstractMergeNode merge = methodScope.graph.add(new MergeNode()); 503 merge.setStateAfter((FrameState) ensureNodeCreated(methodScope, loopScope, invokeData.stateAfterOrderId)); 504 returnValue = InliningUtil.mergeReturns(merge, returnNodes, null); 505 FixedNode n = nodeAfterInvoke(methodScope, loopScope, invokeData, merge); 506 merge.setNext(n); 507 } 508 } else { 509 returnValue = null; 510 } 511 invokeNode.replaceAtUsages(returnValue); 512 513 /* 514 * Usage the handles that we have on the return value and the exception to update the 515 * orderId->Node table. 516 */ 517 registerNode(loopScope, invokeData.invokeOrderId, returnValue, true, true); 518 if (invoke instanceof InvokeWithExceptionNode) { 519 registerNode(loopScope, invokeData.exceptionOrderId, exceptionValue, true, true); 520 } 521 if (inlineScope.exceptionPlaceholderNode != null) { 522 inlineScope.exceptionPlaceholderNode.replaceAtUsages(exceptionValue); 523 inlineScope.exceptionPlaceholderNode.safeDelete(); 524 } 525 deleteInvoke(invoke); 526 527 for (InlineInvokePlugin plugin : methodScope.inlineInvokePlugins) { 528 plugin.notifyAfterInline(inlineMethod); 529 } 530 531 if (Debug.isDumpEnabled() && DumpDuringGraphBuilding.getValue()) { 532 Debug.dump(methodScope.graph, "Inline finished: " + inlineMethod.getDeclaringClass().getUnqualifiedName() + "." + inlineMethod.getName()); 533 } 534 return true; 535 } 536 537 private static RuntimeException tooDeepInlining(PEMethodScope methodScope) { 538 HashMap<ResolvedJavaMethod, Integer> methodCounts = new HashMap<>(); 539 for (PEMethodScope cur = methodScope; cur != null; cur = cur.caller) { 540 Integer oldCount = methodCounts.get(cur.method); 541 methodCounts.put(cur.method, oldCount == null ? 1 : oldCount + 1); 542 } 543 544 List<Map.Entry<ResolvedJavaMethod, Integer>> methods = new ArrayList<>(methodCounts.entrySet()); 545 methods.sort((e1, e2) -> -Integer.compare(e1.getValue(), e2.getValue())); 546 547 StringBuilder msg = new StringBuilder("Too deep inlining, probably caused by recursive inlining. Inlined methods ordered by inlining frequency:"); 548 for (Map.Entry<ResolvedJavaMethod, Integer> entry : methods) { 549 msg.append(System.lineSeparator()).append(entry.getKey().format("%H.%n(%p) [")).append(entry.getValue()).append("]"); 550 } 551 throw new BailoutException(msg.toString()); 552 } 553 554 public FixedNode nodeAfterInvoke(PEMethodScope methodScope, LoopScope loopScope, InvokeData invokeData, AbstractBeginNode lastBlock) { 555 assert lastBlock.isAlive(); 556 FixedNode n; 557 if (invokeData.invoke instanceof InvokeWithExceptionNode) { 558 registerNode(loopScope, invokeData.nextOrderId, lastBlock, false, false); 559 n = makeStubNode(methodScope, loopScope, invokeData.nextNextOrderId); 560 } else { 561 n = makeStubNode(methodScope, loopScope, invokeData.nextOrderId); 562 } 563 return n; 564 } 565 566 private static void deleteInvoke(Invoke invoke) { 567 /* 568 * Clean up unused nodes. We cannot just call killCFG on the invoke node because that can 569 * kill too much: nodes that are decoded later can use values that appear unused by now. 570 */ 571 FrameState frameState = invoke.stateAfter(); 572 invoke.asNode().safeDelete(); 573 assert invoke.callTarget() == null : "must not have been added to the graph yet"; 574 if (frameState != null && frameState.hasNoUsages()) { 575 frameState.safeDelete(); 576 } 577 } 578 579 protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, boolean isIntrinsic); 580 581 @Override 582 protected void handleFixedNode(MethodScope s, LoopScope loopScope, int nodeOrderId, FixedNode node) { 583 PEMethodScope methodScope = (PEMethodScope) s; 584 if (node instanceof SimpleInfopointNode && methodScope.isInlinedMethod()) { 585 InliningUtil.processSimpleInfopoint(methodScope.invokeData.invoke, (SimpleInfopointNode) node, methodScope.getBytecodePosition()); 586 } 587 super.handleFixedNode(s, loopScope, nodeOrderId, node); 588 } 589 590 @Override 591 protected Node handleFloatingNodeBeforeAdd(MethodScope s, LoopScope loopScope, Node node) { 592 PEMethodScope methodScope = (PEMethodScope) s; 593 594 if (node instanceof ParameterNode) { 595 if (methodScope.arguments != null) { 596 Node result = methodScope.arguments[((ParameterNode) node).index()]; 597 assert result != null; 598 return result; 599 600 } else if (methodScope.parameterPlugin != null) { 601 GraphBuilderContext graphBuilderContext = new PENonAppendGraphBuilderContext(methodScope, null); 602 Node result = methodScope.parameterPlugin.interceptParameter(graphBuilderContext, ((ParameterNode) node).index(), ((ParameterNode) node).stamp()); 603 if (result != null) { 604 return result; 605 } 606 } 607 608 } 609 610 return super.handleFloatingNodeBeforeAdd(methodScope, loopScope, node); 611 } 612 613 protected void ensureOuterStateDecoded(PEMethodScope methodScope) { 614 if (methodScope.outerState == null && methodScope.caller != null) { 615 FrameState stateAtReturn = methodScope.invokeData.invoke.stateAfter(); 616 if (stateAtReturn == null) { 617 stateAtReturn = (FrameState) decodeFloatingNode(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId); 618 } 619 620 Kind invokeReturnKind = methodScope.invokeData.invoke.asNode().getKind(); 621 FrameState outerState = stateAtReturn.duplicateModified(methodScope.graph, methodScope.invokeData.invoke.bci(), stateAtReturn.rethrowException(), true, invokeReturnKind, null, null); 622 623 /* 624 * When the encoded graph has methods inlining, we can already have a proper caller 625 * state. If not, we set the caller state here. 626 */ 627 if (outerState.outerFrameState() == null && methodScope.caller != null) { 628 ensureOuterStateDecoded(methodScope.caller); 629 outerState.setOuterFrameState(methodScope.caller.outerState); 630 } 631 methodScope.outerState = outerState; 632 } 633 } 634 635 protected void ensureStateAfterDecoded(PEMethodScope methodScope) { 636 if (methodScope.invokeData.invoke.stateAfter() == null) { 637 methodScope.invokeData.invoke.setStateAfter((FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.stateAfterOrderId)); 638 } 639 } 640 641 protected void ensureExceptionStateDecoded(PEMethodScope methodScope) { 642 if (methodScope.exceptionState == null && methodScope.caller != null && methodScope.invokeData.invoke instanceof InvokeWithExceptionNode) { 643 ensureStateAfterDecoded(methodScope); 644 645 assert methodScope.exceptionPlaceholderNode == null; 646 methodScope.exceptionPlaceholderNode = methodScope.graph.add(new ExceptionPlaceholderNode()); 647 registerNode(methodScope.callerLoopScope, methodScope.invokeData.exceptionOrderId, methodScope.exceptionPlaceholderNode, false, false); 648 FrameState exceptionState = (FrameState) ensureNodeCreated(methodScope.caller, methodScope.callerLoopScope, methodScope.invokeData.exceptionStateOrderId); 649 650 if (exceptionState.outerFrameState() == null && methodScope.caller != null) { 651 ensureOuterStateDecoded(methodScope.caller); 652 exceptionState.setOuterFrameState(methodScope.caller.outerState); 653 } 654 methodScope.exceptionState = exceptionState; 655 } 656 } 657 658 @Override 659 protected Node handleFloatingNodeAfterAdd(MethodScope s, LoopScope loopScope, Node node) { 660 PEMethodScope methodScope = (PEMethodScope) s; 661 662 if (methodScope.isInlinedMethod()) { 663 if (node instanceof FrameState) { 664 FrameState frameState = (FrameState) node; 665 666 ensureOuterStateDecoded(methodScope); 667 if (frameState.bci < 0) { 668 ensureExceptionStateDecoded(methodScope); 669 } 670 return InliningUtil.processFrameState(frameState, methodScope.invokeData.invoke, methodScope.method, methodScope.exceptionState, methodScope.outerState, true); 671 672 } else if (node instanceof MonitorIdNode) { 673 ensureOuterStateDecoded(methodScope); 674 InliningUtil.processMonitorId(methodScope.outerState, (MonitorIdNode) node); 675 return node; 676 } 677 } 678 679 return node; 680 } 681}