001/* 002 * Copyright (c) 2013, 2013, 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.phases.common; 024 025import java.util.*; 026 027import jdk.internal.jvmci.common.*; 028 029import com.oracle.graal.graph.*; 030import com.oracle.graal.graph.iterators.*; 031import com.oracle.graal.nodes.*; 032import com.oracle.graal.nodes.StructuredGraph.GuardsStage; 033import com.oracle.graal.nodes.util.*; 034import com.oracle.graal.phases.*; 035import com.oracle.graal.phases.graph.*; 036import com.oracle.graal.phases.graph.ReentrantNodeIterator.NodeIteratorClosure; 037 038/** 039 * This phase transfers {@link FrameState} nodes from {@link StateSplit} nodes to 040 * {@link DeoptimizingNode DeoptimizingNodes}. 041 * 042 * This allow to enter the {@link GuardsStage#AFTER_FSA AFTER_FSA} stage of the graph where no new 043 * node that may cause deoptimization can be introduced anymore. 044 * <p> 045 * This Phase processes the graph in post order, assigning the {@link FrameState} from the last 046 * {@link StateSplit} node to {@link DeoptimizingNode DeoptimizingNodes}. 047 */ 048public class FrameStateAssignmentPhase extends Phase { 049 050 private static class FrameStateAssignmentClosure extends NodeIteratorClosure<FrameState> { 051 052 @Override 053 protected FrameState processNode(FixedNode node, FrameState previousState) { 054 FrameState currentState = previousState; 055 if (node instanceof DeoptimizingNode.DeoptBefore) { 056 DeoptimizingNode.DeoptBefore deopt = (DeoptimizingNode.DeoptBefore) node; 057 if (deopt.canDeoptimize() && deopt.stateBefore() == null) { 058 JVMCIError.guarantee(currentState != null, "no FrameState at DeoptimizingNode %s", deopt); 059 deopt.setStateBefore(currentState); 060 } 061 } 062 063 if (node instanceof StateSplit) { 064 StateSplit stateSplit = (StateSplit) node; 065 FrameState stateAfter = stateSplit.stateAfter(); 066 if (stateAfter != null) { 067 currentState = stateAfter; 068 stateSplit.setStateAfter(null); 069 } 070 } 071 072 if (node instanceof DeoptimizingNode.DeoptDuring) { 073 DeoptimizingNode.DeoptDuring deopt = (DeoptimizingNode.DeoptDuring) node; 074 if (deopt.canDeoptimize()) { 075 JVMCIError.guarantee(currentState != null, "no FrameState at DeoptimizingNode %s", deopt); 076 deopt.computeStateDuring(currentState); 077 } 078 } 079 080 if (node instanceof DeoptimizingNode.DeoptAfter) { 081 DeoptimizingNode.DeoptAfter deopt = (DeoptimizingNode.DeoptAfter) node; 082 if (deopt.canDeoptimize() && deopt.stateAfter() == null) { 083 JVMCIError.guarantee(currentState != null, "no FrameState at DeoptimizingNode %s", deopt); 084 deopt.setStateAfter(currentState); 085 } 086 } 087 088 return currentState; 089 } 090 091 @Override 092 protected FrameState merge(AbstractMergeNode merge, List<FrameState> states) { 093 FrameState singleFrameState = singleFrameState(states); 094 return singleFrameState == null ? merge.stateAfter() : singleFrameState; 095 } 096 097 @Override 098 protected FrameState afterSplit(AbstractBeginNode node, FrameState oldState) { 099 return oldState; 100 } 101 102 @Override 103 protected Map<LoopExitNode, FrameState> processLoop(LoopBeginNode loop, FrameState initialState) { 104 return ReentrantNodeIterator.processLoop(this, loop, initialState).exitStates; 105 } 106 } 107 108 @Override 109 protected void run(StructuredGraph graph) { 110 assert !graph.getGuardsStage().allowsFloatingGuards() && checkFixedDeopts(graph); 111 if (graph.getGuardsStage().areFrameStatesAtSideEffects()) { 112 ReentrantNodeIterator.apply(new FrameStateAssignmentClosure(), graph.start(), null); 113 graph.setGuardsStage(GuardsStage.AFTER_FSA); 114 graph.getNodes(FrameState.TYPE).filter(state -> state.hasNoUsages()).forEach(GraphUtil::killWithUnusedFloatingInputs); 115 } 116 } 117 118 private static boolean checkFixedDeopts(StructuredGraph graph) { 119 NodePredicate isFloatingNode = GraphUtil.isFloatingNode(); 120 for (Node n : graph.getNodes().filterInterface(DeoptimizingNode.class)) { 121 if (((DeoptimizingNode) n).canDeoptimize() && isFloatingNode.apply(n)) { 122 return false; 123 } 124 } 125 return true; 126 } 127 128 private static FrameState singleFrameState(List<FrameState> states) { 129 FrameState singleState = states.get(0); 130 for (int i = 1; i < states.size(); ++i) { 131 if (states.get(i) != singleState) { 132 return null; 133 } 134 } 135 return singleState; 136 } 137}