package com.oracle.truffle.js.builtins;
import java.io.IOException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.oracle.truffle.api.CallTarget;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.RootCallTarget;
import com.oracle.truffle.api.Truffle;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.instrumentation.Tag;
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.object.DynamicObject;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.api.profiles.ValueProfile;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugArrayTypeNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugAssertIntNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugClassNameNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugClassNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugCompileFunctionNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugContinueInInterpreterNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugCreateLazyStringNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugCreateSafeIntegerNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugDumpCountersNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugDumpFunctionTreeNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugHeapDumpNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugIsHolesArrayNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugJSStackNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugLoadModuleNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugNeverPartOfCompilationNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugPrintObjectNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugPrintSourceAttributionNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugShapeNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugStringCompareNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugSystemPropertiesNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugSystemPropertyNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugToJavaStringNodeGen;
import com.oracle.truffle.js.builtins.DebugBuiltinsFactory.DebugTypedArrayDetachBufferNodeGen;
import com.oracle.truffle.js.builtins.helper.GCNodeGen;
import com.oracle.truffle.js.builtins.helper.HeapDump;
import com.oracle.truffle.js.lang.JavaScriptLanguage;
import com.oracle.truffle.js.nodes.JSGuards;
import com.oracle.truffle.js.nodes.JavaScriptNode;
import com.oracle.truffle.js.nodes.ScriptNode;
import com.oracle.truffle.js.nodes.cast.JSToObjectNode;
import com.oracle.truffle.js.nodes.function.JSBuiltin;
import com.oracle.truffle.js.nodes.function.JSBuiltinNode;
import com.oracle.truffle.js.runtime.Errors;
import com.oracle.truffle.js.runtime.Evaluator;
import com.oracle.truffle.js.runtime.JSContext;
import com.oracle.truffle.js.runtime.JSErrorType;
import com.oracle.truffle.js.runtime.JSException;
import com.oracle.truffle.js.runtime.JSRealm;
import com.oracle.truffle.js.runtime.JSRuntime;
import com.oracle.truffle.js.runtime.SafeInteger;
import com.oracle.truffle.js.runtime.Symbol;
import com.oracle.truffle.js.runtime.builtins.BuiltinEnum;
import com.oracle.truffle.js.runtime.builtins.JSArray;
import com.oracle.truffle.js.runtime.builtins.JSArrayBuffer;
import com.oracle.truffle.js.runtime.builtins.JSFunction;
import com.oracle.truffle.js.runtime.builtins.JSGlobal;
import com.oracle.truffle.js.runtime.builtins.JSOrdinary;
import com.oracle.truffle.js.runtime.builtins.JSProxy;
import com.oracle.truffle.js.runtime.objects.JSDynamicObject;
import com.oracle.truffle.js.runtime.objects.JSLazyString;
import com.oracle.truffle.js.runtime.objects.JSModuleLoader;
import com.oracle.truffle.js.runtime.objects.JSModuleRecord;
import com.oracle.truffle.js.runtime.objects.JSObject;
import com.oracle.truffle.js.runtime.objects.JSObjectUtil;
import com.oracle.truffle.js.runtime.objects.Null;
import com.oracle.truffle.js.runtime.objects.PropertyDescriptor;
import com.oracle.truffle.js.runtime.objects.ScriptOrModule;
import com.oracle.truffle.js.runtime.objects.Undefined;
public final class DebugBuiltins extends JSBuiltinsContainer.SwitchEnum<DebugBuiltins.Debug> {
public static final JSBuiltinsContainer BUILTINS = new DebugBuiltins();
protected DebugBuiltins() {
super(JSRealm.DEBUG_CLASS_NAME, Debug.class);
}
public enum Debug implements BuiltinEnum<Debug> {
class_(1),
getClass(1),
className(1),
shape(1),
dumpCounters(0),
dumpFunctionTree(1),
compileFunction(2),
printObject(1),
toJavaString(1),
srcattr(1),
arraytype(1),
assertInt(2),
continueInInterpreter(0),
stringCompare(2),
isHolesArray(1),
jsStack(0),
loadModule(2),
createSafeInteger(1),
createLazyString(2),
typedArrayDetachBuffer(1),
systemGC(0),
systemProperty(1),
systemProperties(0),
neverPartOfCompilation(0),
dumpHeap(2);
private final int length;
Debug(int length) {
this.length = length;
}
@Override
public int getLength() {
return length;
}
}
@Override
protected Object createNode(JSContext context, JSBuiltin builtin, boolean construct, boolean newTarget, Debug builtinEnum) {
switch (builtinEnum) {
case class_:
return DebugClassNodeGen.create(context, builtin, true, args().fixedArgs(1).createArgumentNodes(context));
case getClass:
return DebugClassNodeGen.create(context, builtin, false, args().fixedArgs(1).createArgumentNodes(context));
case className:
return DebugClassNameNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case shape:
return DebugShapeNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case dumpCounters:
return DebugDumpCountersNodeGen.create(context, builtin, args().createArgumentNodes(context));
case dumpFunctionTree:
return DebugDumpFunctionTreeNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case compileFunction:
return DebugCompileFunctionNodeGen.create(context, builtin, args().fixedArgs(2).createArgumentNodes(context));
case printObject:
return DebugPrintObjectNodeGen.create(context, builtin, args().fixedArgs(2).createArgumentNodes(context));
case toJavaString:
return DebugToJavaStringNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case srcattr:
return DebugPrintSourceAttributionNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case arraytype:
return DebugArrayTypeNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case assertInt:
return DebugAssertIntNodeGen.create(context, builtin, args().fixedArgs(2).createArgumentNodes(context));
case continueInInterpreter:
return DebugContinueInInterpreterNodeGen.create(context, builtin, false, args().createArgumentNodes(context));
case stringCompare:
return DebugStringCompareNodeGen.create(context, builtin, args().fixedArgs(2).createArgumentNodes(context));
case isHolesArray:
return DebugIsHolesArrayNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case jsStack:
return DebugJSStackNodeGen.create(context, builtin, args().createArgumentNodes(context));
case loadModule:
return DebugLoadModuleNodeGen.create(context, builtin, args().fixedArgs(2).createArgumentNodes(context));
case systemGC:
return GCNodeGen.create(context, builtin, args().createArgumentNodes(context));
case systemProperty:
return DebugSystemPropertyNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case systemProperties:
return DebugSystemPropertiesNodeGen.create(context, builtin, args().createArgumentNodes(context));
case neverPartOfCompilation:
return DebugNeverPartOfCompilationNodeGen.create(context, builtin, args().createArgumentNodes(context));
case typedArrayDetachBuffer:
return DebugTypedArrayDetachBufferNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case createSafeInteger:
return DebugCreateSafeIntegerNodeGen.create(context, builtin, args().fixedArgs(1).createArgumentNodes(context));
case createLazyString:
return DebugCreateLazyStringNodeGen.create(context, builtin, args().fixedArgs(2).createArgumentNodes(context));
case dumpHeap:
return DebugHeapDumpNodeGen.create(context, builtin, args().fixedArgs(2).createArgumentNodes(context));
}
return null;
}
public abstract static class DebugContinueInInterpreter extends JSBuiltinNode {
private final boolean invalidate;
public DebugContinueInInterpreter(JSContext context, JSBuiltin builtin, boolean invalidate) {
super(context, builtin);
this.invalidate = invalidate;
}
@Specialization
protected Object continueInInterpreter() {
if (invalidate) {
CompilerDirectives.transferToInterpreterAndInvalidate();
} else {
CompilerDirectives.transferToInterpreter();
}
return Undefined.instance;
}
}
public abstract static class DebugClassNode extends JSBuiltinNode {
private final boolean getName;
public DebugClassNode(JSContext context, JSBuiltin builtin, boolean getName) {
super(context, builtin);
this.getName = getName;
}
@Specialization
protected Object clazz(Object obj) {
return obj == null ? Null.instance : getName ? obj.getClass().getName() : wrap(obj.getClass());
}
private Object wrap(Class<? extends Object> class1) {
return getContext().getRealm().getEnv().asGuestValue(class1);
}
}
public abstract static class DebugClassNameNode extends JSBuiltinNode {
public DebugClassNameNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
@TruffleBoundary
protected static Object clazz(Object obj) {
if (obj instanceof Symbol) {
return Null.instance;
} else if (JSDynamicObject.isJSDynamicObject(obj)) {
DynamicObject jsObj = (DynamicObject) obj;
if (JSObjectUtil.hasHiddenProperty(jsObj, JSRuntime.ITERATED_OBJECT_ID)) {
DynamicObject iteratedObj = (DynamicObject) JSObjectUtil.getHiddenProperty(jsObj, JSRuntime.ITERATED_OBJECT_ID);
return JSObject.getClassName(iteratedObj) + " Iterator";
} else if (JSObjectUtil.hasHiddenProperty(jsObj, JSFunction.GENERATOR_STATE_ID)) {
return "Generator";
} else if (JSObjectUtil.hasHiddenProperty(jsObj, JSFunction.ASYNC_GENERATOR_STATE_ID)) {
return "Async Generator";
} else if (JSProxy.isJSProxy(jsObj)) {
return clazz(JSProxy.getTarget(jsObj));
}
return JSObject.getClassName(jsObj);
} else {
return "not_an_object";
}
}
}
public abstract static class DebugShapeNode extends JSBuiltinNode {
public DebugShapeNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected static Object shape(Object obj) {
if (obj instanceof DynamicObject) {
return ((DynamicObject) obj).getShape().toString();
}
return Undefined.instance;
}
}
public abstract static class DebugDumpCountersNode extends JSBuiltinNode {
public DebugDumpCountersNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected static Object dumpCounters() {
com.oracle.truffle.object.DebugCounter.dumpCounters();
com.oracle.truffle.js.runtime.util.DebugCounter.dumpCounters();
return Undefined.instance;
}
}
public abstract static class DebugDumpFunctionTreeNode extends JSBuiltinNode {
public DebugDumpFunctionTreeNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization(guards = "isJSFunction(functionObj)")
protected Object dumpFunctionTree(DynamicObject functionObj) {
CallTarget target = JSFunction.getCallTarget(functionObj);
if (target instanceof RootCallTarget) {
NodeUtil.printTree(getContext().getRealm().getOutputWriter(), ((RootCallTarget) target).getRootNode());
return Undefined.instance;
} else {
throw Errors.shouldNotReachHere();
}
}
}
public abstract static class DebugCompileFunctionNode extends JSBuiltinNode {
private static final MethodHandle COMPILE_HANDLE;
public DebugCompileFunctionNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected static boolean compileFunction(Object fnObj) {
if (!JSFunction.isJSFunction(fnObj)) {
throw Errors.createTypeErrorNotAFunction(fnObj);
}
CallTarget callTarget = JSFunction.getCallTarget((DynamicObject) fnObj);
if (COMPILE_HANDLE != null) {
try {
COMPILE_HANDLE.invokeExact(callTarget);
return true;
} catch (Throwable e) {
}
}
return false;
}
static {
MethodHandle compileHandle = null;
if (Truffle.getRuntime().getName().contains("Graal")) {
try {
Class<? extends CallTarget> optimizedCallTargetClass = Class.forName("com.oracle.graal.truffle.OptimizedCallTarget").asSubclass(CallTarget.class);
compileHandle = MethodHandles.lookup().findVirtual(optimizedCallTargetClass, "compile", MethodType.methodType(void.class)).asType(
MethodType.methodType(void.class, CallTarget.class));
} catch (ClassNotFoundException | IllegalAccessException | NoSuchMethodException | SecurityException e) {
}
}
COMPILE_HANDLE = compileHandle;
}
}
public abstract static class DebugPrintObjectNode extends JSBuiltinNode {
public DebugPrintObjectNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected Object printObject(DynamicObject object, Object level0) {
int level = level0 == Undefined.instance ? 1 : JSRuntime.toInt32(level0);
getContext().getRealm().getOutputWriter().println(debugPrint(object, 0, level));
return Undefined.instance;
}
@TruffleBoundary
protected String debugPrint(DynamicObject object, int level, int levelStop) {
List<String> properties = JSObject.enumerableOwnNames(object);
StringBuilder sb = new StringBuilder(properties.size() * 10);
sb.append("{\n");
for (String key : properties) {
indent(sb, level + 1);
PropertyDescriptor desc = JSObject.getOwnProperty(object, key);
sb.append(key);
if (desc.isDataDescriptor()) {
Object value = JSObject.get(object, key);
if (JSDynamicObject.isJSDynamicObject(value)) {
if ((JSGuards.isJSOrdinaryObject(value) || JSGlobal.isJSGlobalObject(value)) && !key.equals(JSObject.CONSTRUCTOR)) {
if (level < levelStop && !key.equals(JSObject.CONSTRUCTOR)) {
value = debugPrint((DynamicObject) value, level + 1, levelStop);
} else {
value = "{...}";
}
} else {
value = JSObject.getJSClass((DynamicObject) value);
}
}
sb.append(": ");
sb.append(value);
}
if (!key.equals(properties.get(properties.size() - 1))) {
sb.append(',');
}
sb.append('\n');
}
indent(sb, level);
sb.append('}');
return sb.toString();
}
private static StringBuilder indent(StringBuilder sb, int level) {
for (int i = 0; i < level; i++) {
sb.append(' ');
}
return sb;
}
}
public abstract static class DebugToJavaStringNode extends JSBuiltinNode {
public DebugToJavaStringNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected static Object toJavaString(Object thing) {
return String.valueOf(thing);
}
}
public abstract static class DebugPrintSourceAttribution extends JSBuiltinNode {
public DebugPrintSourceAttribution(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization(guards = "isJSFunction(function)")
protected Object printSourceAttribution(DynamicObject function) {
CallTarget callTarget = JSFunction.getCallTarget(function);
if (callTarget instanceof RootCallTarget) {
return NodeUtil.printSourceAttributionTree(((RootCallTarget) callTarget).getRootNode());
}
return Undefined.instance;
}
@TruffleBoundary
@Specialization
protected Object printSourceAttribution(String code) {
ScriptNode scriptNode = getContext().getEvaluator().evalCompile(getContext(), code, "<eval>");
return NodeUtil.printSourceAttributionTree(scriptNode.getRootNode());
}
}
public abstract static class DebugArrayTypeNode extends JSBuiltinNode {
public DebugArrayTypeNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected Object arraytype(Object array) {
if (!(JSDynamicObject.isJSDynamicObject(array)) || !(JSObject.hasArray((DynamicObject) array))) {
return "NOT_AN_ARRAY";
}
return JSObject.getArray((DynamicObject) array).getClass().getSimpleName();
}
}
public abstract static class DebugAssertIntNode extends JSBuiltinNode {
public DebugAssertIntNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected Object assertInt(Object value, Object message) {
if (!(value instanceof Integer)) {
throw Errors.createTypeError("assert: expected integer here, got " + value.getClass().getSimpleName() + ", message: " + JSRuntime.toString(message));
}
return Undefined.instance;
}
}
public abstract static class DebugHeapDumpNode extends JSBuiltinNode {
public DebugHeapDumpNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected String heapDump(Object fileName0, Object live0) {
String fileName = fileName0 == Undefined.instance ? HeapDump.defaultDumpName() : JSRuntime.toString(fileName0);
boolean live = live0 == Undefined.instance ? true : JSRuntime.toBoolean(live0);
try {
HeapDump.dump(fileName, live);
} catch (IOException e) {
throw JSException.create(JSErrorType.Error, e.getMessage(), e, this);
} catch (IllegalArgumentException e) {
throw JSException.create(JSErrorType.Error, getBuiltin().getFullName() + " unsupported", e, this);
}
return fileName;
}
}
public abstract static class DebugStringCompareNode extends JSBuiltinNode {
public DebugStringCompareNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected int stringCompare(Object a, Object b) {
String str1 = JSRuntime.toString(a);
String str2 = JSRuntime.toString(b);
int result = str1.compareTo(str2);
if (result == 0) {
return 0;
} else if (result < 0) {
return -1;
} else {
return 1;
}
}
}
public abstract static class DebugIsHolesArrayNode extends JSBuiltinNode {
@Child private JSToObjectNode toObjectNode;
private final ValueProfile arrayType;
private final ConditionProfile isArray;
public DebugIsHolesArrayNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
this.toObjectNode = JSToObjectNode.createToObject(getContext());
this.arrayType = ValueProfile.createClassProfile();
this.isArray = ConditionProfile.createBinaryProfile();
}
public abstract boolean executeBoolean(Object object);
@Specialization
protected boolean isHolesArray(Object arr) {
Object obj = toObjectNode.execute(arr);
if (isArray.profile(JSArray.isJSArray(obj))) {
DynamicObject dynObj = (DynamicObject) obj;
return arrayType.profile(JSObject.getArray(dynObj)).hasHoles(dynObj);
} else {
return false;
}
}
@Override
protected JavaScriptNode copyUninitialized(Set<Class<? extends Tag>> materializedTags) {
return DebugIsHolesArrayNodeGen.create(getContext(), getBuiltin(), cloneUninitialized(getArguments(), materializedTags));
}
}
public abstract static class DebugJSStackNode extends JSBuiltinNode {
public DebugJSStackNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected Object printJSStack() {
JSException.printJSStackTrace(getParent());
return Undefined.instance;
}
}
public abstract static class DebugLoadModuleNode extends JSBuiltinNode {
public DebugLoadModuleNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected String loadModule(Object nameObj, Object modulesSourceMapObj) {
String name = JSRuntime.toString(nameObj);
DynamicObject modulesSourceMap = (DynamicObject) modulesSourceMapObj;
JSContext context = getContext();
Evaluator evaluator = context.getEvaluator();
JSModuleLoader moduleLoader = new JSModuleLoader() {
private final Map<String, JSModuleRecord> moduleMap = new HashMap<>();
private Source resolveModuleSource(@SuppressWarnings("unused") ScriptOrModule referencingModule, String specifier) {
Object moduleEntry = JSObject.get(modulesSourceMap, specifier);
if (moduleEntry == Undefined.instance) {
throw Errors.createSyntaxError(String.format("Could not find imported module %s", specifier));
}
String code = JSRuntime.toString(moduleEntry);
return Source.newBuilder(JavaScriptLanguage.ID, code, name).build();
}
@Override
public JSModuleRecord resolveImportedModule(ScriptOrModule referencingModule, String specifier) {
return moduleMap.computeIfAbsent(specifier, (key) -> evaluator.parseModule(context, resolveModuleSource(referencingModule, key), this));
}
@Override
public JSModuleRecord loadModule(Source moduleSource) {
throw new UnsupportedOperationException();
}
};
JSModuleRecord module = moduleLoader.resolveImportedModule(null, name);
JSRealm realm = context.getRealm();
evaluator.moduleInstantiation(realm, module);
evaluator.moduleEvaluation(realm, module);
return String.valueOf(module);
}
}
public abstract static class DebugSystemProperties extends JSBuiltinNode {
public DebugSystemProperties(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected Object systemProperties() {
DynamicObject result = JSOrdinary.create(getContext());
for (Map.Entry<Object, Object> entry : System.getProperties().entrySet()) {
Object key = entry.getKey();
Object value = entry.getValue();
if (key instanceof String && value instanceof String) {
JSObject.set(result, key, value);
}
}
return result;
}
}
public abstract static class DebugSystemProperty extends JSBuiltinNode {
public DebugSystemProperty(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected static Object systemProperty(Object name) {
String key = JSRuntime.toString(name);
String value = System.getProperty(key);
return (value == null) ? Undefined.instance : value;
}
}
public abstract static class DebugTypedArrayDetachBufferNode extends JSBuiltinNode {
public DebugTypedArrayDetachBufferNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@TruffleBoundary
@Specialization
protected static Object detachBuffer(Object obj) {
if (!(JSArrayBuffer.isJSHeapArrayBuffer(obj) || JSArrayBuffer.isJSDirectArrayBuffer(obj))) {
throw Errors.createTypeError("ArrayBuffer expected");
}
JSArrayBuffer.detachArrayBuffer((DynamicObject) obj);
return Undefined.instance;
}
}
public abstract static class DebugCreateSafeInteger extends JSBuiltinNode {
public DebugCreateSafeInteger(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected static SafeInteger createSafeInteger(int a) {
return SafeInteger.valueOf(a);
}
@Specialization
protected static SafeInteger createSafeInteger(SafeInteger a) {
return a;
}
@Specialization
protected static SafeInteger createSafeInteger(Object a) {
long integer = JSRuntime.toInteger(a);
integer = Math.max(integer, JSRuntime.MIN_SAFE_INTEGER_LONG);
integer = Math.min(integer, JSRuntime.MAX_SAFE_INTEGER_LONG);
return SafeInteger.valueOf(integer);
}
}
public abstract static class DebugCreateLazyString extends JSBuiltinNode {
public DebugCreateLazyString(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected CharSequence createLazyString(String left, String right) {
CharSequence result = JSLazyString.create(left, right);
if (!(result instanceof JSLazyString)) {
throw Errors.createError(resultIsNotLazyStringMessage(left, right));
}
return result;
}
@TruffleBoundary
private static String resultIsNotLazyStringMessage(String left, String right) {
return "Concatenation of '" + left + "' and '" + right + "' does not produce JSLazyString.";
}
@Specialization
protected CharSequence createLazyString(Object left, Object right) {
return createLazyString(JSRuntime.toString(left), JSRuntime.toString(right));
}
}
public abstract static class DebugNeverPartOfCompilationNode extends JSBuiltinNode implements JSBuiltinNode.Inlineable, JSBuiltinNode.Inlined {
public DebugNeverPartOfCompilationNode(JSContext context, JSBuiltin builtin) {
super(context, builtin);
}
@Specialization
protected static Object neverPartOfCompilation() {
if (!CompilerDirectives.inCompilationRoot()) {
fail();
}
return Undefined.instance;
}
protected static void fail() {
CompilerDirectives.bailout("Debug.neverPartOfCompilation()");
}
@Override
public Object callInlined(Object[] arguments) {
fail();
return Undefined.instance;
}
@Override
public Inlined createInlined() {
return DebugNeverPartOfCompilationNodeGen.create(getContext(), getBuiltin(), getArguments());
}
}
}