| // Copyright 2018 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // Flags: --expose-wasm --experimental-wasm-anyref --expose-gc |
| |
| load("test/mjsunit/wasm/wasm-module-builder.js"); |
| |
| (function testAnyRefIdentityFunction() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_r_r) |
| .addBody([kExprGetLocal, 0]) |
| .exportFunc(); |
| |
| |
| const instance = builder.instantiate(); |
| |
| let obj = {'hello' : 'world'}; |
| assertEquals(obj, instance.exports.main(obj)); |
| assertEquals(1234, instance.exports.main(1234)); |
| assertEquals(123.4, instance.exports.main(123.4)); |
| assertEquals(undefined, instance.exports.main(undefined)); |
| assertEquals(null, instance.exports.main(null)); |
| assertEquals(print, instance.exports.main(print)); |
| })(); |
| |
| (function testPassAnyRefToImportedFunction() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| const sig_index = builder.addType(kSig_v_r); |
| const imp_index = builder.addImport("q", "func", sig_index); |
| builder.addFunction('main', sig_index) |
| .addBody([kExprGetLocal, 0, |
| kExprCallFunction, imp_index]) |
| .exportFunc(); |
| |
| function checkFunction(value) { |
| assertEquals('world', value.hello); |
| } |
| |
| const instance = builder.instantiate({q: {func: checkFunction}}); |
| |
| instance.exports.main({hello: 'world'}); |
| })(); |
| |
| (function testPassAnyRefWithGCWithLocals() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| const ref_sig = builder.addType(kSig_v_r); |
| const void_sig = builder.addType(kSig_v_v); |
| const imp_index = builder.addImport("q", "func", ref_sig); |
| const gc_index = builder.addImport("q", "gc", void_sig); |
| // First call the gc, then check if the object still exists. |
| builder.addFunction('main', ref_sig) |
| .addLocals({anyref_count: 10}) |
| .addBody([ |
| kExprGetLocal, 0, kExprSetLocal, 1, // Set local |
| kExprGetLocal, 0, kExprSetLocal, 2, // Set local |
| kExprGetLocal, 0, kExprSetLocal, 3, // Set local |
| kExprGetLocal, 0, kExprSetLocal, 4, // Set local |
| kExprGetLocal, 0, kExprSetLocal, 5, // Set local |
| kExprGetLocal, 0, kExprSetLocal, 6, // Set local |
| kExprGetLocal, 0, kExprSetLocal, 7, // Set local |
| kExprGetLocal, 0, kExprSetLocal, 8, // Set local |
| kExprGetLocal, 0, kExprSetLocal, 9, // Set local |
| kExprGetLocal, 0, kExprSetLocal, 10, // Set local |
| kExprCallFunction, gc_index, // call gc |
| kExprGetLocal, 9, kExprCallFunction, imp_index // call import |
| ]) |
| .exportFunc(); |
| |
| function checkFunction(value) { |
| assertEquals('world', value.hello); |
| } |
| |
| const instance = builder.instantiate({q: {func: checkFunction, gc: gc}}); |
| |
| instance.exports.main({hello: 'world'}); |
| })(); |
| |
| (function testPassAnyRefWithGC() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| const ref_sig = builder.addType(kSig_v_r); |
| const void_sig = builder.addType(kSig_v_v); |
| const imp_index = builder.addImport("q", "func", ref_sig); |
| const gc_index = builder.addImport("q", "gc", void_sig); |
| // First call the gc, then check if the object still exists. |
| builder.addFunction('main', ref_sig) |
| .addBody([ |
| kExprCallFunction, gc_index, // call gc |
| kExprGetLocal, 0, kExprCallFunction, imp_index // call import |
| ]) |
| .exportFunc(); |
| |
| function checkFunction(value) { |
| assertEquals('world', value.hello); |
| } |
| |
| const instance = builder.instantiate({q: {func: checkFunction, gc: gc}}); |
| |
| instance.exports.main({hello: 'world'}); |
| })(); |
| |
| (function testPassAnyRefWithGCWithStackParameters() { |
| print(arguments.callee.name); |
| const num_params = 15; |
| for (let index = 0; index < num_params; index++) { |
| const builder = new WasmModuleBuilder(); |
| // Make a signature with {num_params} many anyref parameters. |
| const mysig = makeSig(Array(num_params).fill(kWasmAnyRef), []); |
| const main_sig = builder.addType(mysig); |
| const ref_sig = builder.addType(kSig_v_r); |
| const void_sig = builder.addType(kSig_v_v); |
| const imp_index = builder.addImport('q', 'func', ref_sig); |
| const gc_index = builder.addImport('q', 'gc', void_sig); |
| // First call the gc, then check if the object still exists. |
| builder.addFunction('main', main_sig) |
| .addBody([ |
| kExprCallFunction, gc_index, // call gc |
| kExprGetLocal, index, kExprCallFunction, imp_index // call import |
| ]) |
| .exportFunc(); |
| |
| function checkFunction(value) { |
| assertEquals(index, value.hello); |
| } |
| |
| const instance = builder.instantiate({q: {func: checkFunction, gc: gc}}); |
| |
| // Pass {num_params} many parameters to main. Note that it is important |
| // that no other references to these objects exist. They are kept alive |
| // only through references stored in the parameters slots of a stack frame. |
| instance.exports.main( |
| {hello: 0}, {hello: 1}, {hello: 2}, {hello: 3}, {hello: 4}, {hello: 5}, |
| {hello: 6}, {hello: 7}, {hello: 8}, {hello: 9}, {hello: 10}, |
| {hello: 11}, {hello: 12}, {hello: 13}, {hello: 14}); |
| } |
| })(); |
| |
| (function testPassAnyRefWithGCInWrapper() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| const kSig_r_iri = makeSig([kWasmI32, kWasmAnyRef, kWasmI32], [kWasmAnyRef]); |
| const sig_index = builder.addType(kSig_r_iri); |
| builder.addFunction('main', sig_index) |
| .addBody([kExprGetLocal, 1]) |
| .exportFunc(); |
| |
| const instance = builder.instantiate(); |
| |
| const triggerGCParam = { |
| valueOf: () => { |
| gc(); |
| return 17; |
| } |
| }; |
| |
| const result = instance.exports.main(triggerGCParam, {hello: 'world'}, triggerGCParam); |
| assertEquals('world', result.hello); |
| })(); |
| |
| (function testAnyRefNull() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_r_v) |
| .addBody([kExprRefNull]) |
| .exportFunc(); |
| |
| const instance = builder.instantiate(); |
| |
| assertEquals(null, instance.exports.main()); |
| })(); |
| |
| (function testAnyRefIsNull() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_i_r) |
| .addBody([kExprGetLocal, 0, kExprRefIsNull]) |
| .exportFunc(); |
| |
| const instance = builder.instantiate(); |
| |
| assertEquals(0, instance.exports.main({'hello' : 'world'})); |
| assertEquals(0, instance.exports.main(1234)); |
| assertEquals(0, instance.exports.main(0)); |
| assertEquals(0, instance.exports.main(123.4)); |
| assertEquals(0, instance.exports.main(undefined)); |
| assertEquals(1, instance.exports.main(null)); |
| assertEquals(0, instance.exports.main(print)); |
| })(); |
| |
| (function testAnyRefNullIsNull() { |
| print(arguments.callee.name); |
| |
| const builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_i_v) |
| .addBody([kExprRefNull, kExprRefIsNull]) |
| .exportFunc(); |
| |
| const instance = builder.instantiate(); |
| |
| assertEquals(1, instance.exports.main()); |
| })(); |
| |
| (function testAnyRefLocalDefaultValue() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_r_v) |
| .addBody([kExprGetLocal, 0]) |
| .addLocals({anyref_count: 1}) |
| .exportFunc(); |
| |
| const instance = builder.instantiate(); |
| |
| assertEquals(null, instance.exports.main()); |
| })(); |
| |
| (function testImplicitReturnNullRefAsAnyRef() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| const sig_index = builder.addType(kSig_r_v); |
| builder.addFunction('main', sig_index) |
| .addBody([kExprRefNull]) |
| .exportFunc(); |
| |
| const main = builder.instantiate().exports.main; |
| assertEquals(null, main()); |
| })(); |
| |
| (function testExplicitReturnNullRefAsAnyRef() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| const sig_index = builder.addType(kSig_r_v); |
| builder.addFunction('main', sig_index) |
| .addBody([kExprRefNull, kExprReturn]) |
| .exportFunc(); |
| |
| const main = builder.instantiate().exports.main; |
| assertEquals(null, main()); |
| })(); |