/*
 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.graalvm.compiler.nodes;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;

import org.graalvm.compiler.core.common.CompilationIdentifier;
import org.graalvm.compiler.core.common.cfg.BlockMap;
import org.graalvm.compiler.core.common.type.Stamp;
import org.graalvm.compiler.debug.JavaMethodContext;
import org.graalvm.compiler.graph.Graph;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeMap;
import org.graalvm.compiler.graph.spi.SimplifierTool;
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.cfg.Block;
import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
import org.graalvm.compiler.nodes.spi.VirtualizableAllocation;
import org.graalvm.compiler.nodes.util.GraphUtil;

import jdk.vm.ci.meta.Assumptions;
import jdk.vm.ci.meta.Assumptions.Assumption;
import jdk.vm.ci.meta.DefaultProfilingInfo;
import jdk.vm.ci.meta.JavaMethod;
import jdk.vm.ci.meta.ProfilingInfo;
import jdk.vm.ci.meta.ResolvedJavaField;
import jdk.vm.ci.meta.ResolvedJavaMethod;
import jdk.vm.ci.meta.SpeculationLog;
import jdk.vm.ci.meta.TriState;
import jdk.vm.ci.runtime.JVMCICompiler;

A graph that contains at least one distinguished node : the start node. This node is the start of the control flow of the graph.
/** * A graph that contains at least one distinguished node : the {@link #start() start} node. This * node is the start of the control flow of the graph. */
public class StructuredGraph extends Graph implements JavaMethodContext {
The different stages of the compilation of a Graph regarding the status of guards, deoptimizations and framestates. The stage of a graph progresses monotonously.
/** * The different stages of the compilation of a {@link Graph} regarding the status of * {@link GuardNode guards}, {@link DeoptimizingNode deoptimizations} and {@link FrameState * framestates}. The stage of a graph progresses monotonously. * */
public enum GuardsStage {
During this stage, there can be floating DeoptimizingNode such as GuardNodes. New DeoptimizingNodes can be introduced without constraints. FrameState nodes are associated with StateSplit nodes.
/** * During this stage, there can be {@link FloatingNode floating} {@link DeoptimizingNode} * such as {@link GuardNode GuardNodes}. New {@link DeoptimizingNode DeoptimizingNodes} can * be introduced without constraints. {@link FrameState} nodes are associated with * {@link StateSplit} nodes. */
FLOATING_GUARDS,
During this stage, all DeoptimizingNodes must be fixed but new DeoptimizingNodes can still be introduced. FrameState nodes are still associated with StateSplit nodes.
/** * During this stage, all {@link DeoptimizingNode DeoptimizingNodes} must be * {@link FixedNode fixed} but new {@link DeoptimizingNode DeoptimizingNodes} can still be * introduced. {@link FrameState} nodes are still associated with {@link StateSplit} nodes. */
FIXED_DEOPTS,
During this stage, all DeoptimizingNodes must be fixed. New DeoptimizingNodes can not be introduced any more. FrameState nodes are now associated with DeoptimizingNode nodes.
/** * During this stage, all {@link DeoptimizingNode DeoptimizingNodes} must be * {@link FixedNode fixed}. New {@link DeoptimizingNode DeoptimizingNodes} can not be * introduced any more. {@link FrameState} nodes are now associated with * {@link DeoptimizingNode} nodes. */
AFTER_FSA; public boolean allowsFloatingGuards() { return this == FLOATING_GUARDS; } public boolean areFrameStatesAtDeopts() { return this == AFTER_FSA; } public boolean areFrameStatesAtSideEffects() { return !this.areFrameStatesAtDeopts(); } public boolean areDeoptsFixed() { return this.ordinal() >= FIXED_DEOPTS.ordinal(); } }
Constants denoting whether or not Assumptions can be made while processing a graph.
/** * Constants denoting whether or not {@link Assumption}s can be made while processing a graph. */
public enum AllowAssumptions { YES, NO; public static AllowAssumptions from(boolean flag) { return flag ? YES : NO; } } public static class ScheduleResult { private final ControlFlowGraph cfg; private final NodeMap<Block> nodeToBlockMap; private final BlockMap<List<Node>> blockToNodesMap; public ScheduleResult(ControlFlowGraph cfg, NodeMap<Block> nodeToBlockMap, BlockMap<List<Node>> blockToNodesMap) { this.cfg = cfg; this.nodeToBlockMap = nodeToBlockMap; this.blockToNodesMap = blockToNodesMap; } public ControlFlowGraph getCFG() { return cfg; } public NodeMap<Block> getNodeToBlockMap() { return nodeToBlockMap; } public BlockMap<List<Node>> getBlockToNodesMap() { return blockToNodesMap; } public List<Node> nodesFor(Block block) { return blockToNodesMap.get(block); } } public static final long INVALID_GRAPH_ID = -1; private static final AtomicLong uniqueGraphIds = new AtomicLong(); private StartNode start; private ResolvedJavaMethod rootMethod; private final long graphId; private final CompilationIdentifier compilationId; private final int entryBCI; private GuardsStage guardsStage = GuardsStage.FLOATING_GUARDS; private boolean isAfterFloatingReadPhase = false; private boolean hasValueProxies = true; private final boolean useProfilingInfo;
The assumptions made while constructing and transforming this graph.
/** * The assumptions made while constructing and transforming this graph. */
private final Assumptions assumptions; private final SpeculationLog speculationLog; private ScheduleResult lastSchedule;
Records the methods that were used while constructing this graph, one entry for each time a specific method is used.
/** * Records the methods that were used while constructing this graph, one entry for each time a * specific method is used. */
private final List<ResolvedJavaMethod> methods = new ArrayList<>();
Records the fields that were accessed while constructing this graph.
/** * Records the fields that were accessed while constructing this graph. */
private final Set<ResolvedJavaField> fields = new HashSet<>(); private enum UnsafeAccessState { NO_ACCESS, HAS_ACCESS, DISABLED } private UnsafeAccessState hasUnsafeAccess = UnsafeAccessState.NO_ACCESS;
Creates a new Graph containing a single AbstractBeginNode as the start node.
/** * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() * start} node. */
public StructuredGraph(AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { this(null, null, allowAssumptions, compilationId); } public static final boolean USE_PROFILING_INFO = true; public static final boolean NO_PROFILING_INFO = false; private static final SpeculationLog NO_SPECULATION_LOG = null;
Creates a new Graph containing a single AbstractBeginNode as the start node.
/** * Creates a new Graph containing a single {@link AbstractBeginNode} as the {@link #start() * start} node. */
public StructuredGraph(String name, ResolvedJavaMethod method, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { this(name, method, JVMCICompiler.INVOCATION_ENTRY_BCI, allowAssumptions, NO_SPECULATION_LOG, USE_PROFILING_INFO, compilationId); } public StructuredGraph(String name, ResolvedJavaMethod method, AllowAssumptions allowAssumptions, SpeculationLog speculationLog, CompilationIdentifier compilationId) { this(name, method, JVMCICompiler.INVOCATION_ENTRY_BCI, allowAssumptions, speculationLog, USE_PROFILING_INFO, compilationId); } public StructuredGraph(String name, ResolvedJavaMethod method, AllowAssumptions allowAssumptions, SpeculationLog speculationLog, boolean useProfilingInfo, CompilationIdentifier compilationId) { this(name, method, JVMCICompiler.INVOCATION_ENTRY_BCI, allowAssumptions, speculationLog, useProfilingInfo, compilationId); } public StructuredGraph(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, CompilationIdentifier compilationId) { this(null, method, JVMCICompiler.INVOCATION_ENTRY_BCI, allowAssumptions, NO_SPECULATION_LOG, USE_PROFILING_INFO, compilationId); } public StructuredGraph(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, boolean useProfilingInfo, CompilationIdentifier compilationId) { this(null, method, JVMCICompiler.INVOCATION_ENTRY_BCI, allowAssumptions, NO_SPECULATION_LOG, useProfilingInfo, compilationId); } public StructuredGraph(ResolvedJavaMethod method, AllowAssumptions allowAssumptions, SpeculationLog speculationLog, CompilationIdentifier compilationId) { this(null, method, JVMCICompiler.INVOCATION_ENTRY_BCI, allowAssumptions, speculationLog, USE_PROFILING_INFO, compilationId); } public StructuredGraph(ResolvedJavaMethod method, int entryBCI, AllowAssumptions allowAssumptions, SpeculationLog speculationLog, CompilationIdentifier compilationId) { this(null, method, entryBCI, allowAssumptions, speculationLog, USE_PROFILING_INFO, compilationId); } public StructuredGraph(ResolvedJavaMethod method, int entryBCI, AllowAssumptions allowAssumptions, SpeculationLog speculationLog, boolean useProfilingInfo, CompilationIdentifier compilationId) { this(null, method, entryBCI, allowAssumptions, speculationLog, useProfilingInfo, compilationId); } private StructuredGraph(String name, ResolvedJavaMethod method, int entryBCI, AllowAssumptions allowAssumptions, SpeculationLog speculationLog, boolean useProfilingInfo, CompilationIdentifier compilationId) { super(name); this.setStart(add(new StartNode())); this.rootMethod = method; this.graphId = uniqueGraphIds.incrementAndGet(); this.compilationId = compilationId; this.entryBCI = entryBCI; this.assumptions = allowAssumptions == AllowAssumptions.YES ? new Assumptions() : null; this.speculationLog = speculationLog; this.useProfilingInfo = useProfilingInfo; } public void setLastSchedule(ScheduleResult result) { lastSchedule = result; } public ScheduleResult getLastSchedule() { return lastSchedule; } public void clearLastSchedule() { setLastSchedule(null); } @Override public boolean maybeCompress() { if (super.maybeCompress()) { /* * The schedule contains a NodeMap which is unusable after compression. */ clearLastSchedule(); return true; } return false; } public Stamp getReturnStamp() { Stamp returnStamp = null; for (ReturnNode returnNode : getNodes(ReturnNode.TYPE)) { ValueNode result = returnNode.result(); if (result != null) { if (returnStamp == null) { returnStamp = result.stamp(); } else { returnStamp = returnStamp.meet(result.stamp()); } } } return returnStamp; } @Override public String toString() { StringBuilder buf = new StringBuilder(getClass().getSimpleName() + ":" + graphId); String sep = "{"; if (name != null) { buf.append(sep); buf.append(name); sep = ", "; } if (method() != null) { buf.append(sep); buf.append(method()); sep = ", "; } if (!sep.equals("{")) { buf.append("}"); } return buf.toString(); } public StartNode start() { return start; }
Gets the root method from which this graph was built.
Returns:null if this method was not built from a method or the method is not available
/** * Gets the root method from which this graph was built. * * @return null if this method was not built from a method or the method is not available */
public ResolvedJavaMethod method() { return rootMethod; } public int getEntryBCI() { return entryBCI; } public boolean isOSR() { return entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; } public long graphId() { return graphId; }
See Also:
  • CompilationIdentifier
/** * @see CompilationIdentifier */
public CompilationIdentifier compilationId() { return compilationId; } public void setStart(StartNode start) { this.start = start; }
Creates a copy of this graph.
Params:
  • newName – the name of the copy, used for debugging purposes (can be null)
  • duplicationMapCallback – consumer of the duplication map created during the copying
/** * Creates a copy of this graph. * * @param newName the name of the copy, used for debugging purposes (can be null) * @param duplicationMapCallback consumer of the duplication map created during the copying */
@Override protected Graph copy(String newName, Consumer<Map<Node, Node>> duplicationMapCallback) { return copy(newName, duplicationMapCallback, compilationId); } private StructuredGraph copy(String newName, Consumer<Map<Node, Node>> duplicationMapCallback, CompilationIdentifier newCompilationId) { AllowAssumptions allowAssumptions = AllowAssumptions.from(assumptions != null); StructuredGraph copy = new StructuredGraph(newName, method(), entryBCI, allowAssumptions, speculationLog, useProfilingInfo, newCompilationId); if (allowAssumptions == AllowAssumptions.YES && assumptions != null) { copy.assumptions.record(assumptions); } copy.hasUnsafeAccess = hasUnsafeAccess; copy.setGuardsStage(getGuardsStage()); copy.isAfterFloatingReadPhase = isAfterFloatingReadPhase; copy.hasValueProxies = hasValueProxies; Map<Node, Node> replacements = Node.newMap(); replacements.put(start, copy.start); Map<Node, Node> duplicates = copy.addDuplicates(getNodes(), this, this.getNodeCount(), replacements); if (duplicationMapCallback != null) { duplicationMapCallback.accept(duplicates); } return copy; } public final StructuredGraph copyWithIdentifier(CompilationIdentifier newCompilationId) { return copy(name, null, newCompilationId); } public ParameterNode getParameter(int index) { for (ParameterNode param : getNodes(ParameterNode.TYPE)) { if (param.index() == index) { return param; } } return null; } public Iterable<Invoke> getInvokes() { final Iterator<MethodCallTargetNode> callTargets = getNodes(MethodCallTargetNode.TYPE).iterator(); return new Iterable<Invoke>() { private Invoke next; @Override public Iterator<Invoke> iterator() { return new Iterator<Invoke>() { @Override public boolean hasNext() { if (next == null) { while (callTargets.hasNext()) { Invoke i = callTargets.next().invoke(); if (i != null) { next = i; return true; } } return false; } else { return true; } } @Override public Invoke next() { try { return next; } finally { next = null; } } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }; } public boolean hasLoops() { return hasNode(LoopBeginNode.TYPE); }
Unlinks a node from all its control flow neighbors and then removes it from its graph. The node must have no usages.
Params:
  • node – the node to be unlinked and removed
/** * Unlinks a node from all its control flow neighbors and then removes it from its graph. The * node must have no {@linkplain Node#usages() usages}. * * @param node the node to be unlinked and removed */
public void removeFixed(FixedWithNextNode node) { assert node != null; if (node instanceof AbstractBeginNode) { ((AbstractBeginNode) node).prepareDelete(); } assert node.hasNoUsages() : node + " " + node.usages().count() + ", " + node.usages().first(); GraphUtil.unlinkFixedNode(node); node.safeDelete(); } public void replaceFixed(FixedWithNextNode node, Node replacement) { if (replacement instanceof FixedWithNextNode) { replaceFixedWithFixed(node, (FixedWithNextNode) replacement); } else { assert replacement != null : "cannot replace " + node + " with null"; assert replacement instanceof FloatingNode : "cannot replace " + node + " with " + replacement; replaceFixedWithFloating(node, (FloatingNode) replacement); } } public void replaceFixedWithFixed(FixedWithNextNode node, FixedWithNextNode replacement) { assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement; FixedNode next = node.next(); node.setNext(null); replacement.setNext(next); node.replaceAndDelete(replacement); if (node == start) { setStart((StartNode) replacement); } } public void replaceFixedWithFloating(FixedWithNextNode node, FloatingNode replacement) { assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement; GraphUtil.unlinkFixedNode(node); node.replaceAtUsagesAndDelete(replacement); } public void removeSplit(ControlSplitNode node, AbstractBeginNode survivingSuccessor) { assert node != null; assert node.hasNoUsages(); assert survivingSuccessor != null; node.clearSuccessors(); node.replaceAtPredecessor(survivingSuccessor); node.safeDelete(); } public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor) { removeSplitPropagate(node, survivingSuccessor, null); } public void removeSplitPropagate(ControlSplitNode node, AbstractBeginNode survivingSuccessor, SimplifierTool tool) { assert node != null; assert node.hasNoUsages(); assert survivingSuccessor != null; List<Node> snapshot = node.successors().snapshot(); node.clearSuccessors(); node.replaceAtPredecessor(survivingSuccessor); node.safeDelete(); for (Node successor : snapshot) { if (successor != null && successor.isAlive()) { if (successor != survivingSuccessor) { GraphUtil.killCFG((FixedNode) successor, tool); } } } } public void replaceSplit(ControlSplitNode node, Node replacement, AbstractBeginNode survivingSuccessor) { if (replacement instanceof FixedWithNextNode) { replaceSplitWithFixed(node, (FixedWithNextNode) replacement, survivingSuccessor); } else { assert replacement != null : "cannot replace " + node + " with null"; assert replacement instanceof FloatingNode : "cannot replace " + node + " with " + replacement; replaceSplitWithFloating(node, (FloatingNode) replacement, survivingSuccessor); } } public void replaceSplitWithFixed(ControlSplitNode node, FixedWithNextNode replacement, AbstractBeginNode survivingSuccessor) { assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement; assert survivingSuccessor != null; node.clearSuccessors(); replacement.setNext(survivingSuccessor); node.replaceAndDelete(replacement); } public void replaceSplitWithFloating(ControlSplitNode node, FloatingNode replacement, AbstractBeginNode survivingSuccessor) { assert node != null && replacement != null && node.isAlive() && replacement.isAlive() : "cannot replace " + node + " with " + replacement; assert survivingSuccessor != null; node.clearSuccessors(); node.replaceAtPredecessor(survivingSuccessor); node.replaceAtUsagesAndDelete(replacement); } public void addAfterFixed(FixedWithNextNode node, FixedNode newNode) { assert node != null && newNode != null && node.isAlive() && newNode.isAlive() : "cannot add " + newNode + " after " + node; FixedNode next = node.next(); node.setNext(newNode); if (next != null) { assert newNode instanceof FixedWithNextNode; FixedWithNextNode newFixedWithNext = (FixedWithNextNode) newNode; assert newFixedWithNext.next() == null; newFixedWithNext.setNext(next); } } public void addBeforeFixed(FixedNode node, FixedWithNextNode newNode) { assert node != null && newNode != null && node.isAlive() && newNode.isAlive() : "cannot add " + newNode + " before " + node; assert node.predecessor() != null && node.predecessor() instanceof FixedWithNextNode : "cannot add " + newNode + " before " + node; assert newNode.next() == null : newNode; assert !(node instanceof AbstractMergeNode); FixedWithNextNode pred = (FixedWithNextNode) node.predecessor(); pred.setNext(newNode); newNode.setNext(node); } public void reduceDegenerateLoopBegin(LoopBeginNode begin) { assert begin.loopEnds().isEmpty() : "Loop begin still has backedges"; if (begin.forwardEndCount() == 1) { // bypass merge and remove reduceTrivialMerge(begin); } else { // convert to merge AbstractMergeNode merge = this.add(new MergeNode()); for (EndNode end : begin.forwardEnds()) { merge.addForwardEnd(end); } this.replaceFixedWithFixed(begin, merge); } } public void reduceTrivialMerge(AbstractMergeNode merge) { assert merge.forwardEndCount() == 1; assert !(merge instanceof LoopBeginNode) || ((LoopBeginNode) merge).loopEnds().isEmpty(); for (PhiNode phi : merge.phis().snapshot()) { assert phi.valueCount() == 1; ValueNode singleValue = phi.valueAt(0); if (phi.hasUsages()) { phi.replaceAtUsagesAndDelete(singleValue); } else { phi.safeDelete(); if (singleValue != null) { GraphUtil.tryKillUnused(singleValue); } } } // remove loop exits if (merge instanceof LoopBeginNode) { ((LoopBeginNode) merge).removeExits(); } AbstractEndNode singleEnd = merge.forwardEndAt(0); FixedNode sux = merge.next(); FrameState stateAfter = merge.stateAfter(); // evacuateGuards merge.prepareDelete((FixedNode) singleEnd.predecessor()); merge.safeDelete(); if (stateAfter != null && stateAfter.isAlive() && stateAfter.hasNoUsages()) { GraphUtil.killWithUnusedFloatingInputs(stateAfter); } if (sux == null) { singleEnd.replaceAtPredecessor(null); singleEnd.safeDelete(); } else { singleEnd.replaceAndDelete(sux); } } public GuardsStage getGuardsStage() { return guardsStage; } public void setGuardsStage(GuardsStage guardsStage) { assert guardsStage.ordinal() >= this.guardsStage.ordinal(); this.guardsStage = guardsStage; } public boolean isAfterFloatingReadPhase() { return isAfterFloatingReadPhase; } public void setAfterFloatingReadPhase(boolean state) { assert state : "cannot 'unapply' floating read phase on graph"; isAfterFloatingReadPhase = state; } public boolean hasValueProxies() { return hasValueProxies; } public void setHasValueProxies(boolean state) { assert !state : "cannot 'unapply' value proxy removal on graph"; hasValueProxies = state; }
Determines if ProfilingInfo is used during construction of this graph.
/** * Determines if {@link ProfilingInfo} is used during construction of this graph. */
public boolean useProfilingInfo() { return useProfilingInfo; }
Gets the profiling info for the root method of this graph.
/** * Gets the profiling info for the {@linkplain #method() root method} of this graph. */
public ProfilingInfo getProfilingInfo() { return getProfilingInfo(method()); }
Gets the profiling info for a given method that is or will be part of this graph, taking into account useProfilingInfo().
/** * Gets the profiling info for a given method that is or will be part of this graph, taking into * account {@link #useProfilingInfo()}. */
public ProfilingInfo getProfilingInfo(ResolvedJavaMethod m) { if (useProfilingInfo && m != null) { return m.getProfilingInfo(); } else { return DefaultProfilingInfo.get(TriState.UNKNOWN); } }
Gets the object for recording assumptions while constructing of this graph.
Returns:null if assumptions cannot be made for this graph
/** * Gets the object for recording assumptions while constructing of this graph. * * @return {@code null} if assumptions cannot be made for this graph */
public Assumptions getAssumptions() { return assumptions; }
Gets the methods that were inlined while constructing this graph.
/** * Gets the methods that were inlined while constructing this graph. */
public List<ResolvedJavaMethod> getMethods() { return methods; }
Records that method was used to build this graph.
/** * Records that {@code method} was used to build this graph. */
public void recordMethod(ResolvedJavaMethod method) { methods.add(method); }
Updates the methods used to build this graph with the methods used to build another graph.
/** * Updates the {@linkplain #getMethods() methods} used to build this graph with the methods used * to build another graph. */
public void updateMethods(StructuredGraph other) { assert this != other; this.methods.addAll(other.methods); }
Gets the fields that were accessed while constructing this graph.
/** * Gets the fields that were accessed while constructing this graph. */
public Set<ResolvedJavaField> getFields() { return fields; }
Records that field was accessed in this graph.
/** * Records that {@code field} was accessed in this graph. */
public void recordField(ResolvedJavaField field) { fields.add(field); }
Updates the fields of this graph with the accessed fields of another graph.
/** * Updates the {@linkplain #getFields() fields} of this graph with the accessed fields of * another graph. */
public void updateFields(StructuredGraph other) { assert this != other; this.fields.addAll(other.fields); }
Gets the input bytecode size from which this graph is constructed. This ignores how many bytecodes in each constituent method are actually parsed (which may be none for methods whose IR is retrieved from a cache or less than the full amount for any given method due to profile guided branch pruning).
/** * Gets the input bytecode {@linkplain ResolvedJavaMethod#getCodeSize() size} from which this * graph is constructed. This ignores how many bytecodes in each constituent method are actually * parsed (which may be none for methods whose IR is retrieved from a cache or less than the * full amount for any given method due to profile guided branch pruning). */
public int getBytecodeSize() { int res = 0; for (ResolvedJavaMethod e : methods) { res += e.getCodeSize(); } return res; }
Returns:true if the graph contains only a StartNode and ReturnNode
/** * * @return true if the graph contains only a {@link StartNode} and {@link ReturnNode} */
public boolean isTrivial() { return !(start.next() instanceof ReturnNode); } @Override public JavaMethod asJavaMethod() { return method(); } public boolean hasUnsafeAccess() { return hasUnsafeAccess == UnsafeAccessState.HAS_ACCESS; } public void markUnsafeAccess() { if (hasUnsafeAccess == UnsafeAccessState.DISABLED) { return; } hasUnsafeAccess = UnsafeAccessState.HAS_ACCESS; } public void disableUnsafeAccessTracking() { hasUnsafeAccess = UnsafeAccessState.DISABLED; } public boolean isUnsafeAccessTrackingEnabled() { return hasUnsafeAccess != UnsafeAccessState.DISABLED; } public SpeculationLog getSpeculationLog() { return speculationLog; } public final void clearAllStateAfter() { for (Node node : getNodes()) { if (node instanceof StateSplit) { FrameState stateAfter = ((StateSplit) node).stateAfter(); if (stateAfter != null) { ((StateSplit) node).setStateAfter(null); // 2 nodes referencing the same framestate if (stateAfter.isAlive()) { GraphUtil.killWithUnusedFloatingInputs(stateAfter); } } } } } public final boolean hasVirtualizableAllocation() { for (Node n : getNodes()) { if (n instanceof VirtualizableAllocation) { return true; } } return false; } }