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}