UninitializedWriteObjectFieldNode.java
/*
* Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. This
* code is released under a tri EPL/GPL/LGPL license. You can use it,
* redistribute it and/or modify it under the terms of the:
*
* Eclipse Public License version 1.0
* GNU General Public License version 2
* GNU Lesser General Public License version 2.1
*/
package org.jruby.truffle.nodes.objectstorage;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.nodes.NodeCost;
import com.oracle.truffle.api.nodes.NodeInfo;
import com.oracle.truffle.api.object.*;
import org.jruby.truffle.runtime.core.RubyBasicObject;
@NodeInfo(cost = NodeCost.UNINITIALIZED)
public class UninitializedWriteObjectFieldNode extends WriteObjectFieldNode {
private final Object name;
public UninitializedWriteObjectFieldNode(Object name) {
this.name = name;
}
@Override
public void execute(RubyBasicObject object, Object value) {
CompilerDirectives.transferToInterpreterAndInvalidate();
final Shape currentShape = object.getDynamicObject().getShape();
// If the current shape is obsolete, add a node to migrate
if (object.getDynamicObject().updateShape()) {
final MigrateNode migrateNode = new MigrateNode(currentShape, this);
replace(migrateNode);
migrateNode.execute(object, value);
return;
}
final Shape newShape;
Location location;
final Property currentProperty = currentShape.getProperty(name);
final Property newProperty;
if (currentProperty != null && currentProperty.getLocation().canSet(object.getDynamicObject(), value)) {
newShape = currentShape;
newProperty = currentProperty;
newProperty.setSafe(object.getDynamicObject(), value, null);
} else {
object.getOperations().setInstanceVariable(object, name, value);
newShape = object.getDynamicObject().getShape();
newProperty = newShape.getProperty(name);
if (newProperty == null) {
throw new IllegalStateException("Property missing from object's shape even after setting it");
}
}
location = newProperty.getLocation();
assert location.canSet(object.getDynamicObject(), value);
final WriteObjectFieldChainNode writeNode;
if (location instanceof BooleanLocation) {
writeNode = new WriteBooleanObjectFieldNode(currentShape, newShape, (BooleanLocation) location, this);
} else if (location instanceof IntLocation) {
writeNode = new WriteIntegerObjectFieldNode(currentShape, newShape, (IntLocation) location, this);
} else if (location instanceof LongLocation) {
writeNode = new WriteLongObjectFieldNode(currentShape, newShape, (LongLocation) location, this);
} else if (location instanceof DoubleLocation) {
writeNode = new WriteDoubleObjectFieldNode(currentShape, newShape, (DoubleLocation) location, this);
} else {
writeNode = new WriteObjectObjectFieldNode(currentShape, newShape, location, this);
}
replace(writeNode, "adding new write object field node to chain");
// not executing, value is already set
}
}