1 /* 2 * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.phases.common; 24 25 import java.util.LinkedList; 26 import java.util.List; 27 28 import org.graalvm.compiler.core.common.cfg.Loop; 29 import org.graalvm.compiler.core.common.type.StampFactory; 30 import org.graalvm.compiler.nodes.AbstractDeoptimizeNode; 31 import org.graalvm.compiler.nodes.AbstractMergeNode; 32 import org.graalvm.compiler.nodes.DynamicDeoptimizeNode; 33 import org.graalvm.compiler.nodes.EndNode; 34 import org.graalvm.compiler.nodes.FixedNode; 35 import org.graalvm.compiler.nodes.FrameState; 36 import org.graalvm.compiler.nodes.LoopBeginNode; 37 import org.graalvm.compiler.nodes.LoopExitNode; 38 import org.graalvm.compiler.nodes.MergeNode; 39 import org.graalvm.compiler.nodes.PhiNode; 40 import org.graalvm.compiler.nodes.StructuredGraph; 41 import org.graalvm.compiler.nodes.ValueNode; 42 import org.graalvm.compiler.nodes.ValuePhiNode; 43 import org.graalvm.compiler.nodes.cfg.Block; 44 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph; 45 import org.graalvm.compiler.phases.BasePhase; 46 import org.graalvm.compiler.phases.tiers.MidTierContext; 47 48 /** 49 * This phase tries to find {@link AbstractDeoptimizeNode DeoptimizeNodes} which use the same 50 * {@link FrameState} and merges them together. 51 */ 52 public class DeoptimizationGroupingPhase extends BasePhase<MidTierContext> { 53 54 @Override 55 protected void run(StructuredGraph graph, MidTierContext context) { 56 ControlFlowGraph cfg = null; 57 for (FrameState fs : graph.getNodes(FrameState.TYPE)) { 58 FixedNode target = null; 59 PhiNode reasonActionPhi = null; 60 PhiNode speculationPhi = null; 61 List<AbstractDeoptimizeNode> obsoletes = null; 62 for (AbstractDeoptimizeNode deopt : fs.usages().filter(AbstractDeoptimizeNode.class)) { 63 if (target == null) { 64 target = deopt; 65 } else { 66 if (cfg == null) { 67 cfg = ControlFlowGraph.compute(graph, true, true, false, false); 68 } 69 AbstractMergeNode merge; 70 if (target instanceof AbstractDeoptimizeNode) { 71 merge = graph.add(new MergeNode()); 72 EndNode firstEnd = graph.add(new EndNode()); 73 ValueNode actionAndReason = ((AbstractDeoptimizeNode) target).getActionAndReason(context.getMetaAccess()); 74 ValueNode speculation = ((AbstractDeoptimizeNode) target).getSpeculation(context.getMetaAccess()); 75 reasonActionPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(actionAndReason.getStackKind()), merge)); 76 speculationPhi = graph.addWithoutUnique(new ValuePhiNode(StampFactory.forKind(speculation.getStackKind()), merge)); 77 merge.addForwardEnd(firstEnd); 78 reasonActionPhi.addInput(actionAndReason); 79 speculationPhi.addInput(speculation); 80 target.replaceAtPredecessor(firstEnd); 81 82 exitLoops((AbstractDeoptimizeNode) target, firstEnd, cfg); 83 84 merge.setNext(graph.add(new DynamicDeoptimizeNode(reasonActionPhi, speculationPhi))); 85 obsoletes = new LinkedList<>(); 86 obsoletes.add((AbstractDeoptimizeNode) target); 87 target = merge; 88 } else { 89 merge = (AbstractMergeNode) target; 90 } 91 EndNode newEnd = graph.add(new EndNode()); 92 merge.addForwardEnd(newEnd); 93 reasonActionPhi.addInput(deopt.getActionAndReason(context.getMetaAccess())); 94 speculationPhi.addInput(deopt.getSpeculation(context.getMetaAccess())); 95 deopt.replaceAtPredecessor(newEnd); 96 exitLoops(deopt, newEnd, cfg); 97 obsoletes.add(deopt); 98 } 99 } 100 if (obsoletes != null) { 101 ((DynamicDeoptimizeNode) ((AbstractMergeNode) target).next()).setStateBefore(fs); 102 for (AbstractDeoptimizeNode obsolete : obsoletes) { 103 obsolete.safeDelete(); 104 } 105 } 106 } 107 } 108 109 private static void exitLoops(AbstractDeoptimizeNode deopt, EndNode end, ControlFlowGraph cfg) { 110 Block block = cfg.blockFor(deopt); 111 Loop<Block> loop = block.getLoop(); 112 while (loop != null) { 113 end.graph().addBeforeFixed(end, end.graph().add(new LoopExitNode((LoopBeginNode) loop.getHeader().getBeginNode()))); 114 loop = loop.getParent(); 115 } 116 } 117 118 @Override 119 public float codeSizeIncrease() { 120 return 2.5f; 121 } 122 }