001/* 002 * Copyright (c) 2011, 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.hotspot.phases; 024 025import static com.oracle.graal.phases.common.DeadCodeEliminationPhase.Optionality.*; 026import jdk.internal.jvmci.code.*; 027import jdk.internal.jvmci.common.*; 028import jdk.internal.jvmci.compiler.Compiler; 029import com.oracle.graal.debug.*; 030 031import com.oracle.graal.graph.*; 032import com.oracle.graal.graph.iterators.*; 033import com.oracle.graal.loop.*; 034import com.oracle.graal.nodeinfo.*; 035import com.oracle.graal.nodes.*; 036import com.oracle.graal.nodes.extended.*; 037import com.oracle.graal.nodes.util.*; 038import com.oracle.graal.phases.*; 039import com.oracle.graal.phases.common.*; 040 041public class OnStackReplacementPhase extends Phase { 042 043 @Override 044 protected void run(StructuredGraph graph) { 045 if (graph.getEntryBCI() == Compiler.INVOCATION_ENTRY_BCI) { 046 // This happens during inlining in a OSR method, because the same phase plan will be 047 // used. 048 return; 049 } 050 Debug.dump(graph, "OnStackReplacement initial"); 051 EntryMarkerNode osr; 052 do { 053 NodeIterable<EntryMarkerNode> osrNodes = graph.getNodes(EntryMarkerNode.TYPE); 054 osr = osrNodes.first(); 055 if (osr == null) { 056 throw new BailoutException("No OnStackReplacementNode generated"); 057 } 058 if (osrNodes.count() > 1) { 059 throw new JVMCIError("Multiple OnStackReplacementNodes generated"); 060 } 061 if (osr.stateAfter().locksSize() != 0) { 062 throw new BailoutException("OSR with locks not supported"); 063 } 064 if (osr.stateAfter().stackSize() != 0) { 065 throw new BailoutException("OSR with stack entries not supported: %s", osr.stateAfter().toString(Verbosity.Debugger)); 066 } 067 LoopEx osrLoop = null; 068 LoopsData loops = new LoopsData(graph); 069 for (LoopEx loop : loops.loops()) { 070 if (loop.inside().contains(osr)) { 071 osrLoop = loop; 072 break; 073 } 074 } 075 if (osrLoop == null) { 076 break; 077 } 078 079 LoopTransformations.peel(osrLoop); 080 osr.replaceAtUsages(InputType.Guard, AbstractBeginNode.prevBegin((FixedNode) osr.predecessor())); 081 for (Node usage : osr.usages().snapshot()) { 082 ProxyNode proxy = (ProxyNode) usage; 083 proxy.replaceAndDelete(proxy.value()); 084 } 085 GraphUtil.removeFixedWithUnusedInputs(osr); 086 Debug.dump(graph, "OnStackReplacement loop peeling result"); 087 } while (true); 088 089 FrameState osrState = osr.stateAfter(); 090 osr.setStateAfter(null); 091 OSRStartNode osrStart = graph.add(new OSRStartNode()); 092 StartNode start = graph.start(); 093 FixedNode next = osr.next(); 094 osr.setNext(null); 095 osrStart.setNext(next); 096 graph.setStart(osrStart); 097 osrStart.setStateAfter(osrState); 098 099 for (int i = 0; i < osrState.localsSize(); i++) { 100 ValueNode value = osrState.localAt(i); 101 if (value instanceof ProxyNode) { 102 ProxyNode proxy = (ProxyNode) value; 103 /* 104 * we need to drop the stamp since the types we see during OSR may be too precise 105 * (if a branch was not parsed for example). 106 */ 107 proxy.replaceAndDelete(graph.unique(new OSRLocalNode(i, proxy.stamp().unrestricted()))); 108 } else { 109 assert value == null || value instanceof OSRLocalNode; 110 } 111 } 112 osr.replaceAtUsages(InputType.Guard, osrStart); 113 assert osr.usages().isEmpty(); 114 115 GraphUtil.killCFG(start); 116 117 Debug.dump(graph, "OnStackReplacement result"); 118 new DeadCodeEliminationPhase(Required).apply(graph); 119 } 120}