[wasm][wasm-gc][test] Improve and extend Javascript testing API

Changes:
- Add possibility to define and emit all reference types.
- Simplify function locals definition.
- Change 'type' to 'type_index' where appropiate.

Bug: v8:7748
Change-Id: Ie35a6204369e678298ee2ff2ec7c7793c5315c3e
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2390144
Commit-Queue: Manos Koukoutos <manoskouk@chromium.org>
Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#69814}
This commit is contained in:
Manos Koukoutos 2020-09-10 12:39:52 +00:00 committed by Commit Bot
parent ff0c5cfaf6
commit 79a1468831
46 changed files with 168 additions and 170 deletions

View File

@ -12,7 +12,7 @@ var builder = new WasmModuleBuilder();
// clang-format off
var func_idx = builder.addFunction('helper', kSig_v_v)
.addLocals({ i32_count: 1 })
.addLocals(kWasmI32, 1 )
.addBody([
kExprNop,
kExprI32Const, 12,

View File

@ -80,10 +80,9 @@ async function instantiateWasm() {
])
.exportAs('main');
builder.addFunction('B (liftoff)', kSig_v_i)
.addLocals(
{i32_count: 1, f32_count: 4},
['i32_arg', 'i32_local', 'f32_local', '0', '0'])
builder.addFunction('B (liftoff)', kSig_v_i, ['i32_arg'])
.addLocals(kWasmI32, 1, ['i32_local'])
.addLocals(kWasmF32, 4, ['f32_local', '0', '0'])
.addBody([
// Load a parameter and a constant onto the operand stack.
kExprLocalGet, 0, kExprI32Const, 3,
@ -96,8 +95,8 @@ async function instantiateWasm() {
]);
// A third function which will be stepped through.
let func = builder.addFunction('C (interpreted)', kSig_v_i)
.addLocals({i32_count: 1}, ['i32_arg', 'i32_local'])
let func = builder.addFunction('C (interpreted)', kSig_v_i, ['i32_arg'])
.addLocals(kWasmI32, 1, ['i32_local'])
.addBody([
// Set global 0 to param 0.
kExprLocalGet, 0, kExprGlobalSet, 0,

View File

@ -74,36 +74,37 @@ async function instantiateWasm() {
// Add a function without breakpoint, to check that locals are shown
// correctly in compiled code.
const main = builder.addFunction('call_func', kSig_v_i).addLocals({f32_count: 1}).addBody([
// Set local 1 to 7.2.
...wasmF32Const(7.2), kExprLocalSet, 1,
// Call function 'func', forwarding param 0.
kExprLocalGet, 0, kExprCallFunction, 1
]).exportAs('main');
const main = builder.addFunction('call_func', kSig_v_i).addLocals(kWasmF32, 1)
.addBody([
// Set local 1 to 7.2.
...wasmF32Const(7.2), kExprLocalSet, 1,
// Call function 'func', forwarding param 0.
kExprLocalGet, 0, kExprCallFunction, 1
]).exportAs('main');
// A second function which will be stepped through.
const func = builder.addFunction('func', kSig_v_i)
.addLocals(
{i32_count: 1, i64_count: 1, f64_count: 3},
['i32Arg', undefined, 'i64_local', 'unicode☼f64', '0', '0'])
.addBody([
// Set param 0 to 11.
kExprI32Const, 11, kExprLocalSet, 0,
// Set local 1 to 47.
kExprI32Const, 47, kExprLocalSet, 1,
// Set local 2 to 0x7FFFFFFFFFFFFFFF (max i64).
kExprI64Const, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0,
kExprLocalSet, 2,
// Set local 2 to 0x8000000000000000 (min i64).
kExprI64Const, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f,
kExprLocalSet, 2,
// Set local 3 to 1/7.
kExprI32Const, 1, kExprF64UConvertI32, kExprI32Const, 7,
kExprF64UConvertI32, kExprF64Div, kExprLocalSet, 3,
const func = builder.addFunction('func', kSig_v_i, ['i32Arg'])
.addLocals(kWasmI32, 1)
.addLocals(kWasmI64, 1, ['i64_local'])
.addLocals(kWasmF64, 3, ['unicode☼f64', '0', '0'])
.addBody([
// Set param 0 to 11.
kExprI32Const, 11, kExprLocalSet, 0,
// Set local 1 to 47.
kExprI32Const, 47, kExprLocalSet, 1,
// Set local 2 to 0x7FFFFFFFFFFFFFFF (max i64).
kExprI64Const, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0,
kExprLocalSet, 2,
// Set local 2 to 0x8000000000000000 (min i64).
kExprI64Const, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7f,
kExprLocalSet, 2,
// Set local 3 to 1/7.
kExprI32Const, 1, kExprF64UConvertI32, kExprI32Const, 7,
kExprF64UConvertI32, kExprF64Div, kExprLocalSet, 3,
// Set global 0 to 15
kExprI32Const, 15, kExprGlobalSet, 0,
]);
// Set global 0 to 15
kExprI32Const, 15, kExprGlobalSet, 0,
]);
// Append function to table to test function table output.
builder.appendToTable([main.index]);
@ -114,8 +115,10 @@ async function instantiateWasm() {
function addWasmJSToTable() {
// Create WasmJS functions to test the function tables output.
const js_func = function js_func() { return 7; };
const wasmjs_func = new WebAssembly.Function({parameters:[], results:['i32']}, js_func);
const wasmjs_anonymous_func = new WebAssembly.Function({parameters:[], results:['i32']}, _ => 7);
const wasmjs_func = new WebAssembly.Function(
{parameters:[], results:['i32']}, js_func);
const wasmjs_anonymous_func = new WebAssembly.Function(
{parameters:[], results:['i32']}, _ => 7);
instance.exports.exported_table.set(0, wasmjs_func);
instance.exports.exported_table.set(1, wasmjs_anonymous_func);
@ -123,7 +126,8 @@ async function instantiateWasm() {
InspectorTest.log('Calling instantiate function.');
await WasmInspectorTest.instantiate(moduleBytes);
await WasmInspectorTest.evalWithUrl(`(${addWasmJSToTable})()`, 'populateTable');
await WasmInspectorTest.evalWithUrl(`(${addWasmJSToTable})()`,
'populateTable');
}
function printIfFailure(message) {

View File

@ -11,7 +11,7 @@ var builder = new WasmModuleBuilder();
// clang-format off
var func_idx = builder.addFunction('helper', kSig_v_v)
.addLocals({ i32_count: 1 })
.addLocals(kWasmI32, 1)
.addBody([
kExprNop,
kExprI32Const, 12,

View File

@ -11,9 +11,8 @@ session.setupScriptMap();
const builder = new WasmModuleBuilder();
// Create a function which computes the div of the first two arguments.
builder.addFunction('div', kSig_i_iii)
.addLocals(
{i32_count: 2}, ['a', 'b', 'unused', 'local_zero', 'local_const_11'])
builder.addFunction('div', kSig_i_iii, ['a', 'b', 'unused'])
.addLocals(kWasmI32, 2, ['local_zero', 'local_const_11'])
.addBody([
kExprI32Const, 11, // const 11
kExprLocalSet, 4, // set local #4 ('local_const_11')

View File

@ -34,7 +34,7 @@ var func_b = builder.addFunction('wasm_B', kSig_v_i)
.exportAs('main');
let fact = builder.addFunction('fact', kSig_i_i)
.addLocals({i32_count: 1})
.addLocals(kWasmI32, 1)
.addBody([
// clang-format off
kExprLocalGet, 0,

View File

@ -15,7 +15,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
kExprI32Add,
]).exportFunc();
builder.addFunction("main", kSig_i_i)
.addLocals({except_count: 1})
.addLocals(kWasmExnRef, 1)
.addBody([
kExprTry, kWasmStmt,
kExprLocalGet, 0,

View File

@ -6,9 +6,9 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addFunction('main', kSig_i_iii)
.addLocals({f32_count: 4})
.addLocals({i64_count: 1})
.addLocals({f32_count: 2})
.addLocals(kWasmF32, 4)
.addLocals(kWasmI64, 1)
.addLocals(kWasmF32, 2)
.addBodyWithEnd([
kExprI64Const, 0,
kExprLocalGet, 3,

View File

@ -19,7 +19,7 @@ kExprEnd, // @5
]);
// Generate function 2 (out of 2).
builder.addFunction(undefined, 1 /* sig */)
.addLocals({f32_count: 1}).addLocals({i32_count: 13})
.addLocals(kWasmF32, 1).addLocals(kWasmI32, 13)
.addBodyWithEnd([
// signature: v_v
// body:

View File

@ -18,7 +18,7 @@ kExprEnd, // @3
]);
// Generate function 2 (out of 2).
builder.addFunction(undefined, 1 /* sig */)
.addLocals({f64_count: 8})
.addLocals(kWasmF64, 8)
.addBodyWithEnd([
// signature: d_v
// body:

View File

@ -10,7 +10,7 @@ const builder = new WasmModuleBuilder();
builder.addType(makeSig([kWasmI32, kWasmI32, kWasmI32], [kWasmI32]));
// Generate function 1 (out of 1).
builder.addFunction(undefined, 0 /* sig */)
.addLocals({i32_count: 2}).addLocals({f32_count: 2})
.addLocals(kWasmI32, 2).addLocals(kWasmF32, 2)
.addBodyWithEnd([
// signature: i_iii
// body:

View File

@ -12,7 +12,7 @@ builder.addGlobal(kWasmI32, 1);
const sig = builder.addType(makeSig([kWasmI32, kWasmI64, kWasmI64, kWasmI64], [kWasmF32]));
// Generate function 1 (out of 3).
builder.addFunction(undefined, sig)
.addLocals({i32_count: 57}).addLocals({i64_count: 11})
.addLocals(kWasmI32, 57).addLocals(kWasmI64, 11)
.addBodyWithEnd([
// signature: f_illl
// body:

View File

@ -11,7 +11,7 @@ builder.addMemory(1, 1, false, true);
const sig = builder.addType(makeSig([], [kWasmI32]));
builder.addFunction(undefined, sig)
.addLocals({i32_count: 1002}).addLocals({i64_count: 3})
.addLocals(kWasmI32, 1002).addLocals(kWasmI64, 3)
.addBodyWithEnd([
// signature: i_v
// body:

View File

@ -16,10 +16,10 @@ const sig = builder.addType(makeSig(
[kWasmI64]));
// Generate function 2 (out of 3).
builder.addFunction(undefined, sig)
.addLocals({f32_count: 10})
.addLocals({i32_count: 4})
.addLocals({f64_count: 1})
.addLocals({i32_count: 15})
.addLocals(kWasmF32, 10)
.addLocals(kWasmI32, 4)
.addLocals(kWasmF64, 1)
.addLocals(kWasmI32, 15)
.addBodyWithEnd([
// signature: v_liliiiiiilll
// body:

View File

@ -5,7 +5,7 @@
load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addFunction(undefined, kSig_v_v).addLocals({i64_count: 1}).addBody([
builder.addFunction(undefined, kSig_v_v).addLocals(kWasmI64, 1).addBody([
kExprI64Const, 0xeb, 0xd7, 0xaf, 0xdf,
0xbe, 0xfd, 0xfa, 0xf5, 0x6b, // i64.const
kExprI32Const, 0, // i32.const

View File

@ -6,7 +6,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
sig0 = makeSig([], [kWasmI32]);
builder.addFunction(undefined, sig0).addLocals({i64_count: 1}).addBody([
builder.addFunction(undefined, sig0).addLocals(kWasmI64, 1).addBody([
kExprLoop, kWasmI32, // loop i32
kExprF32Const, 0x00, 0x00, 0x00, 0x00, // f32.const 0 --> f32:0
kExprLocalGet, 0x00, // get_local 0 --> i64:0

View File

@ -49,7 +49,7 @@ assertEquals(1, instance.exports.main());
const builder2 = new WasmModuleBuilder();
sig0 = makeSig([], [kWasmI32]);
builder2.addFunction(undefined, sig0).addLocals({i64_count: 1}).addBody([
builder2.addFunction(undefined, sig0).addLocals(kWasmI64, 1).addBody([
kExprLoop, kWasmI32, // loop i32
kExprLocalGet, 0, // get_local 3
kExprF32SConvertI64, // f32.sconvert/i64

View File

@ -9,6 +9,6 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
let builder = new WasmModuleBuilder();
builder.addFunction("main", kSig_i_i)
.addBody([kExprLocalGet, 0])
.addLocals({s128_count: 1});
.addLocals(kWasmS128, 1)
assertFalse(WebAssembly.validate(builder.toBuffer()));

View File

@ -41,7 +41,7 @@ builder.addImport('mod', 'get', kSig_i_v);
builder.addImport('mod', 'call', kSig_v_i);
builder.
addFunction('main', kSig_v_v).
addLocals({i32_count: kNumLocals}).
addLocals(kWasmI32, kNumLocals).
addBody(body).
exportAs('main');
let m1_bytes = builder.toBuffer();

View File

@ -6,6 +6,6 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
var builder = new WasmModuleBuilder();
builder.addFunction(undefined, kSig_i_i)
.addLocals({i32_count: 0xffffffff})
.addLocals(kWasmI32, 0xffffffff)
.addBody([]);
assertThrows(() => builder.instantiate(), WebAssembly.CompileError);

View File

@ -6,7 +6,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addFunction(undefined, makeSig([kWasmI32, kWasmF32], []))
.addLocals({i32_count: 7})
.addLocals(kWasmI32, 7)
.addBody([
kExprLocalGet, 0, // get_local
kExprI32Const, 0, // i32.const 0

View File

@ -32,7 +32,7 @@ const gen_i32_code = [
kExprI32Const, 1, // i32.const 1
kExprI32Add // i32.add --> 2nd param
];
builder.addFunction(undefined, kSig_v_v).addLocals({i32_count: 1}).addBody([
builder.addFunction(undefined, kSig_v_v).addLocals(kWasmI32, 1).addBody([
// Generate six values on the stack, then six more to force the other six on
// the stack.
...wasmI32Const(0), // i32.const 0

View File

@ -16,7 +16,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
var builder = new WasmModuleBuilder();
var func_idx = builder.addFunction('helper', kSig_i_v)
.addLocals({i32_count: 1})
.addLocals(kWasmI32, 1)
.addBody([
kExprI32Const, 0x01,
]).index;

View File

@ -13,7 +13,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
kExprEnd, // @1
]);
builder.addFunction(undefined, 1 /* sig */)
.addLocals({i32_count: 65})
.addLocals(kWasmI32, 65)
.addBodyWithEnd([
kExprLoop, kWasmStmt, // @3
kSimdPrefix,

View File

@ -9,7 +9,7 @@ builder.addGlobal(kWasmI32, 1);
builder.addGlobal(kWasmF32, 1);
builder.addType(makeSig([kWasmI32, kWasmF32, kWasmF32, kWasmF64], [kWasmI32]));
builder.addFunction(undefined, 0 /* sig */)
.addLocals({i32_count: 504})
.addLocals(kWasmI32, 504)
.addBody([
kExprGlobalGet, 0x00,
kExprLocalSet, 0x04,

View File

@ -7,7 +7,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
const sig = builder.addType(makeSig([], [kWasmF64]));
builder.addFunction(undefined, sig)
.addLocals({f32_count: 5}).addLocals({f64_count: 3})
.addLocals(kWasmF32, 5).addLocals(kWasmF64, 3)
.addBody([
kExprBlock, kWasmF64,
kExprF64Const, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3f,

View File

@ -6,7 +6,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addFunction(undefined, kSig_i_i)
.addLocals({i32_count: 7})
.addLocals(kWasmI32, 7)
.addBody([
kExprI32Const, 0,
kExprIf, kWasmI32, // @11 i32

View File

@ -6,7 +6,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addFunction(undefined, kSig_v_v)
.addLocals({i32_count: 1}).addLocals({f32_count: 1}).addLocals({f64_count: 1})
.addLocals(kWasmI32, 1).addLocals(kWasmF32, 1).addLocals(kWasmF64, 1)
.addBody([
kExprLocalGet, 1,
kExprLocalGet, 2,

View File

@ -6,7 +6,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
builder.addFunction(undefined, kSig_i_i)
.addLocals({i32_count: 5})
.addLocals(kWasmI32, 5)
.addBody([
kExprLocalGet, 0, // --> 1
kExprIf, kWasmI32,

View File

@ -9,7 +9,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
(function TestTruncatedBrOnExnInLoop() {
let builder = new WasmModuleBuilder();
let fun = builder.addFunction(undefined, kSig_v_v)
.addLocals({except_count: 1})
.addLocals(kWasmExnRef, 1)
.addBody([
kExprLoop, kWasmStmt,
kExprLocalGet, 0,

View File

@ -7,7 +7,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
const sig = builder.addType(makeSig([kWasmI32], []));
builder.addFunction(undefined, sig)
.addLocals({i64_count: 1})
.addLocals(kWasmI64, 1)
.addBody([
kExprLoop, kWasmI32,
kExprLocalGet, 1,

View File

@ -7,7 +7,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
const sig = builder.addType(makeSig([kWasmI64], [kWasmI64]));
builder.addFunction(undefined, sig)
.addLocals({i32_count: 14}).addLocals({i64_count: 17}).addLocals({f32_count: 14})
.addLocals(kWasmI32, 14).addLocals(kWasmI64, 17).addLocals(kWasmF32, 14)
.addBody([
kExprBlock, kWasmStmt,
kExprBr, 0x00,

View File

@ -48,7 +48,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
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({anyfunc_count: 10})
.addLocals(kWasmAnyFunc, 10)
.addBody([
kExprLocalGet, 0,
kExprLocalSet, 1, // Set local
@ -139,7 +139,7 @@ load('test/mjsunit/wasm/wasm-module-builder.js');
const builder = new WasmModuleBuilder();
const sig_index = builder.addType(kSig_a_v);
builder.addFunction('main', sig_index)
.addLocals({anyfunc_count: 1})
.addLocals(kWasmAnyFunc, 1)
.addBody([kExprLocalGet, 0])
.exportFunc();

View File

@ -437,7 +437,7 @@ function CmpExchgLoop(opcode, alignment) {
let builder = new WasmModuleBuilder();
builder.addImportedMemory("m", "imported_mem", 0, 2, "shared");
builder.addFunction("main", makeSig([kWasmI32], []))
.addLocals({i64_count: 2})
.addLocals(kWasmI64, 2)
.addBody([
kExprLoop, kWasmStmt,
kExprLocalGet, 0,

View File

@ -126,9 +126,7 @@ function makeWorkerCodeForOpcode(compareExchangeOpcode, size, functionName,
builder.addFunction(functionName, makeSig([kWasmI32, kWasmI32, kWasmI32,
kWasmI32, kWasmI32
], []))
.addLocals({
i32_count: 3
})
.addLocals(kWasmI32, 3)
.addBody(body)
.exportAs(functionName);
}
@ -147,8 +145,8 @@ function spawnWorker(module, memory, address, sequence) {
`onmessage = function(msg) {
this.instance = new WebAssembly.Instance(msg.module,
{m: {imported_mem: msg.memory}});
instance.exports.worker(msg.address, msg.sequence, msg.sequenceLength, msg.workerId,
msg.bitMask);
instance.exports.worker(msg.address, msg.sequence,
msg.sequenceLength, msg.workerId, msg.bitMask);
postMessage({workerId: msg.workerId});
}`,
{type: 'string'}

View File

@ -131,9 +131,7 @@ function makeWorkerCodeForOpcode(compareExchangeOpcode, size, functionName,
builder.addFunction(functionName, makeSig([kWasmI32, kWasmI32, kWasmI32,
kWasmI32, kWasmI32
], []))
.addLocals({
i32_count: 1, i64_count: 2
})
.addLocals(kWasmI32, 1).addLocals(kWasmI64, 2)
.addBody(body)
.exportAs(functionName);
}

View File

@ -105,7 +105,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_a);
builder.addFunction("throw_catch_local", kSig_a_v)
.addLocals({anyfunc_count: 1})
.addLocals(kWasmAnyFunc, 1)
.addBody([
kExprTry, kWasmAnyFunc,
kExprLocalGet, 0,

View File

@ -21,7 +21,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
kExprEnd,
]).exportFunc();
builder.addFunction("rethrow1", kSig_i_i)
.addLocals({except_count: 1})
.addLocals(kWasmExnRef, 1)
.addBody([
kExprTry, kWasmI32,
kExprThrow, except,
@ -51,7 +51,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
let except1 = builder.addException(kSig_v_v);
let except2 = builder.addException(kSig_v_v);
builder.addFunction("rethrow_nested", kSig_i_i)
.addLocals({except_count: 2})
.addLocals(kWasmExnRef, 2)
.addBody([
kExprTry, kWasmI32,
kExprThrow, except2,
@ -93,7 +93,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_v);
builder.addFunction("rethrow_recatch", kSig_i_i)
.addLocals({except_count: 1})
.addLocals(kWasmExnRef, 1)
.addBody([
kExprTry, kWasmI32,
kExprThrow, except,

View File

@ -13,7 +13,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
var kSig_v_s = makeSig([kWasmS128], []);
var except = builder.addException(kSig_v_s);
builder.addFunction("throw_simd", kSig_v_v)
.addLocals({s128_count: 1})
.addLocals(kWasmS128, 1)
.addBody([
kExprLocalGet, 0,
kExprThrow, 0,
@ -31,7 +31,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
var kSig_v_s = makeSig([kWasmS128], []);
var except = builder.addException(kSig_v_s);
builder.addFunction("throw_catch_simd", kSig_i_v)
.addLocals({s128_count: 1})
.addLocals(kWasmS128, 1)
.addBody([
kExprTry, kWasmS128,
kExprLocalGet, 0,

View File

@ -12,7 +12,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction("push_and_drop_exnref", kSig_v_v)
.addLocals({except_count: 1})
.addLocals(kWasmExnRef, 1)
.addBody([
kExprLocalGet, 0,
kExprDrop,
@ -343,7 +343,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_v);
builder.addFunction("catch_complex", kSig_i_i)
.addLocals({except_count: 1})
.addLocals(kWasmExnRef, 1)
.addBody([
kExprBlock, kWasmI32,
kExprTry, kWasmStmt,
@ -467,7 +467,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
let builder = new WasmModuleBuilder();
let except = builder.addException(kSig_v_l);
builder.addFunction("throw_catch_param", kSig_i_i)
.addLocals({i64_count: 1})
.addLocals(kWasmI64, 1)
.addBody([
kExprLocalGet, 0,
kExprI64UConvertI32,
@ -661,7 +661,7 @@ load("test/mjsunit/wasm/exceptions-utils.js");
.exportFunc();
builder.addFunction("same_scope_multiple", kSig_i_i)
.addLocals({i32_count: 1, except_count: 1})
.addLocals(kWasmI32, 1).addLocals(kWasmExnRef, 1)
// path = 0;
//
// try {

View File

@ -53,7 +53,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
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({externref_count: 10})
.addLocals(kWasmExternRef, 10)
.addBody([
kExprLocalGet, 0, kExprLocalSet, 1, // Set local
kExprLocalGet, 0, kExprLocalSet, 2, // Set local
@ -209,7 +209,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
const builder = new WasmModuleBuilder();
builder.addFunction('main', kSig_r_v)
.addBody([kExprLocalGet, 0])
.addLocals({externref_count: 1})
.addLocals(kWasmExternRef, 1)
.exportFunc();
const instance = builder.instantiate();

View File

@ -54,7 +54,7 @@ function WasmI64AtomicWait(memory, offset, index, val_low,
// I64 for the instruction parameter.
builder.addFunction("main",
makeSig([kWasmI32, kWasmI32, kWasmI32, kWasmF64], [kWasmI32]))
.addLocals({i64_count: 1}) // local that is passed as value param to wait
.addLocals(kWasmI64, 1) // local that is passed as value param to wait
.addBody([
kExprLocalGet, 1,
kExprI64UConvertI32,

View File

@ -17,7 +17,7 @@ builder.addImportedMemory('m', 'imported_mem', 1, 2);
builder.addType(makeSig(new Array(18).fill(kWasmS128), []));
builder.addFunction(undefined, makeSig([], []))
.addLocals({s128_count: 9})
.addLocals(kWasmS128, 9)
.addBodyWithEnd([
// These will all be args to the callee.
// Load first arg from memory, this was written with values from JS.

View File

@ -33,7 +33,7 @@ load("test/mjsunit/wasm/wasm-module-builder.js");
// For each v128 on the stack, we return the first and last lane. This help
// catch bugs with reading/writing the wrong stack slots.
builder.addFunction("main", sig_iiiiiiiiii_v)
.addLocals({"i32_count": 10, "s128_count": 1})
.addLocals(kWasmI32, 10).addLocals(kWasmS128, 1)
.addBody([
kExprCallFunction, callee.index,

View File

@ -43,7 +43,7 @@ function instantiate(buffer, ffi) {
print(arguments.callee.name);
let builder = new WasmModuleBuilder();
builder.addFunction(undefined, kSig_i_i)
.addLocals({i32_count: 1})
.addLocals(kWasmI32, 1)
.addBody([kExprLocalGet, 0, kExprLocalSet, 1, kExprLocalGet, 1])
.exportAs('main');
@ -57,16 +57,15 @@ function instantiate(buffer, ffi) {
print(arguments.callee.name);
// TODO(titzer): i64 only works on 64-bit platforms.
var types = [
{locals: {i32_count: 1}, type: kWasmI32},
// {locals: {i64_count: 1}, type: kWasmI64},
{locals: {f32_count: 1}, type: kWasmF32},
{locals: {f64_count: 1}, type: kWasmF64},
{count: 1, type: kWasmI32},
{count: 1, type: kWasmF32},
{count: 1, type: kWasmF64},
];
for (p of types) {
let builder = new WasmModuleBuilder();
builder.addFunction(undefined, makeSig_r_x(p.type, p.type))
.addLocals(p.locals)
.addLocals(p.type, p.count)
.addBody([kExprLocalGet, 0, kExprLocalSet, 1, kExprLocalGet, 1])
.exportAs('main');

View File

@ -102,6 +102,9 @@ let kWasmS128 = 0x7b;
let kWasmExternRef = 0x6f;
let kWasmAnyFunc = 0x70;
let kWasmExnRef = 0x68;
function wasmRefType(index) { return {opcode: 0x6b, index: index}; }
function wasmOptRefType(index) { return {opcode: 0x6c, index: index}; }
function wasmRtt(index, depth) { return {opcode: 0x69, index: index, depth: depth}; }
let kExternalFunction = 0;
let kExternalTable = 1;
@ -781,6 +784,15 @@ class Binary {
}
}
emit_type(type) {
if ((typeof type) == "number") this.emit_u8(type);
else {
this.emit_u8(type.opcode);
if ('depth' in type) this.emit_u8(type.depth);
this.emit_u32v(type.index);
}
}
emit_header() {
this.emit_bytes([
kWasmH0, kWasmH1, kWasmH2, kWasmH3, kWasmV0, kWasmV1, kWasmV2, kWasmV3
@ -802,20 +814,22 @@ class Binary {
}
class WasmFunctionBuilder {
constructor(module, name, type_index) {
// Encoding of local names: a string corresponds to a local name,
// a number n corresponds to n undefined names.
constructor(module, name, type_index, arg_names) {
this.module = module;
this.name = name;
this.type_index = type_index;
this.body = [];
this.locals = [];
this.local_names = [];
this.local_names = arg_names;
this.body_offset = undefined; // Not valid until module is serialized.
}
numLocalNames() {
let num_local_names = 0;
for (let loc_name of this.local_names) {
if (loc_name !== undefined) ++num_local_names;
if (typeof loc_name == "string") ++num_local_names;
}
return num_local_names;
}
@ -854,20 +868,17 @@ class WasmFunctionBuilder {
getNumLocals() {
let total_locals = 0;
for (let l of this.locals) {
for (let type of ["i32", "i64", "f32", "f64", "s128"]) {
total_locals += l[type + "_count"] || 0;
}
total_locals += l.count
}
return total_locals;
}
addLocals(locals, names) {
const old_num_locals = this.getNumLocals();
this.locals.push(locals);
if (names) {
const missing_names = old_num_locals - this.local_names.length;
this.local_names.push(...new Array(missing_names), ...names);
}
addLocals(type, count, names) {
this.locals.push({type: type, count: count});
names = names || [];
if (names.length > count) throw new Error('too many locals names given');
this.local_names.push(...names);
if (count > names.length) this.local_names.push(count - names.length);
return this;
}
@ -972,17 +983,17 @@ class WasmModuleBuilder {
return this.types.length - 1;
}
addGlobal(local_type, mutable) {
let glob = new WasmGlobalBuilder(this, local_type, mutable);
addGlobal(type, mutable) {
let glob = new WasmGlobalBuilder(this, type, mutable);
glob.index = this.globals.length + this.num_imported_globals;
this.globals.push(glob);
return glob;
}
addTable(type, initial_size, max_size = undefined) {
if (type != kWasmExternRef && type != kWasmAnyFunc && type != kWasmExnRef) {
throw new Error(
'Tables must be of type kWasmExternRef, kWasmAnyFunc or kWasmExnRef');
if (type == kWasmI32 || type == kWasmI64 || type == kWasmF32 ||
type == kWasmF64 || type == kWasmS128 || type == kWasmStmt) {
throw new Error('Tables must be of a reference type');
}
let table = new WasmTableBuilder(this, type, initial_size, max_size);
table.index = this.tables.length + this.num_imported_tables;
@ -997,9 +1008,13 @@ class WasmModuleBuilder {
return except_index;
}
addFunction(name, type) {
addFunction(name, type, arg_names) {
arg_names = arg_names || [];
let type_index = (typeof type) == "number" ? type : this.addType(type);
let func = new WasmFunctionBuilder(this, name, type_index);
let num_args = this.types[type_index].params.length;
if (num_args < arg_names.length) throw new Error("too many arg names provided");
if (num_args > arg_names.length) arg_names.push(num_args - arg_names.length);
let func = new WasmFunctionBuilder(this, name, type_index, arg_names);
func.index = this.functions.length + this.num_imported_funcs;
this.functions.push(func);
return func;
@ -1011,7 +1026,7 @@ class WasmModuleBuilder {
}
let type_index = (typeof type) == "number" ? type : this.addType(type);
this.imports.push({module: module, name: name, kind: kExternalFunction,
type: type_index});
type_index: type_index});
return this.num_imported_funcs++;
}
@ -1047,7 +1062,7 @@ class WasmModuleBuilder {
throw new Error('Imported exceptions must be declared before local ones');
}
let type_index = (typeof type) == "number" ? type : this.addType(type);
let o = {module: module, name: name, kind: kExternalException, type: type_index};
let o = {module: module, name: name, kind: kExternalException, type_index: type_index};
this.imports.push(o);
return this.num_imported_exceptions++;
}
@ -1155,11 +1170,11 @@ class WasmModuleBuilder {
section.emit_u8(kWasmFunctionTypeForm);
section.emit_u32v(type.params.length);
for (let param of type.params) {
section.emit_u8(param);
section.emit_type(param);
}
section.emit_u32v(type.results.length);
for (let result of type.results) {
section.emit_u8(result);
section.emit_type(result);
}
}
});
@ -1175,9 +1190,9 @@ class WasmModuleBuilder {
section.emit_string(imp.name || '');
section.emit_u8(imp.kind);
if (imp.kind == kExternalFunction) {
section.emit_u32v(imp.type);
section.emit_u32v(imp.type_index);
} else if (imp.kind == kExternalGlobal) {
section.emit_u32v(imp.type);
section.emit_type(imp.type);
section.emit_u8(imp.mutable);
} else if (imp.kind == kExternalMemory) {
var has_max = (typeof imp.maximum) != "undefined";
@ -1190,14 +1205,14 @@ class WasmModuleBuilder {
section.emit_u32v(imp.initial); // initial
if (has_max) section.emit_u32v(imp.maximum); // maximum
} else if (imp.kind == kExternalTable) {
section.emit_u8(imp.type);
section.emit_type(imp.type);
var has_max = (typeof imp.maximum) != "undefined";
section.emit_u8(has_max ? 1 : 0); // flags
section.emit_u32v(imp.initial); // initial
if (has_max) section.emit_u32v(imp.maximum); // maximum
} else if (imp.kind == kExternalException) {
section.emit_u32v(kExceptionAttribute);
section.emit_u32v(imp.type);
section.emit_u32v(imp.type_index);
} else {
throw new Error("unknown/unsupported import kind " + imp.kind);
}
@ -1222,7 +1237,7 @@ class WasmModuleBuilder {
binary.emit_section(kTableSectionCode, section => {
section.emit_u32v(wasm.tables.length);
for (let table of wasm.tables) {
section.emit_u8(table.type);
section.emit_type(table.type);
section.emit_u8(table.has_max);
section.emit_u32v(table.initial_size);
if (table.has_max) section.emit_u32v(table.max_size);
@ -1253,9 +1268,9 @@ class WasmModuleBuilder {
if (debug) print("emitting events @ " + binary.length);
binary.emit_section(kExceptionSectionCode, section => {
section.emit_u32v(wasm.exceptions.length);
for (let type of wasm.exceptions) {
for (let type_index of wasm.exceptions) {
section.emit_u32v(kExceptionAttribute);
section.emit_u32v(type);
section.emit_u32v(type_index);
}
});
}
@ -1266,7 +1281,7 @@ class WasmModuleBuilder {
binary.emit_section(kGlobalSectionCode, section => {
section.emit_u32v(wasm.globals.length);
for (let global of wasm.globals) {
section.emit_u8(global.type);
section.emit_type(global.type);
section.emit_u8(global.mutable);
if ((typeof global.init_index) == "undefined") {
// Emit a constant initializer.
@ -1306,6 +1321,15 @@ class WasmModuleBuilder {
section.emit_u8(kExprRefNull);
section.emit_u8(kWasmExnRef);
break;
default:
if (global.function_index !== undefined) {
section.emit_u8(kExprRefFunc);
section.emit_u32v(global.function_index);
} else {
section.emit_u8(kExprRefNull);
section.emit_u32v(global.type.index);
}
break;
}
} else {
// Emit a global-index initializer.
@ -1459,40 +1483,12 @@ class WasmModuleBuilder {
for (let func of wasm.functions) {
header.reset();
// Function body length will be patched later.
let local_decls = [];
for (let l of func.locals || []) {
if (l.i32_count > 0) {
local_decls.push({count: l.i32_count, type: kWasmI32});
}
if (l.i64_count > 0) {
local_decls.push({count: l.i64_count, type: kWasmI64});
}
if (l.f32_count > 0) {
local_decls.push({count: l.f32_count, type: kWasmF32});
}
if (l.f64_count > 0) {
local_decls.push({count: l.f64_count, type: kWasmF64});
}
if (l.s128_count > 0) {
local_decls.push({count: l.s128_count, type: kWasmS128});
}
if (l.externref_count > 0) {
local_decls.push({count: l.externref_count, type: kWasmExternRef});
}
if (l.anyfunc_count > 0) {
local_decls.push({count: l.anyfunc_count, type: kWasmAnyFunc});
}
if (l.except_count > 0) {
local_decls.push({count: l.except_count, type: kWasmExnRef});
}
}
let local_decls = func.locals || [];
header.emit_u32v(local_decls.length);
for (let decl of local_decls) {
header.emit_u32v(decl.count);
header.emit_u8(decl.type);
header.emit_type(decl.type);
}
section.emit_u32v(header.length + func.body.length);
section.emit_bytes(header.trunc_buffer());
// Set to section offset for now, will update.
@ -1576,10 +1572,15 @@ class WasmModuleBuilder {
if (func.numLocalNames() == 0) continue;
name_section.emit_u32v(func.index);
name_section.emit_u32v(func.numLocalNames());
let name_index = 0;
for (let i = 0; i < func.local_names.length; ++i) {
if (func.local_names[i] === undefined) continue;
name_section.emit_u32v(i);
name_section.emit_string(func.local_names[i]);
if (typeof func.local_names[i] == "string") {
name_section.emit_u32v(name_index);
name_section.emit_string(func.local_names[i]);
name_index++;
} else {
name_index += func.local_names[i];
}
}
}
});