From 0057bbd00d2156bf4cd55df546930fb5b23b1834 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 4 Oct 2024 09:00:51 +0200 Subject: [PATCH] wasm gc: fix issue with extracting elements from arrays of JS objects --- jso/impl/src/main/java/org/teavm/jso/impl/JS.java | 3 +++ .../java/org/teavm/jso/impl/JSClassProcessor.java | 10 ++++++++++ .../jso/impl/wasmgc/WasmGCJSDependencies.java | 11 +++++++++++ .../teavm/jso/impl/wasmgc/WasmGCJSIntrinsic.java | 14 ++++++++++++-- .../java/org/teavm/jso/impl/wasmgc/WasmGCJso.java | 2 ++ .../java/org/teavm/jso/test/ConversionTest.java | 1 - 6 files changed, 38 insertions(+), 3 deletions(-) diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JS.java b/jso/impl/src/main/java/org/teavm/jso/impl/JS.java index 6922fdbe2..6fe6051f1 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JS.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JS.java @@ -785,4 +785,7 @@ public final class JS { @InjectedBy(JSNativeInjector.class) @NoSideEffects public static native boolean isNull(JSObject o); + + @NoSideEffects + public static native Object jsArrayItem(Object array, int index); } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java b/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java index 21be0f282..906e54ba2 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/JSClassProcessor.java @@ -435,6 +435,16 @@ class JSClassProcessor { unwrap.setLocation(insn.getLocation()); insn.setReceiver(unwrap.getArguments().get(0)); insn.insertNext(unwrap); + + if (wasmGC) { + var invoke = new InvokeInstruction(); + invoke.setType(InvocationType.SPECIAL); + invoke.setMethod(new MethodReference(JS.class, "jsArrayItem", Object.class, int.class, Object.class)); + invoke.setReceiver(insn.getReceiver()); + invoke.setArguments(insn.getArray(), insn.getIndex()); + invoke.setLocation(insn.getLocation()); + insn.replace(invoke); + } } } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSDependencies.java b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSDependencies.java index 68c89fc90..cb7f74379 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSDependencies.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSDependencies.java @@ -19,7 +19,9 @@ import static org.teavm.jso.impl.wasmgc.WasmGCJSConstants.JS_TO_STRING; import static org.teavm.jso.impl.wasmgc.WasmGCJSConstants.STRING_TO_JS; import org.teavm.dependency.AbstractDependencyListener; import org.teavm.dependency.DependencyAgent; +import org.teavm.dependency.MethodDependency; import org.teavm.jso.JSObject; +import org.teavm.jso.impl.JS; import org.teavm.jso.impl.JSWrapper; import org.teavm.model.MethodReference; @@ -37,4 +39,13 @@ class WasmGCJSDependencies extends AbstractDependencyListener { agent.linkMethod(new MethodReference(JSWrapper.class, "createWrapper", JSObject.class, Object.class)) .use(); } + + @Override + public void methodReached(DependencyAgent agent, MethodDependency method) { + if (method.getMethod().getOwnerName().equals(JS.class.getName())) { + if (method.getMethod().getName().equals("jsArrayItem")) { + method.getVariable(1).getArrayItem().connect(method.getResult()); + } + } + } } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSIntrinsic.java b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSIntrinsic.java index a98d0e054..26b78f5d0 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSIntrinsic.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJSIntrinsic.java @@ -22,6 +22,7 @@ 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.WasmArrayGet; import org.teavm.backend.wasm.model.expression.WasmBlock; import org.teavm.backend.wasm.model.expression.WasmBranch; import org.teavm.backend.wasm.model.expression.WasmCall; @@ -32,6 +33,7 @@ import org.teavm.backend.wasm.runtime.gc.WasmGCSupport; import org.teavm.jso.JSObject; import org.teavm.jso.impl.JS; import org.teavm.model.MethodReference; +import org.teavm.model.ValueType; class WasmGCJSIntrinsic implements WasmGCIntrinsic { private WasmFunction globalFunction; @@ -53,9 +55,11 @@ class WasmGCJSIntrinsic implements WasmGCIntrinsic { return new WasmCall(getGlobalFunction(context), name); } case "throwCCEIfFalse": - return throwCCEIfFalse(context, invocation); + return throwCCEIfFalse(invocation, context); case "isNull": return new WasmIsNull(context.generate(invocation.getArguments().get(0))); + case "jsArrayItem": + return arrayItem(invocation, context); default: throw new IllegalArgumentException(); } @@ -74,7 +78,7 @@ class WasmGCJSIntrinsic implements WasmGCIntrinsic { return globalFunction; } - private WasmExpression throwCCEIfFalse(WasmGCIntrinsicContext context, InvocationExpr invocation) { + private WasmExpression throwCCEIfFalse(InvocationExpr invocation, WasmGCIntrinsicContext context) { var block = new WasmBlock(false); block.setType(WasmType.Reference.EXTERN); @@ -93,4 +97,10 @@ class WasmGCJSIntrinsic implements WasmGCIntrinsic { block.getBody().add(context.generate(invocation.getArguments().get(1))); return block; } + + private WasmExpression arrayItem(InvocationExpr invocation, WasmGCIntrinsicContext context) { + var array = context.generate(invocation.getArguments().get(0)); + var arrayType = context.classInfoProvider().getClassInfo(ValueType.parse(Object[].class)).getArray(); + return new WasmArrayGet(arrayType, array, context.generate(invocation.getArguments().get(1))); + } } diff --git a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJso.java b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJso.java index c004e7055..4e721d70c 100644 --- a/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJso.java +++ b/jso/impl/src/main/java/org/teavm/jso/impl/wasmgc/WasmGCJso.java @@ -44,6 +44,8 @@ public final class WasmGCJso { wasmGCHost.addIntrinsic(new MethodReference(JS.class, "throwCCEIfFalse", boolean.class, JSObject.class, JSObject.class), jsIntrinsic); wasmGCHost.addIntrinsic(new MethodReference(JS.class, "isNull", JSObject.class, boolean.class), jsIntrinsic); + wasmGCHost.addIntrinsic(new MethodReference(JS.class, "jsArrayItem", Object.class, int.class, Object.class), + jsIntrinsic); var wrapperIntrinsic = new WasmGCJSWrapperIntrinsic(); wasmGCHost.addIntrinsic(new MethodReference(JSWrapper.class, "wrap", JSObject.class, Object.class), diff --git a/tests/src/test/java/org/teavm/jso/test/ConversionTest.java b/tests/src/test/java/org/teavm/jso/test/ConversionTest.java index d1c9bed71..e8a3e7fe1 100644 --- a/tests/src/test/java/org/teavm/jso/test/ConversionTest.java +++ b/tests/src/test/java/org/teavm/jso/test/ConversionTest.java @@ -138,7 +138,6 @@ public class ConversionTest { } @Test - @SkipPlatform(TestPlatform.WEBASSEMBLY_GC) public void convertsArrayOfJSObject() { assertEquals("(foo)", surround(new JSString[] { JSString.valueOf("foo") })[0].stringValue()); assertEquals("(foo)", surround(new JSString[][] {{ JSString.valueOf("foo") }})[0][0].stringValue());