view graal/com.oracle.graal.virtual/src/com/oracle/graal/virtual/phases/ea/BlockState.java @ 6650:ea38da80dd29

refactor PEA into separate classes
author Lukas Stadler <lukas.stadler@jku.at>
date Tue, 30 Oct 2012 13:54:39 +0100
parents
children b01f9c391e17
line wrap: on
line source

/*
 * Copyright (c) 2011, 2012, 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 com.oracle.graal.virtual.phases.ea;

import static com.oracle.graal.virtual.phases.ea.PartialEscapeAnalysisPhase.*;

import java.util.*;

import com.oracle.graal.api.code.*;
import com.oracle.graal.api.meta.*;
import com.oracle.graal.graph.*;
import com.oracle.graal.nodes.*;
import com.oracle.graal.nodes.virtual.*;
import com.oracle.graal.phases.graph.ReentrantBlockIterator.MergeableBlockState;
import com.oracle.graal.virtual.nodes.*;

class BlockState extends MergeableBlockState<BlockState> {

    final HashMap<VirtualObjectNode, ObjectState> objectStates = new HashMap<>();
    final HashMap<ValueNode, VirtualObjectNode> objectAliases = new HashMap<>();
    final HashMap<ValueNode, ValueNode> scalarAliases = new HashMap<>();

    public BlockState() {
    }

    public BlockState(BlockState other) {
        for (Map.Entry<VirtualObjectNode, ObjectState> entry : other.objectStates.entrySet()) {
            objectStates.put(entry.getKey(), entry.getValue().clone());
        }
        for (Map.Entry<ValueNode, VirtualObjectNode> entry : other.objectAliases.entrySet()) {
            objectAliases.put(entry.getKey(), entry.getValue());
        }
        for (Map.Entry<ValueNode, ValueNode> entry : other.scalarAliases.entrySet()) {
            scalarAliases.put(entry.getKey(), entry.getValue());
        }
    }

    public ObjectState objectState(VirtualObjectNode object) {
        assert objectStates.containsKey(object);
        return objectStates.get(object);
    }

    public ObjectState objectStateOptional(VirtualObjectNode object) {
        return objectStates.get(object);
    }

    public ObjectState objectState(ValueNode value) {
        VirtualObjectNode object = objectAliases.get(value);
        return object == null ? null : objectState(object);
    }

    @Override
    public BlockState cloneState() {
        return new BlockState(this);
    }

    public void materializeBefore(FixedNode fixed, VirtualObjectNode virtual, GraphEffectList materializeEffects) {
        HashSet<VirtualObjectNode> deferred = new HashSet<>();
        GraphEffectList deferredStores = new GraphEffectList();
        materializeChangedBefore(fixed, virtual, deferred, deferredStores, materializeEffects);
        materializeEffects.addAll(deferredStores);
    }

    private void materializeChangedBefore(FixedNode fixed, VirtualObjectNode virtual, HashSet<VirtualObjectNode> deferred, GraphEffectList deferredStores, GraphEffectList materializeEffects) {
        trace("materializing %s at %s", virtual, fixed);
        ObjectState obj = objectState(virtual);
        if (obj.lockCount > 0 && obj.virtual.type().isArrayClass()) {
            throw new BailoutException("array materialized with lock");
        }

        MaterializeObjectNode materialize = new MaterializeObjectNode(virtual, obj.lockCount > 0);
        ValueNode[] values = new ValueNode[obj.fieldState.length];
        materialize.setProbability(fixed.probability());
        ValueNode[] fieldState = obj.fieldState;
        obj.fieldState = null;
        obj.materializedValue = materialize;
        deferred.add(virtual);
        for (int i = 0; i < fieldState.length; i++) {
            ObjectState valueObj = objectState(fieldState[i]);
            if (valueObj != null) {
                if (valueObj.materializedValue == null) {
                    materializeChangedBefore(fixed, valueObj.virtual, deferred, deferredStores, materializeEffects);
                }
                if (deferred.contains(valueObj.virtual)) {
                    Kind fieldKind;
                    CyclicMaterializeStoreNode store;
                    if (virtual instanceof VirtualArrayNode) {
                        store = new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, i);
                        fieldKind = ((VirtualArrayNode) virtual).componentType().getKind();
                    } else {
                        VirtualInstanceNode instanceObject = (VirtualInstanceNode) virtual;
                        store = new CyclicMaterializeStoreNode(materialize, valueObj.materializedValue, instanceObject.field(i));
                        fieldKind = instanceObject.field(i).getType().getKind();
                    }
                    deferredStores.addFixedNodeBefore(store, fixed);
                    values[i] = ConstantNode.defaultForKind(fieldKind, fixed.graph());
                } else {
                    values[i] = valueObj.materializedValue;
                }
            } else {
                values[i] = fieldState[i];
            }
        }
        deferred.remove(virtual);

        materializeEffects.addMaterialization(materialize, fixed, values);
    }

    void addAndMarkAlias(VirtualObjectNode virtual, ValueNode node, NodeBitMap usages) {
        objectAliases.put(node, virtual);
        for (Node usage : node.usages()) {
            markVirtualUsages(usage, usages);
        }
    }

    private void markVirtualUsages(Node node, NodeBitMap usages) {
        if (!usages.isNew(node)) {
            usages.mark(node);
        }
        if (node instanceof VirtualState) {
            for (Node usage : node.usages()) {
                markVirtualUsages(usage, usages);
            }
        }
    }

    public void addObject(VirtualObjectNode virtual, ObjectState state) {
        objectStates.put(virtual, state);
    }

    public void addScalarAlias(ValueNode alias, ValueNode value) {
        scalarAliases.put(alias, value);
    }

    public ValueNode scalarAlias(ValueNode alias) {
        ValueNode result = scalarAliases.get(alias);
        return result == null ? alias : result;
    }

    public Iterable<ObjectState> states() {
        return objectStates.values();
    }

    @Override
    public String toString() {
        return objectStates.toString();
    }
}