| /* |
| * Copyright (c) 2011, 2016, 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.virtual.phases.ea; |
| |
| import static org.graalvm.compiler.core.common.GraalOptions.MaximumEscapeAnalysisArrayLength; |
| |
| import java.util.List; |
| |
| import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; |
| import org.graalvm.compiler.graph.Node; |
| import org.graalvm.compiler.graph.spi.CanonicalizerTool; |
| import org.graalvm.compiler.nodes.FixedNode; |
| import org.graalvm.compiler.nodes.FixedWithNextNode; |
| import org.graalvm.compiler.nodes.ValueNode; |
| import org.graalvm.compiler.nodes.calc.FloatingNode; |
| import org.graalvm.compiler.nodes.java.MonitorIdNode; |
| import org.graalvm.compiler.nodes.spi.LoweringProvider; |
| import org.graalvm.compiler.nodes.spi.VirtualizerTool; |
| import org.graalvm.compiler.nodes.virtual.VirtualObjectNode; |
| |
| import jdk.vm.ci.meta.Assumptions; |
| import jdk.vm.ci.meta.ConstantReflectionProvider; |
| import jdk.vm.ci.meta.JavaKind; |
| import jdk.vm.ci.meta.MetaAccessProvider; |
| |
| class VirtualizerToolImpl implements VirtualizerTool, CanonicalizerTool { |
| |
| private final MetaAccessProvider metaAccess; |
| private final ConstantReflectionProvider constantReflection; |
| private final ConstantFieldProvider constantFieldProvider; |
| private final PartialEscapeClosure<?> closure; |
| private final Assumptions assumptions; |
| private final LoweringProvider loweringProvider; |
| |
| VirtualizerToolImpl(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, PartialEscapeClosure<?> closure, |
| Assumptions assumptions, LoweringProvider loweringProvider) { |
| this.metaAccess = metaAccess; |
| this.constantReflection = constantReflection; |
| this.constantFieldProvider = constantFieldProvider; |
| this.closure = closure; |
| this.assumptions = assumptions; |
| this.loweringProvider = loweringProvider; |
| } |
| |
| private boolean deleted; |
| private PartialEscapeBlockState<?> state; |
| private ValueNode current; |
| private FixedNode position; |
| private GraphEffectList effects; |
| |
| @Override |
| public MetaAccessProvider getMetaAccessProvider() { |
| return metaAccess; |
| } |
| |
| @Override |
| public ConstantReflectionProvider getConstantReflectionProvider() { |
| return constantReflection; |
| } |
| |
| @Override |
| public ConstantFieldProvider getConstantFieldProvider() { |
| return constantFieldProvider; |
| } |
| |
| public void reset(PartialEscapeBlockState<?> newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) { |
| deleted = false; |
| state = newState; |
| current = newCurrent; |
| position = newPosition; |
| effects = newEffects; |
| } |
| |
| public boolean isDeleted() { |
| return deleted; |
| } |
| |
| @Override |
| public ValueNode getAlias(ValueNode value) { |
| return closure.getAliasAndResolve(state, value); |
| } |
| |
| @Override |
| public ValueNode getEntry(VirtualObjectNode virtualObject, int index) { |
| return state.getObjectState(virtualObject).getEntry(index); |
| } |
| |
| @Override |
| public void setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value, boolean unsafe) { |
| ObjectState obj = state.getObjectState(virtual); |
| assert obj.isVirtual() : "not virtual: " + obj; |
| ValueNode newValue; |
| if (value == null) { |
| newValue = null; |
| } else { |
| newValue = closure.getAliasAndResolve(state, value); |
| assert unsafe || obj.getEntry(index) == null || obj.getEntry(index).getStackKind() == newValue.getStackKind() || (isObjectEntry(obj.getEntry(index)) && isObjectEntry(newValue)); |
| } |
| state.setEntry(virtual.getObjectId(), index, newValue); |
| } |
| |
| @Override |
| public void setEnsureVirtualized(VirtualObjectNode virtualObject, boolean ensureVirtualized) { |
| int id = virtualObject.getObjectId(); |
| state.setEnsureVirtualized(id, ensureVirtualized); |
| } |
| |
| @Override |
| public boolean getEnsureVirtualized(VirtualObjectNode virtualObject) { |
| return state.getObjectState(virtualObject).getEnsureVirtualized(); |
| } |
| |
| private static boolean isObjectEntry(ValueNode value) { |
| return value.getStackKind() == JavaKind.Object || value instanceof VirtualObjectNode; |
| } |
| |
| @Override |
| public void replaceWithVirtual(VirtualObjectNode virtual) { |
| closure.addAndMarkAlias(virtual, current); |
| effects.deleteNode(current); |
| deleted = true; |
| } |
| |
| @Override |
| public void replaceWithValue(ValueNode replacement) { |
| effects.replaceAtUsages(current, closure.getScalarAlias(replacement)); |
| closure.addScalarAlias(current, replacement); |
| deleted = true; |
| } |
| |
| @Override |
| public void delete() { |
| effects.deleteNode(current); |
| deleted = true; |
| } |
| |
| @Override |
| public void replaceFirstInput(Node oldInput, Node replacement) { |
| effects.replaceFirstInput(current, oldInput, replacement); |
| } |
| |
| @Override |
| public void addNode(ValueNode node) { |
| if (node instanceof FloatingNode) { |
| effects.addFloatingNode(node, "VirtualizerTool"); |
| } else { |
| effects.addFixedNodeBefore((FixedWithNextNode) node, position); |
| } |
| } |
| |
| @Override |
| public void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, List<MonitorIdNode> locks, boolean ensureVirtualized) { |
| VirtualUtil.trace("{{%s}} ", current); |
| if (!virtualObject.isAlive()) { |
| effects.addFloatingNode(virtualObject, "newVirtualObject"); |
| } |
| for (int i = 0; i < entryState.length; i++) { |
| ValueNode entry = entryState[i]; |
| entryState[i] = entry instanceof VirtualObjectNode ? entry : closure.getAliasAndResolve(state, entry); |
| } |
| int id = virtualObject.getObjectId(); |
| if (id == -1) { |
| id = closure.virtualObjects.size(); |
| closure.virtualObjects.add(virtualObject); |
| virtualObject.setObjectId(id); |
| } |
| state.addObject(id, new ObjectState(entryState, locks, ensureVirtualized)); |
| closure.addAndMarkAlias(virtualObject, virtualObject); |
| PartialEscapeClosure.COUNTER_ALLOCATION_REMOVED.increment(); |
| } |
| |
| @Override |
| public int getMaximumEntryCount() { |
| return MaximumEscapeAnalysisArrayLength.getValue(); |
| } |
| |
| @Override |
| public void replaceWith(ValueNode node) { |
| if (node instanceof VirtualObjectNode) { |
| replaceWithVirtual((VirtualObjectNode) node); |
| } else { |
| replaceWithValue(node); |
| } |
| } |
| |
| @Override |
| public boolean ensureMaterialized(VirtualObjectNode virtualObject) { |
| return closure.ensureMaterialized(state, virtualObject.getObjectId(), position, effects, PartialEscapeClosure.COUNTER_MATERIALIZATIONS_UNHANDLED); |
| } |
| |
| @Override |
| public void addLock(VirtualObjectNode virtualObject, MonitorIdNode monitorId) { |
| int id = virtualObject.getObjectId(); |
| state.addLock(id, monitorId); |
| } |
| |
| @Override |
| public MonitorIdNode removeLock(VirtualObjectNode virtualObject) { |
| int id = virtualObject.getObjectId(); |
| return state.removeLock(id); |
| } |
| |
| @Override |
| public MetaAccessProvider getMetaAccess() { |
| return metaAccess; |
| } |
| |
| @Override |
| public ConstantReflectionProvider getConstantReflection() { |
| return constantReflection; |
| } |
| |
| @Override |
| public boolean canonicalizeReads() { |
| return false; |
| } |
| |
| @Override |
| public boolean allUsagesAvailable() { |
| return true; |
| } |
| |
| @Override |
| public Assumptions getAssumptions() { |
| return assumptions; |
| } |
| |
| @Override |
| public boolean supportSubwordCompare(int bits) { |
| if (loweringProvider != null) { |
| return loweringProvider.supportSubwordCompare(bits); |
| } else { |
| return false; |
| } |
| } |
| } |