From 6942dea95e483d71c7a06765140743be33e02ef5 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 1 Oct 2024 04:34:24 +0200 Subject: [PATCH] Introduce WebAssemblyValueType enum. --- .../js/builtins/ConstructorBuiltins.java | 26 ++-- .../WebAssemblyGlobalPrototypeBuiltins.java | 8 +- .../WebAssemblyTablePrototypeBuiltins.java | 13 +- .../js/nodes/wasm/ToWebAssemblyValueNode.java | 33 +++-- .../builtins/wasm/JSWebAssemblyGlobal.java | 4 +- .../wasm/JSWebAssemblyGlobalObject.java | 6 +- .../builtins/wasm/JSWebAssemblyInstance.java | 38 +++--- .../builtins/wasm/JSWebAssemblyTable.java | 4 +- .../wasm/JSWebAssemblyTableObject.java | 6 +- .../wasm/JSWebAssemblyValueTypes.java | 116 ------------------ .../builtins/wasm/WasmFunctionTypeInfo.java | 9 +- .../wasm/WebAssemblyHostFunction.java | 3 +- .../builtins/wasm/WebAssemblyValueType.java | 96 +++++++++++++++ 13 files changed, 176 insertions(+), 186 deletions(-) delete mode 100644 graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyValueTypes.java create mode 100644 graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WebAssemblyValueType.java diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/ConstructorBuiltins.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/ConstructorBuiltins.java index e3072212df5..6dc81b667fb 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/ConstructorBuiltins.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/ConstructorBuiltins.java @@ -276,7 +276,7 @@ import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyModule; import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyModuleObject; import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyTable; -import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyValueTypes; +import com.oracle.truffle.js.runtime.builtins.wasm.WebAssemblyValueType; import com.oracle.truffle.js.runtime.java.JavaImporter; import com.oracle.truffle.js.runtime.java.JavaPackage; import com.oracle.truffle.js.runtime.objects.IteratorRecord; @@ -3345,12 +3345,14 @@ public ConstructWebAssemblyTableNode(JSContext context, JSBuiltin builtin, boole @Specialization protected JSObject constructTable(JSDynamicObject newTarget, Object descriptor, Object[] args, @Cached JSToStringNode toStringNode, + @Cached TruffleString.ToJavaStringNode toJavaString, @Cached ToWebAssemblyValueNode toWebAssemblyValueNode) { if (!isObjectNode.executeBoolean(descriptor)) { throw Errors.createTypeError("WebAssembly.Table(): Argument 0 must be a table descriptor", this); } - TruffleString elementKind = toStringNode.executeString(getElementNode.getValue(descriptor)); - if (!JSWebAssemblyValueTypes.isReferenceType(elementKind)) { + String elementKindStr = toJavaString.execute(toStringNode.executeString(getElementNode.getValue(descriptor))); + WebAssemblyValueType elementKind = WebAssemblyValueType.lookupType(elementKindStr); + if (elementKind == null || !elementKind.isReference()) { throw Errors.createTypeError("WebAssembly.Table(): Descriptor property 'element' must be 'anyfunc' or 'externref'", this); } Object initial = getInitialNode.getValue(descriptor); @@ -3377,14 +3379,14 @@ protected JSObject constructTable(JSDynamicObject newTarget, Object descriptor, final JSRealm realm = getRealm(); Object wasmValue; if (args.length == 0) { - wasmValue = JSWebAssemblyValueTypes.getDefaultValue(realm, elementKind); + wasmValue = elementKind.getDefaultValue(realm); } else { wasmValue = toWebAssemblyValueNode.execute(args[0], elementKind); } Object wasmTable; try { Object createTable = realm.getWASMTableAlloc(); - wasmTable = tableAllocLib.execute(createTable, initialInt, maximumInt, elementKind, wasmValue); + wasmTable = tableAllocLib.execute(createTable, initialInt, maximumInt, elementKindStr, wasmValue); } catch (InteropException ex) { throw Errors.shouldNotReachHere(ex); } @@ -3416,16 +3418,18 @@ protected JSObject constructGlobal(JSDynamicObject newTarget, Object descriptor, @Cached IsObjectNode isObjectNode, @Cached(inline = true) JSToBooleanNode toBooleanNode, @Cached JSToStringNode toStringNode, + @Cached TruffleString.ToJavaStringNode toJavaString, @Cached ToWebAssemblyValueNode toWebAssemblyValueNode) { if (!isObjectNode.executeBoolean(descriptor)) { throw Errors.createTypeError("WebAssembly.Global(): Argument 0 must be a global descriptor", this); } boolean mutable = toBooleanNode.executeBoolean(this, getMutableNode.getValue(descriptor)); - TruffleString valueType = toStringNode.executeString(getValueNode.getValue(descriptor)); - if (!JSWebAssemblyValueTypes.isValueType(valueType)) { + String valueTypeStr = toJavaString.execute(toStringNode.executeString(getValueNode.getValue(descriptor))); + WebAssemblyValueType valueType = WebAssemblyValueType.lookupType(valueTypeStr); + if (valueType == null) { throw Errors.createTypeError("WebAssembly.Global(): Descriptor property 'value' must be a WebAssembly type (i32, i64, f32, f64, anyfunc, externref)", this); } - if (JSWebAssemblyValueTypes.isV128(valueType)) { + if (valueType == WebAssemblyValueType.v128) { throw Errors.createTypeError("WebAssembly.Global(): Descriptor property 'value' must not be v128", this); } final JSRealm realm = getRealm(); @@ -3433,9 +3437,9 @@ protected JSObject constructGlobal(JSDynamicObject newTarget, Object descriptor, // According to the spec only missing values should produce a default value. // According to the tests also undefined should use the default value. if (args.length == 0 || args[0] == Undefined.instance) { - webAssemblyValue = JSWebAssemblyValueTypes.getDefaultValue(realm, valueType); + webAssemblyValue = valueType.getDefaultValue(realm); } else { - if (!getContext().getLanguageOptions().wasmBigInt() && JSWebAssemblyValueTypes.isI64(valueType)) { + if (!getContext().getLanguageOptions().wasmBigInt() && valueType == WebAssemblyValueType.i64) { throw Errors.createTypeError("WebAssembly.Global(): Can't set the value of i64 WebAssembly.Global", this); } webAssemblyValue = toWebAssemblyValueNode.execute(args[0], valueType); @@ -3443,7 +3447,7 @@ protected JSObject constructGlobal(JSDynamicObject newTarget, Object descriptor, Object wasmGlobal; try { Object createGlobal = realm.getWASMGlobalAlloc(); - wasmGlobal = globalAllocLib.execute(createGlobal, valueType, mutable, webAssemblyValue); + wasmGlobal = globalAllocLib.execute(createGlobal, valueTypeStr, mutable, webAssemblyValue); } catch (InteropException ex) { throw Errors.shouldNotReachHere(ex); } diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/wasm/WebAssemblyGlobalPrototypeBuiltins.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/wasm/WebAssemblyGlobalPrototypeBuiltins.java index fd6545d6968..f4caefe82dd 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/wasm/WebAssemblyGlobalPrototypeBuiltins.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/wasm/WebAssemblyGlobalPrototypeBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -63,7 +63,7 @@ import com.oracle.truffle.js.runtime.builtins.BuiltinEnum; import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyGlobal; import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyGlobalObject; -import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyValueTypes; +import com.oracle.truffle.js.runtime.builtins.wasm.WebAssemblyValueType; import com.oracle.truffle.js.runtime.objects.Undefined; public class WebAssemblyGlobalPrototypeBuiltins extends JSBuiltinsContainer.SwitchEnum { @@ -136,7 +136,7 @@ protected Object getValue(JSWebAssemblyGlobalObject object, @Cached InlinedBranchProfile errorBranch, @Cached ToJSValueNode toJSValueNode, @CachedLibrary(limit = "InteropLibraryLimit") InteropLibrary globalReadLib) { - if (JSWebAssemblyValueTypes.isV128(object.getValueType())) { + if (object.getValueType() == WebAssemblyValueType.v128) { errorBranch.enter(this); v128TypeError(); } @@ -177,7 +177,7 @@ protected Object setValue(JSWebAssemblyGlobalObject global, Object[] args, errorBranch.enter(this); throw Errors.createTypeError("set WebAssembly.Global.value: Can't set the value of an immutable global"); } - if (JSWebAssemblyValueTypes.isV128(global.getValueType())) { + if (global.getValueType() == WebAssemblyValueType.v128) { errorBranch.enter(this); throw Errors.createTypeError("set WebAssembly.Global.value: cannot write value type v128", this); } diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/wasm/WebAssemblyTablePrototypeBuiltins.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/wasm/WebAssemblyTablePrototypeBuiltins.java index b984316fd16..b87979df6fb 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/wasm/WebAssemblyTablePrototypeBuiltins.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/builtins/wasm/WebAssemblyTablePrototypeBuiltins.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -50,7 +50,6 @@ import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.profiles.InlinedBranchProfile; -import com.oracle.truffle.api.strings.TruffleString; import com.oracle.truffle.js.builtins.JSBuiltinsContainer; import com.oracle.truffle.js.builtins.wasm.WebAssemblyTablePrototypeBuiltinsFactory.WebAssemblyTableGetLengthNodeGen; import com.oracle.truffle.js.builtins.wasm.WebAssemblyTablePrototypeBuiltinsFactory.WebAssemblyTableGetNodeGen; @@ -68,7 +67,7 @@ import com.oracle.truffle.js.runtime.builtins.BuiltinEnum; import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyTable; import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyTableObject; -import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyValueTypes; +import com.oracle.truffle.js.runtime.builtins.wasm.WebAssemblyValueType; import com.oracle.truffle.js.runtime.objects.Undefined; public class WebAssemblyTablePrototypeBuiltins extends JSBuiltinsContainer.SwitchEnum { @@ -143,12 +142,12 @@ protected Object grow(Object thiz, Object delta, Object[] args, JSWebAssemblyTableObject table = (JSWebAssemblyTableObject) thiz; int deltaInt = toDeltaNode.executeInt(delta); Object wasmTable = table.getWASMTable(); - TruffleString elementKind = table.getElementKind(); + WebAssemblyValueType elementKind = table.getElementKind(); final JSRealm realm = getRealm(); final Object wasmValue; if (args.length == 0) { - wasmValue = JSWebAssemblyValueTypes.getDefaultValue(realm, elementKind); + wasmValue = elementKind.getDefaultValue(realm); } else { wasmValue = toWebAssemblyValueNode.execute(args[0], elementKind); } @@ -220,12 +219,12 @@ protected Object set(Object thiz, Object index, Object[] args, JSWebAssemblyTableObject table = (JSWebAssemblyTableObject) thiz; int indexInt = toIndexNode.executeInt(index); Object wasmTable = table.getWASMTable(); - TruffleString elementKind = table.getElementKind(); + WebAssemblyValueType elementKind = table.getElementKind(); final JSRealm realm = getRealm(); final Object wasmValue; if (args.length == 0) { - wasmValue = JSWebAssemblyValueTypes.getDefaultValue(realm, elementKind); + wasmValue = elementKind.getDefaultValue(realm); } else { wasmValue = toWebAssemblyValueNode.execute(args[0], elementKind); } diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/wasm/ToWebAssemblyValueNode.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/wasm/ToWebAssemblyValueNode.java index 53c1dff0b5e..c9b86856c54 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/wasm/ToWebAssemblyValueNode.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/wasm/ToWebAssemblyValueNode.java @@ -48,7 +48,6 @@ import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.InlinedBranchProfile; -import com.oracle.truffle.api.strings.TruffleString; import com.oracle.truffle.js.nodes.JavaScriptBaseNode; import com.oracle.truffle.js.nodes.cast.JSToBigIntNode; import com.oracle.truffle.js.nodes.cast.JSToInt32Node; @@ -57,7 +56,7 @@ import com.oracle.truffle.js.runtime.JSException; import com.oracle.truffle.js.runtime.JSRuntime; import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssembly; -import com.oracle.truffle.js.runtime.builtins.wasm.JSWebAssemblyValueTypes; +import com.oracle.truffle.js.runtime.builtins.wasm.WebAssemblyValueType; import com.oracle.truffle.js.runtime.objects.JSDynamicObject; import com.oracle.truffle.js.runtime.objects.Null; @@ -65,44 +64,44 @@ * Implementation of ToWebAssemblyValue() operation. See * Wasm JS-API Spec */ -@ImportStatic(JSWebAssemblyValueTypes.class) +@ImportStatic(WebAssemblyValueType.class) @GenerateUncached public abstract class ToWebAssemblyValueNode extends JavaScriptBaseNode { protected ToWebAssemblyValueNode() { } - public abstract Object execute(Object value, TruffleString type); + public abstract Object execute(Object value, WebAssemblyValueType type); - @Specialization(guards = "isI32(type)") - static int i32(Object value, @SuppressWarnings("unused") TruffleString type, + @Specialization(guards = "type == i32") + static int i32(Object value, @SuppressWarnings("unused") WebAssemblyValueType type, @Cached JSToInt32Node toInt32Node) { return toInt32Node.executeInt(value); } - @Specialization(guards = "isI64(type)") - static long i64(Object value, @SuppressWarnings("unused") TruffleString type, + @Specialization(guards = "type == i64") + static long i64(Object value, @SuppressWarnings("unused") WebAssemblyValueType type, @Cached JSToBigIntNode toBigIntNode) { return toBigIntNode.executeBigInteger(value).longValue(); } - @Specialization(guards = "isF32(type)") - static float f32(Object value, @SuppressWarnings("unused") TruffleString type, + @Specialization(guards = "type == f32") + static float f32(Object value, @SuppressWarnings("unused") WebAssemblyValueType type, @Cached @Shared JSToNumberNode toNumberNode) { Number numberValue = toNumberNode.executeNumber(value); double doubleValue = JSRuntime.toDouble(numberValue); return (float) doubleValue; } - @Specialization(guards = "isF64(type)") - static double f64(Object value, @SuppressWarnings("unused") TruffleString type, + @Specialization(guards = "type == f64") + static double f64(Object value, @SuppressWarnings("unused") WebAssemblyValueType type, @Cached @Shared JSToNumberNode toNumberNode) { Number numberValue = toNumberNode.executeNumber(value); return JSRuntime.toDouble(numberValue); } - @Specialization(guards = "isAnyfunc(type)") - final Object anyfunc(Object value, @SuppressWarnings("unused") TruffleString type, + @Specialization(guards = "type == anyfunc") + final Object anyfunc(Object value, @SuppressWarnings("unused") WebAssemblyValueType type, @Cached InlinedBranchProfile errorBranch) { if (value == Null.instance) { return getRealm().getWasmRefNull(); @@ -120,8 +119,8 @@ private static JSException notAnExportedFunctionError() { throw Errors.createTypeError("value is not an exported function"); } - @Specialization(guards = "isExternref(type)") - final Object externref(Object value, @SuppressWarnings("unused") TruffleString type) { + @Specialization(guards = "type == externref") + final Object externref(Object value, @SuppressWarnings("unused") WebAssemblyValueType type) { if (value == Null.instance) { return getRealm().getWasmRefNull(); } else { @@ -131,7 +130,7 @@ final Object externref(Object value, @SuppressWarnings("unused") TruffleString t @Fallback @TruffleBoundary - final Object fallback(@SuppressWarnings("unused") Object value, TruffleString type) { + final Object fallback(@SuppressWarnings("unused") Object value, WebAssemblyValueType type) { throw Errors.createTypeError("Unknown type: " + type, this); } } diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyGlobal.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyGlobal.java index 0e4a8aa1fce..fc943bd3699 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyGlobal.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyGlobal.java @@ -97,11 +97,11 @@ public static JSConstructor createConstructor(JSRealm realm) { return INSTANCE.createConstructorAndPrototype(realm); } - public static JSWebAssemblyGlobalObject create(JSContext context, JSRealm realm, Object wasmGlobal, TruffleString valueType, boolean mutable) { + public static JSWebAssemblyGlobalObject create(JSContext context, JSRealm realm, Object wasmGlobal, WebAssemblyValueType valueType, boolean mutable) { return create(context, realm, INSTANCE.getIntrinsicDefaultProto(realm), wasmGlobal, valueType, mutable); } - public static JSWebAssemblyGlobalObject create(JSContext context, JSRealm realm, JSDynamicObject proto, Object wasmGlobal, TruffleString valueType, boolean mutable) { + public static JSWebAssemblyGlobalObject create(JSContext context, JSRealm realm, JSDynamicObject proto, Object wasmGlobal, WebAssemblyValueType valueType, boolean mutable) { Object embedderData = JSWebAssembly.getEmbedderData(realm, wasmGlobal); if (embedderData instanceof JSWebAssemblyGlobalObject) { return (JSWebAssemblyGlobalObject) embedderData; diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyGlobalObject.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyGlobalObject.java index 265c5c2b133..e9c278be913 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyGlobalObject.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyGlobalObject.java @@ -47,10 +47,10 @@ public final class JSWebAssemblyGlobalObject extends JSNonProxyObject { private final Object wasmGlobal; - private final TruffleString valueType; + private final WebAssemblyValueType valueType; private final boolean mutable; - protected JSWebAssemblyGlobalObject(Shape shape, JSDynamicObject proto, Object wasmGlobal, TruffleString valueType, boolean mutable) { + protected JSWebAssemblyGlobalObject(Shape shape, JSDynamicObject proto, Object wasmGlobal, WebAssemblyValueType valueType, boolean mutable) { super(shape, proto); this.wasmGlobal = wasmGlobal; this.valueType = valueType; @@ -61,7 +61,7 @@ public Object getWASMGlobal() { return wasmGlobal; } - public TruffleString getValueType() { + public WebAssemblyValueType getValueType() { return valueType; } diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyInstance.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyInstance.java index fb88f5d346b..6294669876d 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyInstance.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyInstance.java @@ -40,6 +40,7 @@ */ package com.oracle.truffle.js.runtime.builtins.wasm; +import java.util.Arrays; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -137,6 +138,7 @@ public static JSWebAssemblyInstanceObject create(JSContext context, JSRealm real return factory.trackAllocation(newObj); } + @TruffleBoundary private static JSObject createExportsObject(JSContext context, JSRealm realm, Object wasmInstance, Object wasmModule) { JSObject exports = JSOrdinary.createWithNullPrototype(context); try { @@ -160,7 +162,8 @@ private static JSObject createExportsObject(JSContext context, JSRealm realm, Ob } else if (Strings.equals(Strings.GLOBAL, externtype)) { TruffleString type = asTString(exportInterop.readMember(exportInfo, "type")); int sepIndex = Strings.indexOf(type, ' '); - final TruffleString valueType = Strings.substring(context, type, 0, sepIndex); + final TruffleString valueTypeStr = Strings.substring(context, type, 0, sepIndex); + WebAssemblyValueType valueType = WebAssemblyValueType.valueOf(valueTypeStr.toJavaStringUncached()); final boolean mutable = Strings.regionEquals(type, sepIndex + 1, MUT, 0, 3); value = JSWebAssemblyGlobal.create(context, realm, externval, valueType, mutable); } else if (Strings.MEMORY.equals(externtype)) { @@ -169,7 +172,8 @@ private static JSObject createExportsObject(JSContext context, JSRealm realm, Ob value = JSWebAssemblyMemory.create(context, realm, externval, shared); } else { assert Strings.TABLE.equals(externtype); - TruffleString type = asTString(exportInterop.readMember(exportInfo, "type")); + TruffleString typeStr = asTString(exportInterop.readMember(exportInfo, "type")); + WebAssemblyValueType type = WebAssemblyValueType.valueOf(typeStr.toJavaStringUncached()); value = JSWebAssemblyTable.create(context, realm, externval, type); } @@ -205,17 +209,22 @@ private static WasmFunctionTypeInfo parseWasmFunctionTypeInfo(JSContext context, int idxClose = Strings.indexOf(typeInfo, ')'); TruffleString argTypes = Strings.lazySubstring(typeInfo, idxOpen + 1, idxClose - (idxOpen + 1)); TruffleString returnTypes = Strings.lazySubstring(typeInfo, idxClose + 1); - TruffleString[] paramTypes = parseTypeSequence(context, argTypes); - TruffleString[] resultTypes = parseTypeSequence(context, returnTypes); - boolean anyReturnTypeIsI64 = Strings.indexOf(typeInfo, JSWebAssemblyValueTypes.I64, idxClose + 1) >= 0; - boolean anyArgTypeIsI64 = Strings.indexOf(typeInfo, JSWebAssemblyValueTypes.I64, idxOpen + 1, idxClose) >= 0; - boolean anyReturnTypeIsV128 = Strings.indexOf(typeInfo, JSWebAssemblyValueTypes.V128, idxClose + 1) >= 0; - boolean anyArgTypeIsV128 = Strings.indexOf(typeInfo, JSWebAssemblyValueTypes.V128, idxOpen + 1, idxClose) >= 0; + WebAssemblyValueType[] paramTypes = parseTypeSequence(context, argTypes); + WebAssemblyValueType[] resultTypes = parseTypeSequence(context, returnTypes); + boolean anyReturnTypeIsI64 = Arrays.asList(resultTypes).contains(WebAssemblyValueType.i64); + boolean anyArgTypeIsI64 = Arrays.asList(paramTypes).contains(WebAssemblyValueType.i64); + boolean anyReturnTypeIsV128 = Arrays.asList(resultTypes).contains(WebAssemblyValueType.v128); + boolean anyArgTypeIsV128 = Arrays.asList(paramTypes).contains(WebAssemblyValueType.v128); return new WasmFunctionTypeInfo(paramTypes, resultTypes, anyReturnTypeIsI64 || anyArgTypeIsI64, anyReturnTypeIsV128 || anyArgTypeIsV128); } - private static TruffleString[] parseTypeSequence(JSContext context, TruffleString typeString) { - return Strings.split(context, typeString, Strings.SPACE); + private static WebAssemblyValueType[] parseTypeSequence(JSContext context, TruffleString typeString) { + TruffleString[] types = Strings.split(context, typeString, Strings.SPACE); + WebAssemblyValueType[] result = new WebAssemblyValueType[types.length]; + for (int i = 0; i < result.length; i++) { + result[i] = WebAssemblyValueType.lookupType(types[i].toJavaStringUncached()); + } + return result; } private static JSFunctionData getOrCreateExportedWasmFunctionAdapter(JSContext context, WasmFunctionTypeInfo funcType) { @@ -348,8 +357,9 @@ public static Object transformImportObject(JSContext context, JSRealm realm, Obj boolean isNumber = JSRuntime.isNumber(value); boolean isBigInt = JSRuntime.isBigInt(value); if (isNumber || context.getLanguageOptions().wasmBigInt() && isBigInt) { - TruffleString valueType = asTString(descriptorInterop.readMember(descriptor, "type")); - boolean isI64 = JSWebAssemblyValueTypes.isI64(valueType); + TruffleString valueTypeStr = asTString(descriptorInterop.readMember(descriptor, "type")); + WebAssemblyValueType valueType = WebAssemblyValueType.lookupType(valueTypeStr.toJavaStringUncached()); + boolean isI64 = valueType == WebAssemblyValueType.i64; if (!context.getLanguageOptions().wasmBigInt() && isI64) { throw createLinkErrorImport(i, module, name, "Can't import the value of i64 WebAssembly.Global"); } @@ -359,13 +369,13 @@ public static Object transformImportObject(JSContext context, JSRealm realm, Obj if (!isI64 && isBigInt) { throw createLinkErrorImport(i, module, name, "BigInt can only be stored in valtype i64"); } - if (JSWebAssemblyValueTypes.isV128(valueType)) { + if (valueType == WebAssemblyValueType.v128) { throw createLinkErrorImport(i, module, name, "Values of valtype v128 cannot be imported from JS"); } Object webAssemblyValue = ToWebAssemblyValueNodeGen.getUncached().execute(value, valueType); try { Object createGlobal = realm.getWASMGlobalAlloc(); - wasmValue = InteropLibrary.getUncached(createGlobal).execute(createGlobal, valueType, false, webAssemblyValue); + wasmValue = InteropLibrary.getUncached(createGlobal).execute(createGlobal, valueTypeStr, false, webAssemblyValue); } catch (InteropException ex) { throw Errors.shouldNotReachHere(ex); } diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyTable.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyTable.java index fc9e362466b..256c3c2ca3e 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyTable.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyTable.java @@ -98,11 +98,11 @@ public static JSConstructor createConstructor(JSRealm realm) { return INSTANCE.createConstructorAndPrototype(realm); } - public static JSWebAssemblyTableObject create(JSContext context, JSRealm realm, Object wasmTable, TruffleString elementKind) { + public static JSWebAssemblyTableObject create(JSContext context, JSRealm realm, Object wasmTable, WebAssemblyValueType elementKind) { return create(context, realm, INSTANCE.getIntrinsicDefaultProto(realm), wasmTable, elementKind); } - public static JSWebAssemblyTableObject create(JSContext context, JSRealm realm, JSDynamicObject proto, Object wasmTable, TruffleString elementKind) { + public static JSWebAssemblyTableObject create(JSContext context, JSRealm realm, JSDynamicObject proto, Object wasmTable, WebAssemblyValueType elementKind) { Object embedderData = JSWebAssembly.getEmbedderData(realm, wasmTable); if (embedderData instanceof JSWebAssemblyTableObject) { return (JSWebAssemblyTableObject) embedderData; diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyTableObject.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyTableObject.java index 1011b72bbed..656db8f621b 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyTableObject.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyTableObject.java @@ -48,9 +48,9 @@ public final class JSWebAssemblyTableObject extends JSNonProxyObject { private final Object wasmTable; - private final TruffleString elementKind; + private final WebAssemblyValueType elementKind; - protected JSWebAssemblyTableObject(Shape shape, JSDynamicObject proto, Object wasmTable, TruffleString elementKind) { + protected JSWebAssemblyTableObject(Shape shape, JSDynamicObject proto, Object wasmTable, WebAssemblyValueType elementKind) { super(shape, proto); this.wasmTable = wasmTable; this.elementKind = elementKind; @@ -60,7 +60,7 @@ public Object getWASMTable() { return wasmTable; } - public TruffleString getElementKind() { + public WebAssemblyValueType getElementKind() { return elementKind; } diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyValueTypes.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyValueTypes.java deleted file mode 100644 index 79dde88d25a..00000000000 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/JSWebAssemblyValueTypes.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * The Universal Permissive License (UPL), Version 1.0 - * - * Subject to the condition set forth below, permission is hereby granted to any - * person obtaining a copy of this software, associated documentation and/or - * data (collectively the "Software"), free of charge and under any and all - * copyright rights in the Software, and any and all patent rights owned or - * freely licensable by each licensor hereunder covering either (i) the - * unmodified Software as contributed to or provided by such licensor, or (ii) - * the Larger Works (as defined below), to deal in both - * - * (a) the Software, and - * - * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if - * one is included with the Software each a "Larger Work" to which the Software - * is contributed by such licensors), - * - * without restriction, including without limitation the rights to copy, create - * derivative works of, display, perform, and distribute the Software and make, - * use, sell, offer for sale, import, export, have made, and have sold the - * Software and the Larger Work(s), and to sublicense the foregoing rights on - * either these or other terms. - * - * This license is subject to the following condition: - * - * The above copyright notice and either this complete permission notice or at a - * minimum a reference to the UPL must be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.oracle.truffle.js.runtime.builtins.wasm; - -import com.oracle.truffle.api.strings.TruffleString; -import com.oracle.truffle.js.runtime.Errors; -import com.oracle.truffle.js.runtime.JSRealm; -import com.oracle.truffle.js.runtime.Strings; -import com.oracle.truffle.js.runtime.objects.Undefined; - -/** - * Represents the value types used in WebAssembly and provides some methods to check their string - * representations. - */ -public final class JSWebAssemblyValueTypes { - public static final TruffleString I32 = Strings.I_32; - public static final TruffleString I64 = Strings.I_64; - public static final TruffleString F32 = Strings.F_32; - public static final TruffleString F64 = Strings.F_64; - public static final TruffleString V128 = Strings.V_128; - public static final TruffleString ANYFUNC = Strings.ANYFUNC; - public static final TruffleString EXTERNREF = Strings.EXTERNREF; - - public static boolean isI32(TruffleString type) { - return Strings.equals(I32, type); - } - - public static boolean isI64(TruffleString type) { - return Strings.equals(I64, type); - } - - public static boolean isF32(TruffleString type) { - return Strings.equals(F32, type); - } - - public static boolean isF64(TruffleString type) { - return Strings.equals(F64, type); - } - - public static boolean isV128(TruffleString type) { - return Strings.equals(V128, type); - } - - public static boolean isAnyfunc(TruffleString type) { - return Strings.equals(ANYFUNC, type); - } - - public static boolean isExternref(TruffleString type) { - return Strings.equals(EXTERNREF, type); - } - - public static boolean isValueType(TruffleString type) { - return isI32(type) || isI64(type) || isF32(type) || isF64(type) || isV128(type) || isAnyfunc(type) || isExternref(type); - } - - public static boolean isReferenceType(TruffleString type) { - return isAnyfunc(type) || isExternref(type); - } - - public static Object getDefaultValue(JSRealm realm, TruffleString type) { - if (isI32(type)) { - return 0; - } else if (isI64(type)) { - return 0L; - } else if (isF32(type)) { - return 0f; - } else if (isF64(type)) { - return 0d; - } else if (isAnyfunc(type)) { - return realm.getWasmRefNull(); - } else if (isExternref(type)) { - return Undefined.instance; - } else { - throw Errors.shouldNotReachHere(); - } - } -} diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WasmFunctionTypeInfo.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WasmFunctionTypeInfo.java index e133da05154..3c9832b0a4c 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WasmFunctionTypeInfo.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WasmFunctionTypeInfo.java @@ -44,11 +44,10 @@ import java.util.Objects; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.strings.TruffleString; public record WasmFunctionTypeInfo( - @CompilationFinal(dimensions = 1) TruffleString[] paramTypes, - @CompilationFinal(dimensions = 1) TruffleString[] resultTypes, + @CompilationFinal(dimensions = 1) WebAssemblyValueType[] paramTypes, + @CompilationFinal(dimensions = 1) WebAssemblyValueType[] resultTypes, boolean anyTypeIsI64, boolean anyTypeIsV128) { @@ -82,7 +81,7 @@ public String toString() { return "(" + String.join(" ", toString(paramTypes)) + ")" + String.join(" ", toString(resultTypes)); } - private static String[] toString(TruffleString[] types) { - return Arrays.stream(types).map(Object::toString).toArray(String[]::new); + private static String[] toString(WebAssemblyValueType[] types) { + return Arrays.stream(types).map(Enum::name).toArray(String[]::new); } } diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WebAssemblyHostFunction.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WebAssemblyHostFunction.java index 5b1f144ccc6..162811cd501 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WebAssemblyHostFunction.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WebAssemblyHostFunction.java @@ -49,7 +49,6 @@ import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.InlinedBranchProfile; -import com.oracle.truffle.api.strings.TruffleString; import com.oracle.truffle.js.lang.JavaScriptLanguage; import com.oracle.truffle.js.nodes.access.GetIteratorNode; import com.oracle.truffle.js.nodes.access.IterableToListNode; @@ -106,7 +105,7 @@ public final Object execute(Object[] args, Object result = callNode.executeCall(JSArguments.create(Undefined.instance, fn, jsArgs)); - TruffleString[] resultTypes = type.resultTypes(); + WebAssemblyValueType[] resultTypes = type.resultTypes(); if (resultTypes.length == 0) { return Undefined.instance; } else if (resultTypes.length == 1) { diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WebAssemblyValueType.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WebAssemblyValueType.java new file mode 100644 index 00000000000..4a37b51f335 --- /dev/null +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/wasm/WebAssemblyValueType.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.oracle.truffle.js.runtime.builtins.wasm; + +import com.oracle.truffle.js.runtime.Errors; +import com.oracle.truffle.js.runtime.JSRealm; +import com.oracle.truffle.js.runtime.objects.Undefined; + +/** + * Represents the value types used in WebAssembly. + * + * See org.graalvm.wasm.api.ValueType. + */ +public enum WebAssemblyValueType { + i32(false), + i64(false), + f32(false), + f64(false), + v128(false), + anyfunc(true), + externref(true); + + private final boolean reference; + + WebAssemblyValueType(boolean reference) { + this.reference = reference; + } + + public boolean isReference() { + return reference; + } + + public Object getDefaultValue(JSRealm realm) { + return switch (this) { + case i32 -> 0; + case i64 -> 0L; + case f32 -> 0f; + case f64 -> 0d; + case anyfunc -> realm.getWasmRefNull(); + case externref -> Undefined.instance; + default -> throw Errors.shouldNotReachHereUnexpectedValue(this); + }; + } + + public static WebAssemblyValueType lookupType(String type) { + return switch (type) { + case "i32" -> i32; + case "i64" -> i64; + case "f32" -> f32; + case "f64" -> f64; + case "v128" -> v128; + case "anyfunc" -> anyfunc; + case "externref" -> externref; + default -> null; + }; + } +}