Skip to content

Commit b735af2

Browse files
committed
[GR-53758] [GR-53760] [GR-53926] [GR-53932] [GR-53940] [GR-53942] WebAssembly fixes for testv8 tests.
PullRequest: graal/17669
2 parents ca11aa2 + fd54917 commit b735af2

File tree

11 files changed

+152
-117
lines changed

11 files changed

+152
-117
lines changed

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/Assert.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ public static void assertIntEqual(int actual, int expected, String message, Fail
7070

7171
public static void assertIntGreaterOrEqual(int n1, int n2, Failure failure) throws WasmException {
7272
if (n1 < n2) {
73-
fail(failure, format("%s: %d should be > %d", failure.name, n1, n2));
73+
fail(failure, format("%s: %d should be >= %d", failure.name, n1, n2));
7474
}
7575
}
7676

@@ -86,7 +86,7 @@ public static void assertIntLessOrEqual(int n1, int n2, Failure failure) throws
8686

8787
public static void assertIntLess(int n1, int n2, Failure failure) throws WasmException {
8888
if (n1 >= n2) {
89-
fail(failure, format("%s: %d should be <= %d", failure.name, n1, n2));
89+
fail(failure, format("%s: %d should be < %d", failure.name, n1, n2));
9090
}
9191
}
9292

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/BinaryParser.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,7 +1525,7 @@ private void readNumericInstructions(ParserState state, int opcode) {
15251525
break;
15261526
case Instructions.ATOMIC:
15271527
checkThreadsSupport(opcode);
1528-
int atomicOpcode = read1() & 0xFF;
1528+
int atomicOpcode = readUnsignedInt32();
15291529
state.addAtomicFlag();
15301530
switch (atomicOpcode) {
15311531
case Instructions.ATOMIC_NOTIFY:
@@ -1802,7 +1802,7 @@ private void readNumericInstructions(ParserState state, int opcode) {
18021802
break;
18031803
case Instructions.VECTOR:
18041804
checkSIMDSupport();
1805-
int vectorOpcode = read1() & 0xFF;
1805+
int vectorOpcode = readUnsignedInt32();
18061806
state.addVectorFlag();
18071807
switch (vectorOpcode) {
18081808
case Instructions.VECTOR_V128_LOAD:

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/Linker.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@
103103
import com.oracle.truffle.api.CompilerAsserts;
104104
import com.oracle.truffle.api.CompilerDirectives;
105105
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
106+
import com.oracle.truffle.api.TruffleContext;
106107

107108
public class Linker {
108109
public enum LinkState {
@@ -248,8 +249,25 @@ private static void runStartFunctions(Map<String, WasmInstance> instances, Array
248249
static void runStartFunction(WasmInstance instance) {
249250
final WasmFunction start = instance.symbolTable().startFunction();
250251
if (start != null) {
251-
WasmInstance targetInstance = !start.isImported() ? instance : instance.functionInstance(start.index()).moduleInstance();
252-
instance.target(start.index()).call(WasmArguments.create(targetInstance));
252+
if (start.isImported()) {
253+
final WasmFunctionInstance functionInstance = instance.functionInstance(start.index());
254+
final WasmContext currentContext = WasmContext.get(null);
255+
final WasmContext functionInstanceContext = functionInstance.context();
256+
if (functionInstanceContext == currentContext) {
257+
instance.target(start.index()).call(WasmArguments.create(functionInstance.moduleInstance()));
258+
} else {
259+
// Enter function's context when it is not from the current one
260+
TruffleContext truffleContext = functionInstance.getTruffleContext();
261+
Object prev = truffleContext.enter(null);
262+
try {
263+
instance.target(start.index()).call(WasmArguments.create(functionInstance.moduleInstance()));
264+
} finally {
265+
truffleContext.leave(null, prev);
266+
}
267+
}
268+
} else {
269+
instance.target(start.index()).call(WasmArguments.create(instance));
270+
}
253271
}
254272
}
255273

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/WasmContext.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,19 @@ public final class WasmContext {
6767
private final FdManager filesManager;
6868
private final WasmContextOptions contextOptions;
6969

70+
/**
71+
* Optional grow callback to notify the embedder.
72+
*/
73+
private Object memGrowCallback;
74+
/**
75+
* JS callback to implement part of memory.atomic.notify.
76+
*/
77+
private Object memNotifyCallback;
78+
/**
79+
* JS callback to implement part of memory.atomic.waitN.
80+
*/
81+
private Object memWaitCallback;
82+
7083
public WasmContext(Env env, WasmLanguage language) {
7184
this.env = env;
7285
this.language = language;
@@ -222,4 +235,34 @@ public WasmContextOptions getContextOptions() {
222235
public static WasmContext get(Node node) {
223236
return REFERENCE.get(node);
224237
}
238+
239+
public void setMemGrowCallback(Object callback) {
240+
this.memGrowCallback = callback;
241+
}
242+
243+
public Object getMemGrowCallback() {
244+
return memGrowCallback;
245+
}
246+
247+
public void setMemNotifyCallback(Object callback) {
248+
this.memNotifyCallback = callback;
249+
}
250+
251+
public Object getMemNotifyCallback() {
252+
return memNotifyCallback;
253+
}
254+
255+
public void setMemWaitCallback(Object callback) {
256+
this.memWaitCallback = callback;
257+
}
258+
259+
public Object getMemWaitCallback() {
260+
return memWaitCallback;
261+
}
262+
263+
public void inheritCallbacksFromParentContext(WasmContext parent) {
264+
setMemGrowCallback(parent.getMemGrowCallback());
265+
setMemNotifyCallback(parent.getMemNotifyCallback());
266+
setMemWaitCallback(parent.getMemWaitCallback());
267+
}
225268
}

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/api/ImportModule.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ protected WasmInstance createInstance(WasmLanguage language, WasmContext context
8686
final WasmFunction function = info.getLeft();
8787
final Object executable = info.getRight();
8888
final SymbolTable.FunctionType type = function.type();
89-
if (executable instanceof WasmFunctionInstance) {
90-
defineExportedFunction(instance, functionName, type.paramTypes(), type.resultTypes(), (WasmFunctionInstance) executable);
89+
if (executable instanceof WasmFunctionInstance functionInstance) {
90+
defineExportedFunction(instance, functionName, functionInstance);
9191
} else {
9292
var executableWrapper = new ExecuteInParentContextNode(context.language(), module, executable, function.resultCount());
9393
WasmFunction exported = defineFunction(context, module, functionName, type.paramTypes(), type.resultTypes(), executableWrapper);

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/api/WebAssembly.java

Lines changed: 62 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
import com.oracle.truffle.api.interop.InvalidArrayIndexException;
8282
import com.oracle.truffle.api.interop.UnknownIdentifierException;
8383
import com.oracle.truffle.api.interop.UnsupportedMessageException;
84+
import com.oracle.truffle.api.nodes.Node;
8485

8586
public class WebAssembly extends Dictionary {
8687
private final WasmContext currentContext;
@@ -142,6 +143,7 @@ public WasmInstance moduleInstantiate(WasmModule module, Object importObject) {
142143
final Object prev = innerTruffleContext.enter(null);
143144
try {
144145
final WasmContext instanceContext = WasmContext.get(null);
146+
instanceContext.inheritCallbacksFromParentContext(currentContext);
145147
WasmInstance instance = instantiateModule(module, importObject, instanceContext, innerTruffleContext);
146148
instanceContext.linker().tryLink(instance);
147149
return instance;
@@ -511,9 +513,6 @@ private static Object tableGrow(Object[] args) {
511513
WasmTable table = (WasmTable) args[0];
512514
int delta = (Integer) args[1];
513515
if (args.length > 2) {
514-
if (InteropLibrary.getUncached().isNull(args[2])) {
515-
return tableGrow(table, delta, WasmConstant.NULL);
516-
}
517516
return tableGrow(table, delta, args[2]);
518517
}
519518
return tableGrow(table, delta, WasmConstant.NULL);
@@ -705,24 +704,33 @@ public static long memGrow(WasmMemory memory, int delta) {
705704
}
706705

707706
private static Object memSetGrowCallback(Object[] args) {
707+
checkArgumentCount(args, 1);
708708
InteropLibrary lib = InteropLibrary.getUncached();
709-
if (!(args[0] instanceof WasmMemory)) {
710-
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "First argument must be wasm memory");
709+
if (args.length > 1) {
710+
// TODO: drop this branch after JS adopts the single-argument version
711+
if (!(args[0] instanceof WasmMemory)) {
712+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "First argument must be executable");
713+
}
714+
if (!lib.isExecutable(args[1])) {
715+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Second argument must be executable");
716+
}
717+
return memSetGrowCallback(args[1]);
711718
}
712-
if (!lib.isExecutable(args[1])) {
713-
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Second argument must be executable");
719+
if (!lib.isExecutable(args[0])) {
720+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Argument must be executable");
714721
}
715-
WasmMemory memory = (WasmMemory) args[0];
716-
return memSetGrowCallback(memory, args[1]);
722+
return memSetGrowCallback(args[0]);
717723
}
718724

719-
private static Object memSetGrowCallback(WasmMemory memory, Object callback) {
720-
memory.setGrowCallback(callback);
725+
private static Object memSetGrowCallback(Object callback) {
726+
WasmContext context = WasmContext.get(null);
727+
context.setMemGrowCallback(callback);
721728
return WasmConstant.VOID;
722729
}
723730

724731
public static void invokeMemGrowCallback(WasmMemory memory) {
725-
Object callback = memory.getGrowCallback();
732+
WasmContext context = WasmContext.get(null);
733+
Object callback = context.getMemGrowCallback();
726734
if (callback != null) {
727735
InteropLibrary lib = InteropLibrary.getUncached();
728736
try {
@@ -734,24 +742,33 @@ public static void invokeMemGrowCallback(WasmMemory memory) {
734742
}
735743

736744
private static Object memSetNotifyCallback(Object[] args) {
745+
checkArgumentCount(args, 1);
737746
InteropLibrary lib = InteropLibrary.getUncached();
738-
if (!(args[0] instanceof WasmMemory)) {
739-
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "First argument must be wasm memory");
747+
if (args.length > 1) {
748+
// TODO: drop this branch after JS adopts the single-argument version
749+
if (!(args[0] instanceof WasmMemory)) {
750+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "First argument must be executable");
751+
}
752+
if (!lib.isExecutable(args[1])) {
753+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Second argument must be executable");
754+
}
755+
return memSetNotifyCallback(args[1]);
740756
}
741-
if (!lib.isExecutable(args[1])) {
742-
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Second argument must be executable");
757+
if (!lib.isExecutable(args[0])) {
758+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Argument must be executable");
743759
}
744-
WasmMemory memory = (WasmMemory) args[0];
745-
return memSetNotifyCallback(memory, args[1]);
760+
return memSetNotifyCallback(args[0]);
746761
}
747762

748-
private static Object memSetNotifyCallback(WasmMemory memory, Object callback) {
749-
memory.setNotifyCallback(callback);
763+
private static Object memSetNotifyCallback(Object callback) {
764+
WasmContext context = WasmContext.get(null);
765+
context.setMemNotifyCallback(callback);
750766
return WasmConstant.VOID;
751767
}
752768

753-
public static int invokeMemNotifyCallback(WasmMemory memory, long address, int count) {
754-
Object callback = memory.getNotifyCallback();
769+
public static int invokeMemNotifyCallback(Node node, WasmMemory memory, long address, int count) {
770+
WasmContext context = WasmContext.get(node);
771+
Object callback = context.getMemNotifyCallback();
755772
if (callback != null) {
756773
InteropLibrary lib = InteropLibrary.getUncached();
757774
try {
@@ -764,24 +781,33 @@ public static int invokeMemNotifyCallback(WasmMemory memory, long address, int c
764781
}
765782

766783
private static Object memSetWaitCallback(Object[] args) {
784+
checkArgumentCount(args, 1);
767785
InteropLibrary lib = InteropLibrary.getUncached();
768-
if (!(args[0] instanceof WasmMemory)) {
769-
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "First argument must be wasm memory");
786+
if (args.length > 1) {
787+
// TODO: drop this branch after JS adopts the single-argument version
788+
if (!(args[0] instanceof WasmMemory)) {
789+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "First argument must be executable");
790+
}
791+
if (!lib.isExecutable(args[1])) {
792+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Second argument must be executable");
793+
}
794+
return memSetWaitCallback(args[1]);
770795
}
771-
if (!lib.isExecutable(args[1])) {
772-
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Second argument must be executable");
796+
if (!lib.isExecutable(args[0])) {
797+
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Argument must be executable");
773798
}
774-
WasmMemory memory = (WasmMemory) args[0];
775-
return memSetWaitCallback(memory, args[1]);
799+
return memSetWaitCallback(args[0]);
776800
}
777801

778-
private static Object memSetWaitCallback(WasmMemory memory, Object callback) {
779-
memory.setWaitCallback(callback);
802+
private static Object memSetWaitCallback(Object callback) {
803+
WasmContext context = WasmContext.get(null);
804+
context.setMemWaitCallback(callback);
780805
return WasmConstant.VOID;
781806
}
782807

783-
public static int invokeMemWaitCallback(WasmMemory memory, long address, long expected, long timeout, boolean is64) {
784-
Object callback = memory.getWaitCallback();
808+
public static int invokeMemWaitCallback(Node node, WasmMemory memory, long address, long expected, long timeout, boolean is64) {
809+
WasmContext context = WasmContext.get(node);
810+
Object callback = context.getMemWaitCallback();
785811
if (callback != null) {
786812
InteropLibrary lib = InteropLibrary.getUncached();
787813
try {
@@ -839,23 +865,14 @@ public WasmGlobal globalAlloc(ValueType valueType, boolean mutable, Object value
839865
case f64:
840866
return new DefaultWasmGlobal(valueType, mutable, Double.doubleToRawLongBits(valueInterop.asDouble(value)));
841867
case anyfunc:
842-
if (!refTypes) {
868+
if (!refTypes || !(value == WasmConstant.NULL || value instanceof WasmFunctionInstance)) {
843869
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Invalid value type");
844870
}
845-
if (valueInterop.isNull(value)) {
846-
return new DefaultWasmGlobal(valueType, mutable, WasmConstant.NULL);
847-
} else if (value instanceof WasmFunctionInstance) {
848-
return new DefaultWasmGlobal(valueType, mutable, value);
849-
}
850-
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Invalid value type");
851-
871+
return new DefaultWasmGlobal(valueType, mutable, value);
852872
case externref:
853873
if (!refTypes) {
854874
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Invalid value type");
855875
}
856-
if (valueInterop.isNull(value)) {
857-
return new DefaultWasmGlobal(valueType, mutable, WasmConstant.NULL);
858-
}
859876
return new DefaultWasmGlobal(valueType, mutable, value);
860877
default:
861878
throw new WasmJsApiException(WasmJsApiException.Kind.TypeError, "Invalid value type");
@@ -935,9 +952,7 @@ public Object globalWrite(WasmGlobal global, Object value) {
935952
if (!refTypes) {
936953
throw WasmJsApiException.format(WasmJsApiException.Kind.TypeError, "Invalid value type. Reference types are not enabled");
937954
}
938-
if (InteropLibrary.getUncached(value).isNull(value)) {
939-
global.storeObject(WasmConstant.NULL);
940-
} else if (!(value instanceof WasmFunctionInstance)) {
955+
if (!(value == WasmConstant.NULL || value instanceof WasmFunctionInstance)) {
941956
throw WasmJsApiException.format(WasmJsApiException.Kind.TypeError, "Global type %s, value: %s", valueType, value);
942957
} else {
943958
global.storeObject(value);
@@ -947,11 +962,7 @@ public Object globalWrite(WasmGlobal global, Object value) {
947962
if (!refTypes) {
948963
throw WasmJsApiException.format(WasmJsApiException.Kind.TypeError, "Invalid value type. Reference types are not enabled");
949964
}
950-
if (InteropLibrary.getUncached(value).isNull(value)) {
951-
global.storeObject(WasmConstant.NULL);
952-
} else {
953-
global.storeObject(value);
954-
}
965+
global.storeObject(value);
955966
break;
956967
}
957968
return WasmConstant.VOID;

wasm/src/org.graalvm.wasm/src/org/graalvm/wasm/memory/ByteArrayWasmMemory.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ public int atomic_notify(Node node, long address, int count) {
983983
if (!this.isShared()) {
984984
return 0;
985985
}
986-
return invokeNotifyCallback(address, count);
986+
return invokeNotifyCallback(node, address, count);
987987
}
988988

989989
@Override
@@ -996,7 +996,7 @@ public int atomic_wait32(Node node, long address, int expected, long timeout) {
996996
if (!this.isShared()) {
997997
throw trapUnsharedMemory(node);
998998
}
999-
return invokeWaitCallback(address, expected, timeout, false);
999+
return invokeWaitCallback(node, address, expected, timeout, false);
10001000
}
10011001

10021002
@Override
@@ -1009,7 +1009,7 @@ public int atomic_wait64(Node node, long address, long expected, long timeout) {
10091009
if (!this.isShared()) {
10101010
throw trapUnsharedMemory(node);
10111011
}
1012-
return invokeWaitCallback(address, expected, timeout, true);
1012+
return invokeWaitCallback(node, address, expected, timeout, true);
10131013
}
10141014

10151015
@Override

0 commit comments

Comments
 (0)