001/*
002 * Copyright (c) 2011, 2012, 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.virtual.phases.ea;
024
025import static com.oracle.graal.compiler.common.GraalOptions.*;
026
027import java.util.*;
028
029import jdk.internal.jvmci.meta.*;
030
031import com.oracle.graal.graph.*;
032import com.oracle.graal.graph.spi.*;
033import com.oracle.graal.nodes.*;
034import com.oracle.graal.nodes.calc.*;
035import com.oracle.graal.nodes.java.*;
036import com.oracle.graal.nodes.spi.*;
037import com.oracle.graal.nodes.virtual.*;
038
039class VirtualizerToolImpl implements VirtualizerTool, CanonicalizerTool {
040
041    private final MetaAccessProvider metaAccess;
042    private final ConstantReflectionProvider constantReflection;
043    private final PartialEscapeClosure<?> closure;
044
045    VirtualizerToolImpl(MetaAccessProvider metaAccess, ConstantReflectionProvider constantReflection, PartialEscapeClosure<?> closure) {
046        this.metaAccess = metaAccess;
047        this.constantReflection = constantReflection;
048        this.closure = closure;
049    }
050
051    private boolean deleted;
052    private PartialEscapeBlockState<?> state;
053    private ValueNode current;
054    private FixedNode position;
055    private GraphEffectList effects;
056
057    @Override
058    public MetaAccessProvider getMetaAccessProvider() {
059        return metaAccess;
060    }
061
062    public ConstantReflectionProvider getConstantReflectionProvider() {
063        return constantReflection;
064    }
065
066    public void reset(PartialEscapeBlockState<?> newState, ValueNode newCurrent, FixedNode newPosition, GraphEffectList newEffects) {
067        deleted = false;
068        state = newState;
069        current = newCurrent;
070        position = newPosition;
071        effects = newEffects;
072    }
073
074    public boolean isDeleted() {
075        return deleted;
076    }
077
078    @Override
079    public ValueNode getAlias(ValueNode value) {
080        return closure.getAliasAndResolve(state, value);
081    }
082
083    public ValueNode getEntry(VirtualObjectNode virtualObject, int index) {
084        return state.getObjectState(virtualObject).getEntry(index);
085    }
086
087    @Override
088    public void setVirtualEntry(VirtualObjectNode virtual, int index, ValueNode value, boolean unsafe) {
089        ObjectState obj = state.getObjectState(virtual);
090        assert obj.isVirtual() : "not virtual: " + obj;
091        ValueNode newValue;
092        if (value == null) {
093            newValue = null;
094        } else {
095            newValue = closure.getAliasAndResolve(state, value);
096            assert unsafe || obj.getEntry(index) == null || obj.getEntry(index).getKind() == newValue.getKind() || (isObjectEntry(obj.getEntry(index)) && isObjectEntry(newValue));
097        }
098        state.setEntry(virtual.getObjectId(), index, newValue);
099    }
100
101    public void setEnsureVirtualized(VirtualObjectNode virtualObject, boolean ensureVirtualized) {
102        int id = virtualObject.getObjectId();
103        state.setEnsureVirtualized(id, ensureVirtualized);
104    }
105
106    public boolean getEnsureVirtualized(VirtualObjectNode virtualObject) {
107        return state.getObjectState(virtualObject).getEnsureVirtualized();
108    }
109
110    private static boolean isObjectEntry(ValueNode value) {
111        return value.getKind() == Kind.Object || value instanceof VirtualObjectNode;
112    }
113
114    @Override
115    public void replaceWithVirtual(VirtualObjectNode virtual) {
116        closure.addAndMarkAlias(virtual, current);
117        effects.deleteNode(current);
118        deleted = true;
119    }
120
121    @Override
122    public void replaceWithValue(ValueNode replacement) {
123        effects.replaceAtUsages(current, closure.getScalarAlias(replacement));
124        closure.addScalarAlias(current, replacement);
125        deleted = true;
126    }
127
128    @Override
129    public void delete() {
130        effects.deleteNode(current);
131        deleted = true;
132    }
133
134    @Override
135    public void replaceFirstInput(Node oldInput, Node replacement) {
136        effects.replaceFirstInput(current, oldInput, replacement);
137    }
138
139    @Override
140    public void addNode(ValueNode node) {
141        if (node instanceof FloatingNode) {
142            effects.addFloatingNode(node, "VirtualizerTool");
143        } else {
144            effects.addFixedNodeBefore((FixedWithNextNode) node, position);
145        }
146    }
147
148    @Override
149    public void createVirtualObject(VirtualObjectNode virtualObject, ValueNode[] entryState, List<MonitorIdNode> locks, boolean ensureVirtualized) {
150        VirtualUtil.trace("{{%s}} ", current);
151        if (!virtualObject.isAlive()) {
152            effects.addFloatingNode(virtualObject, "newVirtualObject");
153        }
154        for (int i = 0; i < entryState.length; i++) {
155            ValueNode entry = entryState[i];
156            entryState[i] = entry instanceof VirtualObjectNode ? entry : closure.getAliasAndResolve(state, entry);
157        }
158        int id = virtualObject.getObjectId();
159        if (id == -1) {
160            id = closure.virtualObjects.size();
161            closure.virtualObjects.add(virtualObject);
162            virtualObject.setObjectId(id);
163        }
164        state.addObject(id, new ObjectState(entryState, locks, ensureVirtualized));
165        closure.addAndMarkAlias(virtualObject, virtualObject);
166        PartialEscapeClosure.METRIC_ALLOCATION_REMOVED.increment();
167    }
168
169    @Override
170    public int getMaximumEntryCount() {
171        return MaximumEscapeAnalysisArrayLength.getValue();
172    }
173
174    @Override
175    public void replaceWith(ValueNode node) {
176        if (node instanceof VirtualObjectNode) {
177            replaceWithVirtual((VirtualObjectNode) node);
178        } else {
179            replaceWithValue(node);
180        }
181    }
182
183    public void addLock(VirtualObjectNode virtualObject, MonitorIdNode monitorId) {
184        int id = virtualObject.getObjectId();
185        state.addLock(id, monitorId);
186    }
187
188    public MonitorIdNode removeLock(VirtualObjectNode virtualObject) {
189        int id = virtualObject.getObjectId();
190        return state.removeLock(id);
191    }
192
193    public MetaAccessProvider getMetaAccess() {
194        return metaAccess;
195    }
196
197    public ConstantReflectionProvider getConstantReflection() {
198        return constantReflection;
199    }
200
201    public boolean canonicalizeReads() {
202        return false;
203    }
204
205    @Override
206    public boolean allUsagesAvailable() {
207        return true;
208    }
209}