package com.oracle.truffle.js.nodes.access;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Cached.Shared;
import com.oracle.truffle.api.dsl.Executed;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.FrameSlot;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.instrumentation.StandardTags;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.js.nodes.JavaScriptNode;
import com.oracle.truffle.js.nodes.instrumentation.JSTags;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.WriteVariableTag;
import com.oracle.truffle.js.nodes.instrumentation.NodeObjectDescriptor;
import com.oracle.truffle.js.runtime.builtins.JSArgumentsArray;
import java.util.Set;
public abstract class JSGuardDisconnectedArgumentWrite extends JavaScriptNode implements WriteNode {
private final int index;
@Child @Executed JavaScriptNode argumentsArrayNode;
@Child @Executed JavaScriptNode rhsNode;
@Child private WriteElementNode writeArgumentsElementNode;
private final FrameSlot slot;
JSGuardDisconnectedArgumentWrite(int index, WriteElementNode argumentsArrayAccess, JavaScriptNode argumentsArray, JavaScriptNode rhs, FrameSlot slot) {
this.index = index;
this.argumentsArrayNode = argumentsArray;
this.rhsNode = rhs;
this.writeArgumentsElementNode = argumentsArrayAccess;
this.slot = slot;
}
public static JSGuardDisconnectedArgumentWrite create(int index, WriteElementNode argumentsArrayAccess, JavaScriptNode argumentsArray, JavaScriptNode rhs, FrameSlot slot) {
return JSGuardDisconnectedArgumentWriteNodeGen.create(index, argumentsArrayAccess, argumentsArray, rhs, slot);
}
@Override
public boolean hasTag(Class<? extends Tag> tag) {
if (tag == WriteVariableTag.class || tag == StandardTags.WriteVariableTag.class) {
return true;
} else {
return super.hasTag(tag);
}
}
@Override
public Object getNodeObject() {
NodeObjectDescriptor descriptor = JSTags.createNodeObjectDescriptor("name", slot.getIdentifier());
descriptor.addProperty(StandardTags.WriteVariableTag.NAME, slot.getIdentifier());
return descriptor;
}
@Specialization(guards = "!isArgumentsDisconnected(argumentsArray)")
public Object doObject(DynamicObject argumentsArray, Object value,
@Cached("createBinaryProfile()") @Shared("unconnected") ConditionProfile unconnected) {
assert JSArgumentsArray.isJSArgumentsObject(argumentsArray);
if (unconnected.profile(index >= JSArgumentsArray.getConnectedArgumentCount(argumentsArray))) {
JSArgumentsArray.disconnectIndex(argumentsArray, index, value);
} else {
writeArgumentsElementNode.executeWithTargetAndIndexAndValue(argumentsArray, index, value);
}
return value;
}
@Specialization(guards = "isArgumentsDisconnected(argumentsArray)")
public Object doObjectDisconnected(DynamicObject argumentsArray, Object value,
@Cached("createBinaryProfile()") ConditionProfile wasDisconnected,
@Cached("createBinaryProfile()") @Shared("unconnected") ConditionProfile unconnected) {
assert JSArgumentsArray.isJSArgumentsObject(argumentsArray);
if (wasDisconnected.profile(JSArgumentsArray.wasIndexDisconnected(argumentsArray, index))) {
JSArgumentsArray.setDisconnectedIndexValue(argumentsArray, index, value);
} else if (unconnected.profile(index >= JSArgumentsArray.getConnectedArgumentCount(argumentsArray))) {
JSArgumentsArray.disconnectIndex(argumentsArray, index, value);
} else {
writeArgumentsElementNode.executeWithTargetAndIndexAndValue(argumentsArray, index, value);
}
return value;
}
@Override
public final Object executeWrite(VirtualFrame frame, Object value) {
return executeWrite(frame, argumentsArrayNode.execute(frame), value);
}
protected abstract Object executeWrite(VirtualFrame frame, Object argumentsArray, Object value);
@Override
public JavaScriptNode getRhs() {
return rhsNode;
}
@Override
protected JavaScriptNode copyUninitialized(Set<Class<? extends Tag>> materializedTags) {
return JSGuardDisconnectedArgumentWriteNodeGen.create(index, cloneUninitialized(writeArgumentsElementNode, materializedTags), cloneUninitialized(argumentsArrayNode, materializedTags),
cloneUninitialized(rhsNode, materializedTags), slot);
}
}