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.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.ReadNode;
import com.oracle.truffle.js.nodes.RepeatableNode;
import com.oracle.truffle.js.nodes.instrumentation.JSTags;
import com.oracle.truffle.js.nodes.instrumentation.JSTags.ReadVariableTag;
import com.oracle.truffle.js.nodes.instrumentation.NodeObjectDescriptor;
import com.oracle.truffle.js.runtime.builtins.JSArgumentsArray;
import com.oracle.truffle.js.runtime.objects.Undefined;
import java.util.Set;
public abstract class JSGuardDisconnectedArgumentRead extends JavaScriptNode implements RepeatableNode, ReadNode {
private final int index;
@Child @Executed JavaScriptNode argumentsArrayNode;
@Child private ReadElementNode readElementNode;
private final FrameSlot slot;
JSGuardDisconnectedArgumentRead(int index, ReadElementNode readElementNode, JavaScriptNode argumentsArray, FrameSlot slot) {
this.index = index;
this.argumentsArrayNode = argumentsArray;
this.readElementNode = readElementNode;
this.slot = slot;
}
public static JSGuardDisconnectedArgumentRead create(int index, ReadElementNode readElementNode, JavaScriptNode argumentsArray, FrameSlot slot) {
return JSGuardDisconnectedArgumentReadNodeGen.create(index, readElementNode, argumentsArray, slot);
}
@Override
public boolean hasTag(Class<? extends Tag> tag) {
if ((tag == ReadVariableTag.class || tag == StandardTags.ReadVariableTag.class)) {
return true;
} else {
return super.hasTag(tag);
}
}
@Override
public Object getNodeObject() {
NodeObjectDescriptor descriptor = JSTags.createNodeObjectDescriptor("name", slot.getIdentifier());
descriptor.addProperty(StandardTags.ReadVariableTag.NAME, slot.getIdentifier());
return descriptor;
}
@Specialization(guards = "!isArgumentsDisconnected(argumentsArray)")
public Object doObject(DynamicObject argumentsArray,
@Cached("createBinaryProfile()") @Shared("unconnected") ConditionProfile unconnected) {
assert JSArgumentsArray.isJSArgumentsObject(argumentsArray);
if (unconnected.profile(index >= JSArgumentsArray.getConnectedArgumentCount(argumentsArray))) {
return Undefined.instance;
} else {
return readElementNode.executeWithTargetAndIndex(argumentsArray, index);
}
}
public final int getIndex() {
return index;
}
@Specialization(guards = "isArgumentsDisconnected(argumentsArray)")
public Object doObjectDisconnected(DynamicObject argumentsArray,
@Cached("createBinaryProfile()") ConditionProfile wasDisconnected,
@Cached("createBinaryProfile()") @Shared("unconnected") ConditionProfile unconnected) {
assert JSArgumentsArray.isJSArgumentsObject(argumentsArray);
if (wasDisconnected.profile(JSArgumentsArray.wasIndexDisconnected(argumentsArray, index))) {
return JSArgumentsArray.getDisconnectedIndexValue(argumentsArray, index);
} else if (unconnected.profile(index >= JSArgumentsArray.getConnectedArgumentCount(argumentsArray))) {
return Undefined.instance;
} else {
return readElementNode.executeWithTargetAndIndex(argumentsArray, index);
}
}
@Override
protected JavaScriptNode copyUninitialized(Set<Class<? extends Tag>> materializedTags) {
return JSGuardDisconnectedArgumentReadNodeGen.create(index, cloneUninitialized(readElementNode, materializedTags), cloneUninitialized(argumentsArrayNode, materializedTags), slot);
}
}