| // 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-reftypes --expose-gc |
| |
| load("test/mjsunit/wasm/wasm-module-builder.js"); |
| |
| (function testExternRefIdentityFunction() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_r_r) |
| .addBody([kExprLocalGet, 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 testPassExternRefToImportedFunction() { |
| 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([kExprLocalGet, 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 testPassExternRefWithGCWithLocals() { |
| 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(kWasmExternRef, 10) |
| .addBody([ |
| kExprLocalGet, 0, kExprLocalSet, 1, // Set local |
| kExprLocalGet, 0, kExprLocalSet, 2, // Set local |
| kExprLocalGet, 0, kExprLocalSet, 3, // Set local |
| kExprLocalGet, 0, kExprLocalSet, 4, // Set local |
| kExprLocalGet, 0, kExprLocalSet, 5, // Set local |
| kExprLocalGet, 0, kExprLocalSet, 6, // Set local |
| kExprLocalGet, 0, kExprLocalSet, 7, // Set local |
| kExprLocalGet, 0, kExprLocalSet, 8, // Set local |
| kExprLocalGet, 0, kExprLocalSet, 9, // Set local |
| kExprLocalGet, 0, kExprLocalSet, 10, // Set local |
| kExprCallFunction, gc_index, // call gc |
| kExprLocalGet, 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 testPassExternRefWithGC() { |
| 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 |
| kExprLocalGet, 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 testPassExternRefWithGCWithStackParameters() { |
| 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 externref parameters. |
| const mysig = makeSig(Array(num_params).fill(kWasmExternRef), []); |
| 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 |
| kExprLocalGet, 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 testPassExternRefWithGCInWrapper() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| const kSig_r_iri = makeSig([kWasmI32, kWasmExternRef, kWasmI32], [kWasmExternRef]); |
| const sig_index = builder.addType(kSig_r_iri); |
| builder.addFunction('main', sig_index) |
| .addBody([kExprLocalGet, 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 testExternRefNull() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_r_v) |
| .addBody([kExprRefNull, kWasmExternRef]) |
| .exportFunc(); |
| |
| const instance = builder.instantiate(); |
| |
| assertEquals(null, instance.exports.main()); |
| })(); |
| |
| (function testExternRefIsNull() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_i_r) |
| .addBody([kExprLocalGet, 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 testExternRefNullIsNull() { |
| print(arguments.callee.name); |
| |
| const builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_i_v) |
| .addBody([kExprRefNull, kWasmExternRef, kExprRefIsNull]) |
| .exportFunc(); |
| |
| const instance = builder.instantiate(); |
| |
| assertEquals(1, instance.exports.main()); |
| })(); |
| |
| (function testExternRefLocalDefaultValue() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| builder.addFunction('main', kSig_r_v) |
| .addBody([kExprLocalGet, 0]) |
| .addLocals(kWasmExternRef, 1) |
| .exportFunc(); |
| |
| const instance = builder.instantiate(); |
| |
| assertEquals(null, instance.exports.main()); |
| })(); |
| |
| (function testImplicitReturnNullAsExternRef() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| const sig_index = builder.addType(kSig_r_v); |
| builder.addFunction('main', sig_index) |
| .addBody([kExprRefNull, kWasmExternRef]) |
| .exportFunc(); |
| |
| const main = builder.instantiate().exports.main; |
| assertEquals(null, main()); |
| })(); |
| |
| (function testExplicitReturnNullAsExternRef() { |
| print(arguments.callee.name); |
| const builder = new WasmModuleBuilder(); |
| const sig_index = builder.addType(kSig_r_v); |
| builder.addFunction('main', sig_index) |
| .addBody([kExprRefNull, kWasmExternRef, kExprReturn]) |
| .exportFunc(); |
| |
| const main = builder.instantiate().exports.main; |
| assertEquals(null, main()); |
| })(); |