use of org.graalvm.compiler.nodes.virtual.MaterializedObjectState in project graal by oracle.
the class FrameState method ensureHasVirtualObjectMapping.
/**
* A {@link VirtualObjectNode} in a frame state requires a corresponding
* {@link EscapeObjectState} entry in {@link FrameState#virtualObjectMappings}. So when a
* {@link VirtualObjectNode} is pushed as part of a frame state modification, the
* {@link EscapeObjectState} must either be already there, or it must be passed in explicitly
* from another frame state where the pushed value is coming from.
*/
private List<EscapeObjectState> ensureHasVirtualObjectMapping(VirtualObjectNode pushedValue, List<EscapeObjectState> pushedVirtualObjectMappings, List<EscapeObjectState> copiedVirtualObjectMappings) {
if (virtualObjectMappings != null) {
for (EscapeObjectState existingEscapeObjectState : virtualObjectMappings) {
if (existingEscapeObjectState.object() == pushedValue) {
/* Found a matching EscapeObjectState, nothing needs to be added. */
return copiedVirtualObjectMappings;
}
}
}
if (pushedVirtualObjectMappings == null) {
throw GraalError.shouldNotReachHere("Pushing a virtual object, but no virtual object mapping provided: " + pushedValue);
}
for (EscapeObjectState pushedEscapeObjectState : pushedVirtualObjectMappings) {
if (pushedEscapeObjectState.object() == pushedValue) {
/*
* A VirtualObjectState could have transitive dependencies on other object states
* that are would also need to be added. For now, we do not have a case where a
* FrameState with a VirtualObjectState is duplicated, therefore this case is not
* implemented yet.
*/
GraalError.guarantee(pushedEscapeObjectState instanceof MaterializedObjectState, "A VirtualObjectState could have transitive dependencies");
/*
* Found a new EscapeObjectState that needs to be added to the
* virtualObjectMappings.
*/
List<EscapeObjectState> result = copiedVirtualObjectMappings;
if (result == null) {
result = new ArrayList<>();
if (virtualObjectMappings != null) {
result.addAll(virtualObjectMappings);
}
}
result.add(pushedEscapeObjectState);
return result;
}
}
throw GraalError.shouldNotReachHere("Did not find a virtual object mapping: " + pushedValue);
}
use of org.graalvm.compiler.nodes.virtual.MaterializedObjectState 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.MaterializedObjectState 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.MaterializedObjectState 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);
}
}
Aggregations