summaryrefslogtreecommitdiff
path: root/deps/v8/test/mjsunit/wasm/wasm-module-builder.js
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/mjsunit/wasm/wasm-module-builder.js')
-rw-r--r--deps/v8/test/mjsunit/wasm/wasm-module-builder.js159
1 files changed, 101 insertions, 58 deletions
diff --git a/deps/v8/test/mjsunit/wasm/wasm-module-builder.js b/deps/v8/test/mjsunit/wasm/wasm-module-builder.js
index 9670f72031..5a19284c70 100644
--- a/deps/v8/test/mjsunit/wasm/wasm-module-builder.js
+++ b/deps/v8/test/mjsunit/wasm/wasm-module-builder.js
@@ -80,6 +80,7 @@ let kWasmFunctionTypeForm = 0x60;
let kWasmStructTypeForm = 0x5f;
let kWasmArrayTypeForm = 0x5e;
let kWasmSubtypeForm = 0x50;
+let kWasmSubtypeFinalForm = 0x4e;
let kWasmRecursiveTypeGroupForm = 0x4f;
let kNoSuperType = 0xFFFFFFFF;
@@ -195,6 +196,7 @@ let kSig_v_i = makeSig([kWasmI32], []);
let kSig_v_ii = makeSig([kWasmI32, kWasmI32], []);
let kSig_v_iii = makeSig([kWasmI32, kWasmI32, kWasmI32], []);
let kSig_v_l = makeSig([kWasmI64], []);
+let kSig_v_li = makeSig([kWasmI64, kWasmI32], []);
let kSig_v_d = makeSig([kWasmF64], []);
let kSig_v_dd = makeSig([kWasmF64, kWasmF64], []);
let kSig_v_ddi = makeSig([kWasmF64, kWasmF64, kWasmI32], []);
@@ -498,7 +500,6 @@ let kExprArrayGet = 0x13;
let kExprArrayGetS = 0x14;
let kExprArrayGetU = 0x15;
let kExprArraySet = 0x16;
-let kExprArrayLenDeprecated = 0x17;
let kExprArrayCopy = 0x18;
let kExprArrayLen = 0x19;
let kExprArrayNewFixed = 0x1a;
@@ -506,6 +507,7 @@ let kExprArrayNew = 0x1b;
let kExprArrayNewDefault = 0x1c;
let kExprArrayNewData = 0x1d;
let kExprArrayNewElem = 0x1f;
+let kExprArrayFill = 0x0f;
let kExprI31New = 0x20;
let kExprI31GetS = 0x21;
let kExprI31GetU = 0x22;
@@ -515,8 +517,11 @@ let kExprRefTestDeprecated = 0x44;
let kExprRefCast = 0x41;
let kExprRefCastNull = 0x49;
let kExprRefCastDeprecated = 0x45;
-let kExprBrOnCast = 0x46;
-let kExprBrOnCastFail = 0x47;
+let kExprBrOnCast = 0x42;
+let kExprBrOnCastNull = 0x4a;
+let kExprBrOnCastDeprecated = 0x46;
+let kExprBrOnCastFail = 0x43;
+let kExprBrOnCastFailNull = 0x4b;
let kExprRefCastNop = 0x4c;
let kExprRefIsData = 0x51;
let kExprRefIsI31 = 0x52;
@@ -547,6 +552,7 @@ let kExprStringNewLossyUtf8 = 0x8b;
let kExprStringNewWtf8 = 0x8c;
let kExprStringEncodeLossyUtf8 = 0x8d;
let kExprStringEncodeWtf8 = 0x8e;
+let kExprStringNewUtf8Try = 0x8f;
let kExprStringAsWtf8 = 0x90;
let kExprStringViewWtf8Advance = 0x91;
let kExprStringViewWtf8EncodeUtf8 = 0x92;
@@ -563,6 +569,9 @@ let kExprStringViewIterNext = 0xa1
let kExprStringViewIterAdvance = 0xa2;
let kExprStringViewIterRewind = 0xa3
let kExprStringViewIterSlice = 0xa4;
+let kExprStringCompare = 0xa8;
+let kExprStringFromCodePoint = 0xa9;
+let kExprStringHash = 0xaa;
let kExprStringNewUtf8Array = 0xb0;
let kExprStringNewWtf16Array = 0xb1;
let kExprStringEncodeUtf8Array = 0xb2;
@@ -571,6 +580,7 @@ let kExprStringNewLossyUtf8Array = 0xb4;
let kExprStringNewWtf8Array = 0xb5;
let kExprStringEncodeLossyUtf8Array = 0xb6;
let kExprStringEncodeWtf8Array = 0xb7;
+let kExprStringNewUtf8ArrayTry = 0xb8;
// Numeric opcodes.
let kExprI32SConvertSatF32 = 0x00;
@@ -1121,9 +1131,8 @@ class WasmFunctionBuilder {
addBody(body) {
checkExpr(body);
- this.body = body.slice();
- // Automatically add the end for the function block to the body.
- this.body.push(kExprEnd);
+ // Store a copy of the body, and automatically add the end opcode.
+ this.body = body.concat([kExprEnd]);
return this;
}
@@ -1205,21 +1214,23 @@ function makeField(type, mutability) {
}
class WasmStruct {
- constructor(fields, supertype_idx) {
+ constructor(fields, is_final, supertype_idx) {
if (!Array.isArray(fields)) {
throw new Error('struct fields must be an array');
}
this.fields = fields;
this.type_form = kWasmStructTypeForm;
+ this.is_final = is_final;
this.supertype = supertype_idx;
}
}
class WasmArray {
- constructor(type, mutability, supertype_idx) {
+ constructor(type, mutability, is_final, supertype_idx) {
this.type = type;
this.mutability = mutability;
this.type_form = kWasmArrayTypeForm;
+ this.is_final = is_final;
this.supertype = supertype_idx;
}
}
@@ -1273,16 +1284,11 @@ class WasmModuleBuilder {
this.element_segments = [];
this.data_segments = [];
this.explicit = [];
+ this.rec_groups = [];
this.num_imported_funcs = 0;
this.num_imported_globals = 0;
this.num_imported_tables = 0;
this.num_imported_tags = 0;
- // If a wasm-gc type is detected, all types are put by default into a single
- // recursive group. This field overrides this behavior and puts each type in
- // a separate rec. group instead.
- // TODO(7748): Support more flexible rec. groups.
- this.singleton_rec_groups = false;
- this.early_data_count_section = false;
return this;
}
@@ -1341,13 +1347,14 @@ class WasmModuleBuilder {
this.explicit.push(this.createCustomSection(name, bytes));
}
- // TODO(7748): Support recursive groups.
-
- addType(type, supertype_idx = kNoSuperType) {
+ // We use {is_final = true} so that the MVP syntax is generated for
+ // signatures.
+ addType(type, supertype_idx = kNoSuperType, is_final = true) {
var pl = type.params.length; // should have params
var rl = type.results.length; // should have results
- type.supertype = supertype_idx;
- this.types.push(type);
+ var type_copy = {params: type.params, results: type.results,
+ is_final: is_final, supertype: supertype_idx};
+ this.types.push(type_copy);
return this.types.length - 1;
}
@@ -1356,13 +1363,13 @@ class WasmModuleBuilder {
return this.stringrefs.length - 1;
}
- addStruct(fields, supertype_idx = kNoSuperType) {
- this.types.push(new WasmStruct(fields, supertype_idx));
+ addStruct(fields, supertype_idx = kNoSuperType, is_final = false) {
+ this.types.push(new WasmStruct(fields, is_final, supertype_idx));
return this.types.length - 1;
}
- addArray(type, mutability, supertype_idx = kNoSuperType) {
- this.types.push(new WasmArray(type, mutability, supertype_idx));
+ addArray(type, mutability, supertype_idx = kNoSuperType, is_final = false) {
+ this.types.push(new WasmArray(type, mutability, is_final, supertype_idx));
return this.types.length - 1;
}
@@ -1609,12 +1616,19 @@ class WasmModuleBuilder {
return this;
}
- setSingletonRecGroups() {
- this.singleton_rec_groups = true;
+ startRecGroup() {
+ this.rec_groups.push({start: this.types.length, size: 0});
}
- setEarlyDataCountSection() {
- this.early_data_count_section = true;
+ endRecGroup() {
+ if (this.rec_groups.length == 0) {
+ throw new Error("Did not start a recursive group before ending one")
+ }
+ let last_element = this.rec_groups[this.rec_groups.length - 1]
+ if (last_element.size != 0) {
+ throw new Error("Did not start a recursive group before ending one")
+ }
+ last_element.size = this.types.length - last_element.start;
}
setName(name) {
@@ -1633,21 +1647,31 @@ class WasmModuleBuilder {
if (wasm.types.length > 0) {
if (debug) print('emitting types @ ' + binary.length);
binary.emit_section(kTypeSectionCode, section => {
- // If any type is a wasm-gc type, wrap everything in a recursive group.
- // TODO(7748): Support more flexible rec. groups.
- if (!this.singleton_rec_groups &&
- wasm.types.findIndex(type => type instanceof WasmStruct ||
- type instanceof WasmArray) >= 0) {
- section.emit_u32v(1);
- section.emit_u8(kWasmRecursiveTypeGroupForm);
+ let length_with_groups = wasm.types.length;
+ for (let group of wasm.rec_groups) {
+ length_with_groups -= group.size - 1;
}
- section.emit_u32v(wasm.types.length);
+ section.emit_u32v(length_with_groups);
+
+ let rec_group_index = 0;
- for (let type of wasm.types) {
+ for (let i = 0; i < wasm.types.length; i++) {
+ if (rec_group_index < wasm.rec_groups.length &&
+ wasm.rec_groups[rec_group_index].start == i) {
+ section.emit_u8(kWasmRecursiveTypeGroupForm);
+ section.emit_u32v(wasm.rec_groups[rec_group_index].size);
+ rec_group_index++;
+ }
+
+ let type = wasm.types[i];
if (type.supertype != kNoSuperType) {
- section.emit_u8(kWasmSubtypeForm);
+ section.emit_u8(type.is_final ? kWasmSubtypeFinalForm
+ : kWasmSubtypeForm);
section.emit_u8(1); // supertype count
section.emit_u32v(type.supertype);
+ } else if (!type.is_final) {
+ section.emit_u8(kWasmSubtypeForm);
+ section.emit_u8(0); // no supertypes
}
if (type instanceof WasmStruct) {
section.emit_u8(kWasmStructTypeForm);
@@ -1727,14 +1751,6 @@ class WasmModuleBuilder {
});
}
- // If there are any passive data segments, add the DataCount section.
- if (this.early_data_count_section &&
- wasm.data_segments.some(seg => !seg.is_active)) {
- binary.emit_section(kDataCountSectionCode, section => {
- section.emit_u32v(wasm.data_segments.length);
- });
- }
-
// Add table section
if (wasm.tables.length > 0) {
if (debug) print('emitting tables @ ' + binary.length);
@@ -1900,8 +1916,7 @@ class WasmModuleBuilder {
}
// If there are any passive data segments, add the DataCount section.
- if (!this.early_data_count_section &&
- wasm.data_segments.some(seg => !seg.is_active)) {
+ if (wasm.data_segments.some(seg => !seg.is_active)) {
binary.emit_section(kDataCountSectionCode, section => {
section.emit_u32v(wasm.data_segments.length);
});
@@ -1948,18 +1963,24 @@ class WasmModuleBuilder {
let section_length = 0;
binary.emit_section(kCodeSectionCode, section => {
section.emit_u32v(wasm.functions.length);
- let header = new Binary;
+ let header;
for (let func of wasm.functions) {
- header.reset();
- // Function body length will be patched later.
- let local_decls = func.locals || [];
- header.emit_u32v(local_decls.length);
- for (let decl of local_decls) {
- header.emit_u32v(decl.count);
- header.emit_type(decl.type);
+ if (func.locals.length == 0) {
+ // Fast path for functions without locals.
+ section.emit_u32v(func.body.length + 1);
+ section.emit_u8(0); // 0 locals.
+ } else {
+ // Build the locals declarations in separate buffer first.
+ if (!header) header = new Binary;
+ header.reset();
+ header.emit_u32v(func.locals.length);
+ for (let decl of func.locals) {
+ header.emit_u32v(decl.count);
+ header.emit_type(decl.type);
+ }
+ section.emit_u32v(header.length + func.body.length);
+ section.emit_bytes(header.trunc_buffer());
}
- section.emit_u32v(header.length + func.body.length);
- section.emit_bytes(header.trunc_buffer());
// Set to section offset for now, will update.
func.body_offset = section.length;
section.emit_bytes(func.body);
@@ -2095,6 +2116,28 @@ function wasmSignedLeb(val, max_len = 5) {
'Leb value <' + val + '> exceeds maximum length of ' + max_len);
}
+function wasmSignedLeb64(val, max_len) {
+ if (typeof val != "bigint") {
+ if (val < Math.pow(2, 31)) {
+ return wasmSignedLeb(val, max_len);
+ }
+ val = BigInt(val);
+ }
+ let res = [];
+ for (let i = 0; i < max_len; ++i) {
+ let v = val & 0x7fn;
+ // If {v} sign-extended from 7 to 32 bits is equal to val, we are done.
+ if (((v << 25n) >> 25n) == val) {
+ res.push(Number(v));
+ return res;
+ }
+ res.push(Number(v) | 0x80);
+ val = val >> 7n;
+ }
+ throw new Error(
+ 'Leb value <' + val + '> exceeds maximum length of ' + max_len);
+}
+
function wasmUnsignedLeb(val, max_len = 5) {
let res = [];
for (let i = 0; i < max_len; ++i) {
@@ -2117,7 +2160,7 @@ function wasmI32Const(val) {
// Note: Since {val} is a JS number, the generated constant only has 53 bits of
// precision.
function wasmI64Const(val) {
- return [kExprI64Const, ...wasmSignedLeb(val, 10)];
+ return [kExprI64Const, ...wasmSignedLeb64(val, 10)];
}
function wasmF32Const(f) {