use of org.graalvm.compiler.nodes.virtual.VirtualObjectState in project graal by oracle.
the class ObjectState method createEscapeObjectState.
public EscapeObjectState createEscapeObjectState(DebugContext debug, MetaAccessExtensionProvider metaAccessExtensionProvider, VirtualObjectNode virtual) {
GET_ESCAPED_OBJECT_STATE.increment(debug);
if (cachedState == null) {
CREATE_ESCAPED_OBJECT_STATE.increment(debug);
if (isVirtual()) {
/*
* Clear out entries that are default values anyway.
*
* TODO: this should be propagated into ObjectState.entries, but that will take some
* more refactoring.
*/
ValueNode[] newEntries = entries.clone();
for (int i = 0; i < newEntries.length; i++) {
if (newEntries[i].asJavaConstant() == JavaConstant.defaultForKind(virtual.entryKind(metaAccessExtensionProvider, i).getStackKind())) {
newEntries[i] = null;
}
}
cachedState = new VirtualObjectState(virtual, newEntries);
} else {
cachedState = new MaterializedObjectState(virtual, materializedValue);
}
}
return cachedState;
}
use of org.graalvm.compiler.nodes.virtual.VirtualObjectState in project graal by oracle.
the class DebugInfoBuilder method toJavaValue.
protected JavaValue toJavaValue(ValueNode value) {
try {
if (value instanceof VirtualObjectNode) {
VirtualObjectNode obj = (VirtualObjectNode) value;
EscapeObjectState state = objectStates.get(obj);
if (state == null && obj.entryCount() > 0) {
// null states occur for objects with 0 fields
throw new GraalError("no mapping found for virtual object %s", obj);
}
if (state instanceof MaterializedObjectState) {
return toJavaValue(((MaterializedObjectState) state).materializedValue());
} else {
assert obj.entryCount() == 0 || state instanceof VirtualObjectState;
VirtualObject vobject = virtualObjects.get(obj);
if (vobject == null) {
boolean isAutoBox = obj instanceof VirtualBoxingNode;
vobject = GraalServices.createVirtualObject(obj.type(), virtualObjects.size(), isAutoBox);
virtualObjects.put(obj, vobject);
pendingVirtualObjects.add(obj);
}
STATE_VIRTUAL_OBJECTS.increment(debug);
return vobject;
}
} else {
// Remove proxies from constants so the constant can be directly embedded.
ValueNode unproxied = GraphUtil.unproxify(value);
if (unproxied instanceof ConstantNode) {
STATE_CONSTANTS.increment(debug);
return unproxied.asJavaConstant();
} else if (value != null) {
STATE_VARIABLES.increment(debug);
Value operand = nodeValueMap.operand(value);
if (operand instanceof ConstantValue && ((ConstantValue) operand).isJavaConstant()) {
return ((ConstantValue) operand).getJavaConstant();
} else if (LIRValueUtil.isVariable(operand)) {
return LIRValueUtil.asVariable(operand);
} else {
assert operand instanceof RegisterValue : operand + " for " + value;
return (JavaValue) operand;
}
} else {
// return a dummy value because real value not needed
STATE_ILLEGALS.increment(debug);
return Value.ILLEGAL;
}
}
} catch (GraalError e) {
throw e.addContext("toValue: ", value);
}
}
use of org.graalvm.compiler.nodes.virtual.VirtualObjectState in project graal by oracle.
the class DebugInfoBuilder method build.
public LIRFrameState build(NodeWithState node, FrameState topState, LabelRef exceptionEdge, JavaConstant deoptReasonAndAction, JavaConstant deoptSpeculation) {
assert virtualObjects.size() == 0;
assert objectStates.size() == 0;
assert pendingVirtualObjects.size() == 0;
// collect all VirtualObjectField instances:
FrameState current = topState;
do {
if (current.virtualObjectMappingCount() > 0) {
for (EscapeObjectState state : current.virtualObjectMappings()) {
if (!objectStates.containsKey(state.object())) {
if (!(state instanceof MaterializedObjectState) || ((MaterializedObjectState) state).materializedValue() != state.object()) {
objectStates.put(state.object(), state);
}
}
}
}
current = current.outerFrameState();
} while (current != null);
assert verifyFrameState(node, topState);
BytecodeFrame frame = computeFrameForState(node, topState);
VirtualObject[] virtualObjectsArray = null;
if (virtualObjects.size() != 0) {
// fill in the VirtualObject values
VirtualObjectNode vobjNode;
while ((vobjNode = pendingVirtualObjects.poll()) != null) {
VirtualObject vobjValue = virtualObjects.get(vobjNode);
assert vobjValue.getValues() == null;
JavaValue[] values;
JavaKind[] slotKinds;
int entryCount = vobjNode.entryCount();
if (entryCount == 0) {
values = NO_JAVA_VALUES;
slotKinds = NO_JAVA_KINDS;
} else {
values = new JavaValue[entryCount];
slotKinds = new JavaKind[entryCount];
}
if (values.length > 0) {
VirtualObjectState currentField = (VirtualObjectState) objectStates.get(vobjNode);
assert currentField != null;
int pos = 0;
for (int i = 0; i < entryCount; i++) {
ValueNode value = currentField.values().get(i);
if (value == null) {
JavaKind entryKind = vobjNode.entryKind(metaAccessExtensionProvider, i);
values[pos] = JavaConstant.defaultForKind(entryKind.getStackKind());
slotKinds[pos] = entryKind.getStackKind();
pos++;
} else if (!value.isConstant() || value.asJavaConstant().getJavaKind() != JavaKind.Illegal) {
values[pos] = toJavaValue(value);
slotKinds[pos] = toSlotKind(value);
pos++;
} else {
assert value.getStackKind() == JavaKind.Illegal;
ValueNode previousValue = currentField.values().get(i - 1);
assert (previousValue != null && (previousValue.getStackKind().needsTwoSlots()) || vobjNode.isVirtualByteArray(metaAccessExtensionProvider)) : vobjNode + " " + i + " " + previousValue + " " + currentField.values().snapshot();
if (vobjNode.isVirtualByteArray(metaAccessExtensionProvider)) {
/*
* Let Illegals pass through to help knowing the number of bytes to
* write. For example, writing a short to index 2 of a byte array of
* size 6 would look like, in debug info:
*
* {b0, b1, INT(...), ILLEGAL, b4, b5}
*
* Thus, from the VM, we can simply count the number of illegals to
* restore the byte count.
*/
values[pos] = Value.ILLEGAL;
slotKinds[pos] = JavaKind.Illegal;
pos++;
} else if (previousValue == null || !previousValue.getStackKind().needsTwoSlots()) {
// Don't allow the IllegalConstant to leak into the debug info
JavaKind entryKind = vobjNode.entryKind(metaAccessExtensionProvider, i);
values[pos] = JavaConstant.defaultForKind(entryKind.getStackKind());
slotKinds[pos] = entryKind.getStackKind();
pos++;
}
}
}
if (pos != entryCount) {
values = Arrays.copyOf(values, pos);
slotKinds = Arrays.copyOf(slotKinds, pos);
}
}
assert checkValues(vobjValue.getType(), values, slotKinds);
vobjValue.setValues(values, slotKinds);
}
virtualObjectsArray = new VirtualObject[virtualObjects.size()];
int index = 0;
for (VirtualObject value : virtualObjects.getValues()) {
virtualObjectsArray[index++] = value;
}
virtualObjects.clear();
}
objectStates.clear();
if (deoptReasonAndAction == null && deoptSpeculation == null) {
return new LIRFrameState(frame, virtualObjectsArray, exceptionEdge);
} else {
return new ImplicitLIRFrameState(frame, virtualObjectsArray, exceptionEdge, deoptReasonAndAction, deoptSpeculation);
}
}
use of org.graalvm.compiler.nodes.virtual.VirtualObjectState in project graal by oracle.
the class CompileQueue method transplantEscapeAnalysisState.
/**
* The nodes produced by escape analysis need some manual patching: escape analysis requires
* that {@link ResolvedJavaType#getInstanceFields} is stable and uses the index of a field in
* that array also to index its own data structures. But {@link AnalysisType} and
* {@link HostedType} cannot return fields in the same order: Fields that are not seen as
* reachable by the static analysis are removed from the hosted type; and the layout of objects,
* i.e., the field order, is only decided after static analysis. Therefore, we need to fix up
* all the nodes that implicitly use the field index.
*/
protected void transplantEscapeAnalysisState(StructuredGraph graph) {
for (CommitAllocationNode node : graph.getNodes().filter(CommitAllocationNode.class)) {
List<ValueNode> values = node.getValues();
List<ValueNode> aValues = new ArrayList<>(values);
values.clear();
int aObjectStartIndex = 0;
for (VirtualObjectNode virtualObject : node.getVirtualObjects()) {
transplantVirtualObjectState(virtualObject, aValues, values, aObjectStartIndex);
aObjectStartIndex += virtualObject.entryCount();
}
assert aValues.size() == aObjectStartIndex;
}
for (VirtualObjectState node : graph.getNodes().filter(VirtualObjectState.class)) {
List<ValueNode> values = node.values();
List<ValueNode> aValues = new ArrayList<>(values);
values.clear();
transplantVirtualObjectState(node.object(), aValues, values, 0);
}
for (VirtualInstanceNode node : graph.getNodes(VirtualInstanceNode.TYPE)) {
AnalysisType aType = (AnalysisType) node.type();
ResolvedJavaField[] aFields = node.getFields();
assert Arrays.equals(aFields, aType.getInstanceFields(true));
HostedField[] hFields = universe.lookup(aType).getInstanceFields(true);
/*
* We cannot directly write the final field `VirtualInstanceNode.fields`. So we rely on
* the NodeClass mechanism, which is also used to transplant all other fields.
*/
Fields nodeClassDataFields = node.getNodeClass().getData();
for (int i = 0; i < nodeClassDataFields.getCount(); i++) {
if (nodeClassDataFields.get(node, i) == aFields) {
nodeClassDataFields.putObjectChecked(node, i, hFields);
}
}
}
}
Aggregations