| // Copyright 2016 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 --allow-natives-syntax |
| |
| load("test/mjsunit/wasm/wasm-constants.js"); |
| load("test/mjsunit/wasm/wasm-module-builder.js"); |
| |
| var expect_elison = 0; |
| var expect_no_elison = 1; |
| // function calls stack: first_export -> first_func -> first_import -> |
| // second_export -> second_import |
| // In this case, first_import and second_export have same signature, |
| // So that wrappers will be removed |
| (function TestWasmWrapperElision() { |
| var imported = function (a) { |
| return a; |
| }; |
| |
| var second_module = new WasmModuleBuilder(); |
| var sig_index = second_module.addType(kSig_i_i); |
| second_module |
| .addImport("import_module_2", "import_name_2", sig_index); |
| second_module |
| .addFunction("second_export", sig_index) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprCallFunction, 0, |
| kExprReturn |
| ]) |
| .exportFunc(); |
| |
| var first_module = new WasmModuleBuilder(); |
| var sig_index = first_module.addType(kSig_i_i); |
| first_module |
| .addImport("import_module_1", "import_name_1", sig_index); |
| first_module |
| .addFunction("first_export", sig_index) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprCallFunction, 2, |
| kExprReturn |
| ]) |
| .exportFunc(); |
| first_module |
| .addFunction("first_func", sig_index) |
| .addBody([ |
| kExprI32Const, 1, |
| kExprGetLocal, 0, |
| kExprI32Add, |
| kExprCallFunction, 0, |
| kExprReturn |
| ]); |
| |
| var f = second_module |
| .instantiate({import_module_2: {import_name_2: imported}}) |
| .exports.second_export; |
| var the_export = first_module |
| .instantiate({import_module_1: {import_name_1: f}}) |
| .exports.first_export; |
| assertEquals(the_export(2), 3); |
| assertEquals(the_export(-1), 0); |
| assertEquals(the_export(0), 1); |
| assertEquals(the_export(5.5), 6); |
| assertEquals(%CheckWasmWrapperElision(the_export, expect_elison), true); |
| })(); |
| |
| // Function calls stack: first_export -> first_func -> first_import -> |
| // second_export -> second_import |
| // In this test, first_import and second_export have the same signature, and |
| // therefore the wrappers will be removed. If the wrappers are not removed, then |
| // the test crashes because of the int64 parameter, which is not allowed in the |
| // wrappers. |
| (function TestWasmWrapperElisionInt64() { |
| var imported = function (a) { |
| return a; |
| }; |
| |
| var second_module = new WasmModuleBuilder(); |
| var sig_index1 = second_module.addType(kSig_i_i); |
| var sig_index_ll = second_module.addType(kSig_l_l); |
| second_module |
| .addImport("import_module_2", "import_name_2", sig_index1); |
| second_module |
| .addFunction("second_export", sig_index_ll) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprI32ConvertI64, |
| kExprCallFunction, 0, |
| kExprI64SConvertI32, |
| kExprReturn |
| ]) |
| .exportFunc(); |
| |
| var first_module = new WasmModuleBuilder(); |
| var sig_index = first_module.addType(kSig_i_v); |
| var sig_index_ll = first_module.addType(kSig_l_l); |
| first_module |
| .addImport("import_module_1", "import_name_1", sig_index_ll); |
| first_module |
| .addFunction("first_export", sig_index) |
| .addBody([ |
| kExprI64Const, 2, |
| kExprCallFunction, 2, |
| kExprI32ConvertI64, |
| kExprReturn |
| ]) |
| .exportFunc(); |
| first_module |
| .addFunction("first_func", sig_index_ll) |
| .addBody([ |
| kExprI64Const, 1, |
| kExprGetLocal, 0, |
| kExprI64Add, |
| kExprCallFunction, 0, |
| kExprReturn |
| ]); |
| |
| var f = second_module |
| .instantiate({import_module_2: {import_name_2: imported}}) |
| .exports.second_export; |
| var the_export = first_module |
| .instantiate({import_module_1: {import_name_1: f}}) |
| .exports.first_export; |
| assertEquals(the_export(), 3); |
| })(); |
| |
| // function calls stack: first_export -> first_func -> first_import -> |
| // second_export -> second_import |
| // In this case, second_export has fewer params than first_import, |
| // so instantiation should fail. |
| assertThrows(function TestWasmWrapperNoElisionLessParams() { |
| var imported = function (a) { |
| return a; |
| }; |
| |
| var second_module = new WasmModuleBuilder(); |
| var sig_index_1 = second_module.addType(kSig_i_i); |
| second_module |
| .addImport("import_module_2", "import_name_2", sig_index_1); |
| second_module |
| .addFunction("second_export", sig_index_1) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprCallFunction, 0, |
| kExprReturn |
| ]) |
| .exportFunc(); |
| |
| var first_module = new WasmModuleBuilder(); |
| var sig_index_2 = first_module.addType(kSig_i_ii); |
| first_module |
| .addImport("import_module_1", "import_name_1", sig_index_2); |
| first_module |
| .addFunction("first_export", sig_index_2) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprGetLocal, 1, |
| kExprCallFunction, 2, |
| kExprReturn |
| ]) |
| .exportFunc(); |
| first_module |
| .addFunction("first_func", sig_index_2) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprGetLocal, 1, |
| kExprCallFunction, 0, |
| kExprReturn |
| ]); |
| |
| var f = second_module |
| .instantiate({import_module_2: {import_name_2: imported}}) |
| .exports.second_export; |
| var the_export = first_module |
| .instantiate({import_module_1: {import_name_1: f}}) |
| .exports.first_export; |
| assertEquals(the_export(4, 5), 4); |
| assertEquals(the_export(-1, 4), -1); |
| assertEquals(the_export(0, 2), 0); |
| assertEquals(the_export(9.9, 4.3), 9); |
| assertEquals(%CheckWasmWrapperElision(the_export, expect_no_elison), true); |
| }); |
| |
| // function calls stack: first_export -> first_func -> first_import -> |
| // second_export -> second_import |
| // In this case, second_export has more params than first_import, |
| // so instantiation should fail. |
| assertThrows(function TestWasmWrapperNoElisionMoreParams() { |
| var imported = function (a, b, c) { |
| return a+b+c; |
| }; |
| |
| var second_module = new WasmModuleBuilder(); |
| var sig_index_3 = second_module.addType(kSig_i_iii); |
| second_module |
| .addImport("import_module_2", "import_name_2", sig_index_3); |
| second_module |
| .addFunction("second_export", sig_index_3) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprGetLocal, 1, |
| kExprGetLocal, 2, |
| kExprCallFunction, 0, |
| kExprReturn |
| ]) |
| .exportFunc(); |
| |
| var first_module = new WasmModuleBuilder(); |
| var sig_index_2 = first_module.addType(kSig_i_ii); |
| first_module |
| .addImport("import_module_1", "import_name_1", sig_index_2); |
| first_module |
| .addFunction("first_export", sig_index_2) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprGetLocal, 1, |
| kExprCallFunction, 2, |
| kExprReturn |
| ]) |
| .exportFunc(); |
| first_module |
| .addFunction("first_func", sig_index_2) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprGetLocal, 1, |
| kExprCallFunction, 0, |
| kExprReturn |
| ]); |
| |
| var f = second_module |
| .instantiate({import_module_2: {import_name_2: imported}}) |
| .exports.second_export; |
| var the_export = first_module |
| .instantiate({import_module_1: {import_name_1: f}}) |
| .exports.first_export; |
| assertEquals(the_export(5, 6), 11); |
| assertEquals(the_export(-1, -4), -5); |
| assertEquals(the_export(0, 0), 0); |
| assertEquals(the_export(1.1, 2.7), 3); |
| assertEquals(%CheckWasmWrapperElision(the_export, expect_no_elison), true); |
| }); |
| |
| // function calls stack: first_export -> first_func -> first_import -> |
| // second_export -> second_import |
| // In this case, second_export has different params type with first_import, |
| // so instantiation should fail. |
| assertThrows(function TestWasmWrapperNoElisionTypeMismatch() { |
| var imported = function (a, b) { |
| return a+b; |
| }; |
| |
| var second_module = new WasmModuleBuilder(); |
| var sig_index_2 = second_module.addType(kSig_d_dd); |
| second_module |
| .addImport("import_module_2", "import_name_2", sig_index_2); |
| second_module |
| .addFunction("second_export", sig_index_2) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprGetLocal, 1, |
| kExprCallFunction, 0, |
| kExprReturn |
| ]) |
| .exportFunc(); |
| |
| var first_module = new WasmModuleBuilder(); |
| var sig_index_2 = first_module.addType(kSig_i_ii); |
| first_module |
| .addImport("import_module_1", "import_name_1", sig_index_2); |
| first_module |
| .addFunction("first_export", sig_index_2) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprGetLocal, 1, |
| kExprCallFunction, 2, |
| kExprReturn |
| ]) |
| .exportFunc(); |
| first_module |
| .addFunction("first_func", sig_index_2) |
| .addBody([ |
| kExprGetLocal, 0, |
| kExprGetLocal, 1, |
| kExprCallFunction, 0, |
| kExprReturn |
| ]); |
| |
| var f = second_module |
| .instantiate({import_module_2: {import_name_2: imported}}) |
| .exports.second_export; |
| var the_export = first_module |
| .instantiate({import_module_1: {import_name_1: f}}) |
| .exports.first_export; |
| assertEquals(the_export(2.8, 9.1), 11); |
| assertEquals(the_export(-1.7, -2.5), -3); |
| assertEquals(the_export(0.0, 0.0), 0); |
| assertEquals(the_export(2, -2), 0); |
| assertEquals(%CheckWasmWrapperElision(the_export, expect_no_elison), true); |
| }); |
| |
| |
| (function TestSimpleI64Ret() { |
| var builder = new WasmModuleBuilder(); |
| builder.addFunction("exp", kSig_l_v) |
| .addBody([ |
| kExprI64Const, 23 |
| ]) |
| .exportFunc(); |
| var exported = builder.instantiate().exports.exp; |
| |
| var builder = new WasmModuleBuilder(); |
| builder.addImport("imp", "func", kSig_l_v); |
| builder.addFunction("main", kSig_i_v) |
| .addBody([ |
| kExprCallFunction, 0, |
| kExprI32ConvertI64 |
| ]) |
| .exportFunc(); |
| |
| var instance = builder.instantiate({imp: {func: exported}}); |
| |
| assertEquals(23, instance.exports.main()); |
| |
| })(); |