wasm gc: support primitive array conversion to JavaScript in JSO

This commit is contained in:
Alexey Andreev 2024-09-28 19:52:14 +02:00
parent bbf45760b8
commit 5ad4496c34
7 changed files with 34 additions and 13 deletions

View File

@ -18,7 +18,7 @@ var TeaVM = TeaVM || {};
TeaVM.wasm = function() {
let exports;
let getGlobalName = function(name) {
return eval("return " + {name});
return eval(name);
}
function defaults(imports) {
let stderr = "";

View File

@ -746,7 +746,6 @@ public final class JS {
@InjectedBy(JSNativeInjector.class)
@NoSideEffects
@Import(name = "global", module = "teavmJso")
public static native JSObject global(String name);
@InjectedBy(JSNativeInjector.class)

View File

@ -29,7 +29,7 @@ class WasmGCJSFunctions {
if (function == null) {
var extern = WasmType.SpecialReferenceKind.EXTERN.asNonNullType();
var constructorParamTypes = new WasmType[index + 1];
Arrays.fill(constructorParamTypes, extern);
Arrays.fill(constructorParamTypes, WasmType.Reference.EXTERN);
var functionType = context.functionTypes().of(extern, constructorParamTypes);
function = new WasmFunction(functionType);
function.setName(context.names().topLevel("teavm.js:createFunction" + index));
@ -44,11 +44,9 @@ class WasmGCJSFunctions {
WasmFunction getFunctionCaller(WasmGCIntrinsicContext context, int index) {
var function = callers[index];
if (function == null) {
var extern = WasmType.SpecialReferenceKind.EXTERN.asNonNullType();
var paramTypes = new WasmType[index + 1];
Arrays.fill(paramTypes, extern);
paramTypes[0] = WasmType.Reference.EXTERN;
var functionType = context.functionTypes().of(extern, paramTypes);
Arrays.fill(paramTypes, WasmType.Reference.EXTERN);
var functionType = context.functionTypes().of(WasmType.Reference.EXTERN, paramTypes);
function = new WasmFunction(functionType);
function.setName(context.names().topLevel("teavm.js:callFunction" + index));
function.setImportModule("teavmJso");

View File

@ -20,10 +20,17 @@ import static org.teavm.jso.impl.wasmgc.WasmGCJSConstants.STRING_TO_JS;
import org.teavm.ast.InvocationExpr;
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsic;
import org.teavm.backend.wasm.intrinsics.gc.WasmGCIntrinsicContext;
import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmType;
import org.teavm.backend.wasm.model.expression.WasmCall;
import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.jso.JSObject;
import org.teavm.jso.impl.JS;
import org.teavm.model.MethodReference;
class WasmGCJSIntrinsic implements WasmGCIntrinsic {
private WasmFunction globalFunction;
@Override
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
switch (invocation.getMethod().getName()) {
@ -35,8 +42,26 @@ class WasmGCJSIntrinsic implements WasmGCIntrinsic {
var function = context.functions().forStaticMethod(JS_TO_STRING);
return new WasmCall(function, context.generate(invocation.getArguments().get(0)));
}
case "global": {
var stringToJs = context.functions().forStaticMethod(STRING_TO_JS);
var name = new WasmCall(stringToJs, context.generate(invocation.getArguments().get(0)));
return new WasmCall(getGlobalFunction(context), name);
}
default:
throw new IllegalArgumentException();
}
}
private WasmFunction getGlobalFunction(WasmGCIntrinsicContext context) {
if (globalFunction == null) {
globalFunction = new WasmFunction(context.functionTypes().of(WasmType.Reference.EXTERN,
WasmType.Reference.EXTERN));
globalFunction.setName(context.names().suggestForMethod(new MethodReference(JS.class,
"global", String.class, JSObject.class)));
globalFunction.setImportName("global");
globalFunction.setImportModule("teavmJso");
context.module().functions.add(globalFunction);
}
return globalFunction;
}
}

View File

@ -20,12 +20,14 @@ import org.teavm.backend.wasm.generate.gc.classes.WasmGCCustomTypeMapperFactory;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCCustomTypeMapperFactoryContext;
import org.teavm.backend.wasm.model.WasmType;
import org.teavm.jso.JSObject;
import org.teavm.jso.core.JSArray;
class WasmGCJSTypeMapper implements WasmGCCustomTypeMapper, WasmGCCustomTypeMapperFactory {
@Override
public WasmType map(String className) {
if (className.equals(JSObject.class.getName())) {
return WasmType.SpecialReferenceKind.EXTERN.asNonNullType();
if (className.equals(JSObject.class.getName())
|| className.equals(JSArray.class.getName())) {
return WasmType.Reference.EXTERN;
}
return null;
}

View File

@ -35,5 +35,6 @@ public final class WasmGCJso {
wasmGCHost.addIntrinsic(new MethodReference(JS.class, "wrap", String.class, JSObject.class), jsIntrinsic);
wasmGCHost.addIntrinsic(new MethodReference(JS.class, "unwrapString", JSObject.class, String.class),
jsIntrinsic);
wasmGCHost.addIntrinsic(new MethodReference(JS.class, "global", String.class, JSObject.class), jsIntrinsic);
}
}

View File

@ -58,7 +58,6 @@ public class ConversionTest {
}
@Test
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
public void convertsPrimitiveArraysToJavaScript() {
assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays(new boolean[] { true }, new byte[] { 2 },
new short[] { 3 }, new char[] { '@' }, new int[] { 4 }, new float[] { 5.5F }, new double[] { 6.5 },
@ -84,7 +83,6 @@ public class ConversionTest {
}
@Test
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
public void convertsPrimitiveArrays2ToJavaScript() {
assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays2(new boolean[][] {{ true }},
new byte[][] {{ 2 }}, new short[][] {{ 3 }}, new char[][] {{ '@' }}, new int[][] {{ 4 }},
@ -111,7 +109,6 @@ public class ConversionTest {
}
@Test
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
public void convertsPrimitiveArrays4ToJavaScript() {
assertEquals("true:2:3:64:4:5.5:6.5:foo", combinePrimitiveArrays4(new boolean[][][][] {{{{ true }}}},
new byte[][][][] {{{{ 2 }}}}, new short[][][][] {{{{ 3 }}}}, new char[][][][] {{{{ '@' }}}},
@ -153,7 +150,6 @@ public class ConversionTest {
}
@Test
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
public void copiesArray() {
int[] array = { 23 };
assertEquals(24, mutate(array));