wasm gc: fix issue with extracting elements from arrays of JS objects

This commit is contained in:
Alexey Andreev 2024-10-04 09:00:51 +02:00
parent eba0e2b2e8
commit 0057bbd00d
6 changed files with 38 additions and 3 deletions

View File

@ -785,4 +785,7 @@ public final class JS {
@InjectedBy(JSNativeInjector.class) @InjectedBy(JSNativeInjector.class)
@NoSideEffects @NoSideEffects
public static native boolean isNull(JSObject o); public static native boolean isNull(JSObject o);
@NoSideEffects
public static native Object jsArrayItem(Object array, int index);
} }

View File

@ -435,6 +435,16 @@ class JSClassProcessor {
unwrap.setLocation(insn.getLocation()); unwrap.setLocation(insn.getLocation());
insn.setReceiver(unwrap.getArguments().get(0)); insn.setReceiver(unwrap.getArguments().get(0));
insn.insertNext(unwrap); 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);
}
} }
} }

View File

@ -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 static org.teavm.jso.impl.wasmgc.WasmGCJSConstants.STRING_TO_JS;
import org.teavm.dependency.AbstractDependencyListener; import org.teavm.dependency.AbstractDependencyListener;
import org.teavm.dependency.DependencyAgent; import org.teavm.dependency.DependencyAgent;
import org.teavm.dependency.MethodDependency;
import org.teavm.jso.JSObject; import org.teavm.jso.JSObject;
import org.teavm.jso.impl.JS;
import org.teavm.jso.impl.JSWrapper; import org.teavm.jso.impl.JSWrapper;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
@ -37,4 +39,13 @@ class WasmGCJSDependencies extends AbstractDependencyListener {
agent.linkMethod(new MethodReference(JSWrapper.class, "createWrapper", JSObject.class, Object.class)) agent.linkMethod(new MethodReference(JSWrapper.class, "createWrapper", JSObject.class, Object.class))
.use(); .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());
}
}
}
} }

View File

@ -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.intrinsics.gc.WasmGCIntrinsicContext;
import org.teavm.backend.wasm.model.WasmFunction; import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmType; 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.WasmBlock;
import org.teavm.backend.wasm.model.expression.WasmBranch; import org.teavm.backend.wasm.model.expression.WasmBranch;
import org.teavm.backend.wasm.model.expression.WasmCall; 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.JSObject;
import org.teavm.jso.impl.JS; import org.teavm.jso.impl.JS;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;
import org.teavm.model.ValueType;
class WasmGCJSIntrinsic implements WasmGCIntrinsic { class WasmGCJSIntrinsic implements WasmGCIntrinsic {
private WasmFunction globalFunction; private WasmFunction globalFunction;
@ -53,9 +55,11 @@ class WasmGCJSIntrinsic implements WasmGCIntrinsic {
return new WasmCall(getGlobalFunction(context), name); return new WasmCall(getGlobalFunction(context), name);
} }
case "throwCCEIfFalse": case "throwCCEIfFalse":
return throwCCEIfFalse(context, invocation); return throwCCEIfFalse(invocation, context);
case "isNull": case "isNull":
return new WasmIsNull(context.generate(invocation.getArguments().get(0))); return new WasmIsNull(context.generate(invocation.getArguments().get(0)));
case "jsArrayItem":
return arrayItem(invocation, context);
default: default:
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
@ -74,7 +78,7 @@ class WasmGCJSIntrinsic implements WasmGCIntrinsic {
return globalFunction; return globalFunction;
} }
private WasmExpression throwCCEIfFalse(WasmGCIntrinsicContext context, InvocationExpr invocation) { private WasmExpression throwCCEIfFalse(InvocationExpr invocation, WasmGCIntrinsicContext context) {
var block = new WasmBlock(false); var block = new WasmBlock(false);
block.setType(WasmType.Reference.EXTERN); block.setType(WasmType.Reference.EXTERN);
@ -93,4 +97,10 @@ class WasmGCJSIntrinsic implements WasmGCIntrinsic {
block.getBody().add(context.generate(invocation.getArguments().get(1))); block.getBody().add(context.generate(invocation.getArguments().get(1)));
return block; 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)));
}
} }

View File

@ -44,6 +44,8 @@ public final class WasmGCJso {
wasmGCHost.addIntrinsic(new MethodReference(JS.class, "throwCCEIfFalse", boolean.class, JSObject.class, wasmGCHost.addIntrinsic(new MethodReference(JS.class, "throwCCEIfFalse", boolean.class, JSObject.class,
JSObject.class), jsIntrinsic); JSObject.class), jsIntrinsic);
wasmGCHost.addIntrinsic(new MethodReference(JS.class, "isNull", JSObject.class, boolean.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(); var wrapperIntrinsic = new WasmGCJSWrapperIntrinsic();
wasmGCHost.addIntrinsic(new MethodReference(JSWrapper.class, "wrap", JSObject.class, Object.class), wasmGCHost.addIntrinsic(new MethodReference(JSWrapper.class, "wrap", JSObject.class, Object.class),

View File

@ -138,7 +138,6 @@ public class ConversionTest {
} }
@Test @Test
@SkipPlatform(TestPlatform.WEBASSEMBLY_GC)
public void convertsArrayOfJSObject() { public void convertsArrayOfJSObject() {
assertEquals("(foo)", surround(new JSString[] { JSString.valueOf("foo") })[0].stringValue()); assertEquals("(foo)", surround(new JSString[] { JSString.valueOf("foo") })[0].stringValue());
assertEquals("(foo)", surround(new JSString[][] {{ JSString.valueOf("foo") }})[0][0].stringValue()); assertEquals("(foo)", surround(new JSString[][] {{ JSString.valueOf("foo") }})[0][0].stringValue());