COMMIT_MESSAGE

 1WebAssembly JS API: implement more sections
 2
 3On the JSC side:
 4
 5 - Put in parser stubs for all WebAssembly sections.
 6 - Parse Import, Export sections.
 7 - Use tryReserveCapacity instead of reserve, and bail out of the parser if it fails. This prevents the parser from bringing everything down when faced with a malicious input.
 8 - Encapsulate all parsed module information into its own structure, making it easier to pass around (from parser to Plan to Module to Instance).
 9 - Create WasmFormat.cpp to hold parsed module information's dtor to avoid including WasmMemory.h needlessly.
 10 - Remove all remainders of polyfill-prototype-1, and update license.
 11 - Add missing WasmOps.h and WasmValidateInlines.h auto-generation for cmake build.
 12
 13On the Builder.js testing side:
 14
 15 - Implement Type, Import (function only), Export (function only) sections.
 16 - Check section order and uniqueness.
 17 - Optionally auto-generate the Type section from subsequent Export / Import / Code entries.
 18 - Allow re-exporting an import.

JSTests/ChangeLog

 12016-11-02 JF Bastien <jfbastien@apple.com>
 2
 3 WebAssembly JS API: implement more sections
 4
 5 On the JSC side:
 6
 7 - Put in parser stubs for all WebAssembly sections.
 8 - Parse Import, Export sections.
 9 - Use tryReserveCapacity instead of reserve, and bail out of the parser if it fails. This prevents the parser from bringing everything down when faced with a malicious input.
 10 - Encapsulate all parsed module information into its own structure, making it easier to pass around (from parser to Plan to Module to Instance).
 11 - Create WasmFormat.cpp to hold parsed module information's dtor to avoid including WasmMemory.h needlessly.
 12 - parseCode: avoid overflow through function size.
 13 - Remove all remainders of polyfill-prototype-1, and update license.
 14 - Add missing WasmOps.h and WasmValidateInlines.h auto-generation for cmake build.
 15
 16 On the Builder.js testing side:
 17
 18 - Implement Type, Import (function only), Export (function only) sections.
 19 - Check section order and uniqueness.
 20 - Optionally auto-generate the Type section from subsequent Export / Import / Code entries.
 21 - Allow re-exporting an import.
 22
 23 WebAssembly JS API: Module should decode strings
 24 https://bugs.webkit.org/show_bug.cgi?id=164023
 25
 26 Reviewed by NOBODY (OOPS!).
 27
 28 * wasm/Builder.js: build type, import, and export sections
 29 (const._normalizeFunctionSignature):
 30 * wasm/Builder_WebAssemblyBinary.js: Added. Forked from Builder.js
 31 (const.emitters.Type):
 32 (const.emitters.Import):
 33 (const.emitters.Function):
 34 (const.emitters.Table):
 35 (const.emitters.Memory):
 36 (const.emitters.Global):
 37 (const.emitters.Export):
 38 (const.emitters.Start):
 39 (const.emitters.Element):
 40 (const.emitters.Code):
 41 (const.emitters.Data):
 42 (export.const.Binary):
 43 * wasm/LowLevelBinary.js: Add a few useful outputs
 44 (export.default.LowLevelBinary.prototype.varuint1):
 45 (export.default.LowLevelBinary.prototype.varint7):
 46 * wasm/WASM.js: value type and external kind helpers
 47 * wasm/assert.js: array element-wise equality comparison
 48 (const._eq):
 49 * wasm/js-api/test_Module.js:
 50 (ModuleWithImports):
 51 * wasm/self-test/test_BuilderJSON.js: many more tests for all the new Builder APIs, and update to some older tests which now require a Type section or rejiggered Function signature
 52 (const.assertOpThrows):
 53 (SectionsWithSameCustomName):
 54 (TwoTypeSections):
 55 (EmptyImportSection):
 56 (ImportBeforeTypeSections):
 57 * wasm/self-test/test_BuilderWebAssembly.js: remove a test which wasn't helpful and is now obsolete
 58 (CustomSection):
 59
1602016-11-01 Saam Barati <sbarati@apple.com>
261
362 We should be able to eliminate rest parameter allocations

JSTests/wasm/Builder.js

2323 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424 */
2525
26 import LowLevelBinary from 'LowLevelBinary.js';
 26import * as BuildWebAssembly from 'Builder_WebAssemblyBinary.js';
2727import * as WASM from 'WASM.js';
2828
2929const _toJavaScriptName = name => {

@@const _isValidValue = (value, type) => {
4343};
4444const _unknownSectionId = 0;
4545
46 const _BuildWebAssemblyBinary = (preamble, sections) => {
47  let wasmBin = new LowLevelBinary();
48  const put = (bin, type, value) => bin[type](value);
49  for (const p of WASM.description.preamble)
50  put(wasmBin, p.type, preamble[p.name]);
51  for (const section of sections) {
52  put(wasmBin, WASM.sectionEncodingType, section.id);
53  let sectionBin = wasmBin.newPatchable("varuint");
54  switch (section.name) {
55  case "Type": throw new Error(`Unimplemented: section type "${section.name}"`);
56  case "Import": throw new Error(`Unimplemented: section type "${section.name}"`);
57  case "Function": throw new Error(`Unimplemented: section type "${section.name}"`);
58  case "Table": throw new Error(`Unimplemented: section type "${section.name}"`);
59  case "Memory": throw new Error(`Unimplemented: section type "${section.name}"`);
60  case "Global": throw new Error(`Unimplemented: section type "${section.name}"`);
61  case "Export": throw new Error(`Unimplemented: section type "${section.name}"`);
62  case "Start": throw new Error(`Unimplemented: section type "${section.name}"`);
63  case "Element": throw new Error(`Unimplemented: section type "${section.name}"`);
64  case "Code":
65  const numberOfFunctionBodies = section.data.length;
66  put(sectionBin, "varuint", numberOfFunctionBodies);
67  for (const func of section.data) {
68  let funcBin = sectionBin.newPatchable("varuint");
69  const localCount = func.locals.length;
70  put(funcBin, "varuint", localCount);
71  if (localCount !== 0) throw new Error(`Unimplemented: locals`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
72  for (const op of func.code) {
73  put(funcBin, "uint8", op.value);
74  if (op.arguments.length !== 0) throw new Error(`Unimplemented: arguments`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
75  if (op.immediates.length !== 0) throw new Error(`Unimplemented: immediates`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
 46const _normalizeFunctionSignature = (params, ret) => {
 47 if (!Array.isArray(params)) throw new Error(`expected a parameter array, got "${params}"`);
 48 for (const p of params) if (!WASM.isValidValueType(p)) throw new Error(`Type parameter ${p} isn't a valid value type`);
 49 if (typeof(ret) === "undefined") ret = "void";
 50 if (Array.isArray(ret)) throw new Error(`Multiple return values aren't supported by WebAssembly yet`);
 51 if (ret !== "void" && !WASM.isValidValueType(ret)) throw new Error(`Type return ${ret} isn't a valid value type`);
 52 return [params, ret];
 53};
 54
 55const _maybeRegisterType = (builder, type) => {
 56 const typeSection = builder._getSection("Type");
 57 if (typeof(type) === "number") {
 58 // Type numbers already refer to the type section, no need to register them.
 59 if (builder._checked) {
 60 if (typeof(typeSection) === "undefined") throw new Error(`Can't use type ${type} if a type section isn't present`);
 61 if (typeof(typeSection.data[type]) === "undefined") throw new Error(`Type ${type} doesn't exist in type section`);
 62 }
 63 return type;
 64 }
 65 if (typeof(type) !== "object" || typeof(type.params) === "undefined") throw new Error(`Expected type to be a number or object with 'params' and optionally 'ret' fields`);
 66 const [params, ret] = _normalizeFunctionSignature(type.params, type.ret);
 67 if (typeof(typeSection) === "undefined") throw new Error(`Can't add type if a type section isn't present`);
 68 // Try reusing an equivalent type from the type section.
 69 types:
 70 for (let i = 0; i !== typeSection.data.length; ++i) {
 71 const t = typeSection.data[i];
 72 if (t.ret === ret && params.length === t.params.length) {
 73 for (let j = 0; j !== t.params.length; ++j)
 74 if (params[j] !== t.params[j])
 75 continue types;
 76 type = i;
 77 break types;
 78 }
 79 }
 80 if (typeof(type) !== "number") {
 81 // Couldn't reuse a pre-existing type, register this type in the type section.
 82 typeSection.data.push({ params: params, ret: ret });
 83 type = typeSection.data.length - 1;
 84 }
 85 return type;
 86};
 87
 88const _importFunctionContinuation = (builder, section, nextBuilder) => {
 89 return (module, field, type) => {
 90 if (typeof(module) !== "string") throw new Error(`Import function module should be a string, got "${module}"`);
 91 if (typeof(field) !== "string") throw new Error(`Import function field should be a string, got "${field}"`);
 92 const typeSection = builder._getSection("Type");
 93 type = _maybeRegisterType(builder, type);
 94 section.data.push({ field: field, type: type, kind: "Function", module: module });
 95 // Imports also count in the function index space. Map them as objects to avoid clashing with Code functions' names.
 96 builder._registerFunctionToIndexSpace({ module: module, field: field });
 97 return nextBuilder;
 98 };
 99};
 100
 101const _exportFunctionContinuation = (builder, section, nextBuilder) => {
 102 return (field, index, type) => {
 103 if (typeof(field) !== "string") throw new Error(`Export function field should be a string, got "${field}"`);
 104 const typeSection = builder._getSection("Type");
 105 if (typeof(type) !== "undefined") {
 106 // Exports can leave the type unspecified, letting the Code builder patch them up later.
 107 type = _maybeRegisterType(builder, type);
 108 }
 109 // We can't check much about "index" here because the Code section succeeds the Export section. More work is done at Code().End() time.
 110 switch (typeof(index)) {
 111 case "string": break; // Assume it's a function name which will be revealed in the Code section.
 112 case "number": break; // Assume it's a number in the "function index space".
 113 case "object":
 114 // Re-exporting an import.
 115 if (typeof(index.module) === "undefined" || typeof(index.field) === "undefined") throw new Error(`Re-exporting "${field}" from an import requires an object with module and field`);
 116 break;
 117 case "undefined": index = field; break; // Assume it's the same as the field (i.e. it's not being renamed).
 118 default: throw new Error(`Export section's index must be a string or a number, got ${index}`);
 119 }
 120 const correspondingImport = builder._getFunctionFromIndexSpace(index);
 121 const importSection = builder._getSection("Import");
 122 if (typeof(index) === "object") {
 123 // Re-exporting an import using its module+field name.
 124 if (typeof(correspondingImport) === "undefined") throw new Error(`Re-exporting "${field}" couldn't find import from module "${index.module}" field "${index.field}"`);
 125 index = correspondingImport;
 126 if (typeof(type) === "undefined")
 127 type = importSection.data[index].type;
 128 if (builder._checked && type !== importSection.data[index].type) throw new Error(`Re-exporting import "${importSection.data[index].field}" as "${field}" has mismatching type`);
 129 } else if (typeof(correspondingImport) !== "undefined") {
 130 // Re-exporting an import using its index.
 131 let exportedImport;
 132 for (const i of importSection.data) {
 133 if (i.module === correspondingImport.module && i.field === correspondingImport.field) {
 134 exportedImport = i;
 135 break;
76136 }
77  funcBin.apply();
78137 }
79  break;
80  case "Data": throw new Error(`Unimplemented: section type "${section.name}"`);
81  default:
82  if (section.id !== _unknownSectionId) throw new Error(`Unknown section "${section.name}" with number ${section.id}`);
83  put(sectionBin, "string", section.name);
84  for (const byte of section.data)
85  put(sectionBin, "uint8", byte);
86  break;
 138 if (typeof(type) === "undefined")
 139 type = exportedImport.type;
 140 if (builder._checked && type !== exportedImport.type) throw new Error(`Re-exporting import "${exportedImport.field}" as "${field}" has mismatching type`);
87141 }
88  sectionBin.apply();
89  }
90  return wasmBin;
 142 section.data.push({ field: field, type: type, kind: "Function", index: index });
 143 return nextBuilder;
 144 };
91145};
92146
93147export default class Builder {

@@export default class Builder {
98152 preamble[p.name] = p.value;
99153 this.setPreamble(preamble);
100154 this._sections = [];
 155 this._functionIndexSpace = {};
 156 this._functionIndexSpaceCount = 0;
101157 this._registerSectionBuilders();
102158 }
103159 setChecked(checked) {

@@export default class Builder {
108164 this._preamble = Object.assign(this._preamble || {}, p);
109165 return this;
110166 }
 167 _registerFunctionToIndexSpace(name) {
 168 // Collisions are fine: we'll simply count the function and forget the previous one.
 169 this._functionIndexSpace[name] = this._functionIndexSpaceCount++;
 170 // Map it both ways, the number space is distinct from the name space.
 171 this._functionIndexSpace[this._functionIndexSpace[name]] = name;
 172 }
 173 _getFunctionFromIndexSpace(name) {
 174 return this._functionIndexSpace[name];
 175 }
111176 _registerSectionBuilders() {
112177 for (const section in WASM.description.section) {
113178 switch (section) {
 179 case "Type":
 180 this[section] = function() {
 181 const s = this._addSection(section);
 182 const builder = this;
 183 const typeBuilder = {
 184 End: () => builder,
 185 Func: (params, ret) => {
 186 [params, ret] = _normalizeFunctionSignature(params, ret);
 187 s.data.push({ params: params, ret: ret });
 188 return typeBuilder;
 189 },
 190 };
 191 return typeBuilder;
 192 };
 193 break;
 194 case "Import":
 195 this[section] = function() {
 196 const s = this._addSection(section);
 197 const importBuilder = {
 198 End: () => this,
 199 Table: () => { throw new Error(`Unimplemented: import table`); },
 200 Memory: () => { throw new Error(`Unimplemented: import memory`); },
 201 Global: () => { throw new Error(`Unimplemented: import global`); },
 202 };
 203 importBuilder.Function = _importFunctionContinuation(this, s, importBuilder);
 204 return importBuilder;
 205 };
 206 break;
 207 case "Export":
 208 this[section] = function() {
 209 const s = this._addSection(section);
 210 const exportBuilder = {
 211 End: () => this,
 212 Table: () => { throw new Error(`Unimplemented: export table`); },
 213 Memory: () => { throw new Error(`Unimplemented: export memory`); },
 214 Global: () => { throw new Error(`Unimplemented: export global`); },
 215 };
 216 exportBuilder.Function = _exportFunctionContinuation(this, s, exportBuilder);
 217 return exportBuilder;
 218 };
 219 break;
114220 case "Code":
115221 this[section] = function() {
116222 const s = this._addSection(section);
117223 const builder = this;
118224 const codeBuilder = {
119  End: () => builder,
120  Function: parameters => {
121  parameters = parameters || [];
122  const invalidParameterTypes = parameters.filter(p => !WASM.isValidValueType(p));
123  if (invalidParameterTypes.length !== 0) throw new Error(`Function declared with parameters [${parameters}], invalid: [${invalidParameterTypes}]`);
 225 End: () => {
 226 // We now have enough information to remap the export section's "type" and "index" according to the Code section we're currently ending.
 227 const typeSection = builder._getSection("Type");
 228 const importSection = builder._getSection("Import");
 229 const exportSection = builder._getSection("Export");
 230 const codeSection = s;
 231 if (exportSection) {
 232 for (const e of exportSection.data) {
 233 switch (typeof(e.index)) {
 234 default: throw new Error(`Unexpected export index "${e.index}"`);
 235 case "string": {
 236 const index = builder._getFunctionFromIndexSpace(e.index);
 237 if (typeof(index) !== "number") throw new Error(`Export section contains undefined function "${e.index}"`);
 238 e.index = index;
 239 } // Fallthrough.
 240 case "number": {
 241 const index = builder._getFunctionFromIndexSpace(e.index);
 242 if (builder._checked && index === "undefined") throw new Error(`Export "${e.field}" doesn't correspond to a defined in the function index space`);
 243 } break;
 244 case "undefined":
 245 throw new Error(`Unimplemented: Function().End() with undefined export index`); // FIXME
 246 }
 247 if (typeof(e.type) === "undefined") {
 248 // This must be a function export from the Code section (re-exports were handled earlier).
 249 const functionIndexSpaceOffset = importSection ? importSection.data.length : 0;
 250 const functionIndex = e.index - functionIndexSpaceOffset;
 251 e.type = codeSection.data[functionIndex].type;
 252 }
 253 }
 254 }
 255 return builder;
 256 },
 257 Function: (a0, a1) => {
 258 let signature = typeof(a0) === "string" ? a1 : a0;
 259 const functionName = typeof(a0) === "string" ? a0 : undefined;
 260 if (typeof(signature) === "undefined")
 261 signature = { params: [] };
 262 if (typeof(signature) !== "object" || typeof(signature.params) === "undefined") throw new Error(`Expect function signature to be an object with a "params" field, got "${signature}"`);
 263 const [params, ret] = _normalizeFunctionSignature(signature.params, signature.ret);
 264 signature = { params: params, ret: ret };
124265 const func = {
125  locals: parameters, // Parameters are the first locals.
126  parameterCount: parameters.length,
 266 name: functionName,
 267 type: _maybeRegisterType(builder, signature),
 268 signature: signature,
 269 locals: params, // Parameters are the first locals.
 270 parameterCount: params.length,
127271 code: []
128272 };
129273 s.data.push(func);
 274 builder._registerFunctionToIndexSpace(functionName);
130275 let functionBuilder = {};
131276 for (const op in WASM.description.opcode) {
132277 const name = _toJavaScriptName(op);

@@export default class Builder {
234379 _addSection(nameOrNumber, extraObject) {
235380 const name = typeof(nameOrNumber) === "string" ? nameOrNumber : "";
236381 const number = typeof(nameOrNumber) === "number" ? nameOrNumber : (WASM.description.section[name] ? WASM.description.section[name].value : _unknownSectionId);
 382 if (this._checked) {
 383 // Check uniqueness.
 384 for (const s of this._sections)
 385 if (s.name === name && s.id === number)
 386 throw new Error(`Cannot have to sections with the same name "${name}" and ID ${number}`);
 387 // Check ordering.
 388 if ((number !== _unknownSectionId) && (this._sections.length !== 0)) {
 389 for (let i = this._sections.length - 1; i >= 0; --i) {
 390 if (this._sections[i].id === _unknownSectionId)
 391 continue;
 392 if (this._sections[i].id > number)
 393 throw new Error(`Bad section ordering: "${this._sections[i].name}" cannot precede "${name}"`);
 394 break;
 395 }
 396 }
 397 }
237398 const s = Object.assign({ name: name, id: number, data: [] }, extraObject || {});
238399 this._sections.push(s);
239400 return s;
240401 }
 402 _getSection(nameOrNumber) {
 403 switch (typeof(nameOrNumber)) {
 404 default: throw new Error(`Implementation problem: can't get section "${nameOrNumber}"`);
 405 case "string":
 406 for (const s of this._sections)
 407 if (s.name === nameOrNumber)
 408 return s;
 409 return undefined;
 410 case "number":
 411 for (const s of this._sections)
 412 if (s.id === nameOrNumber)
 413 return s;
 414 return undefined;
 415 }
 416 }
241417 optimize() {
242418 // FIXME Add more optimizations. https://bugs.webkit.org/show_bug.cgi?id=163424
243419 return this;

@@export default class Builder {
254430 // FIXME Create an asm.js equivalent string which can be eval'd. https://bugs.webkit.org/show_bug.cgi?id=163425
255431 throw new Error("asm.js not implemented yet");
256432 }
257  WebAssembly() { return _BuildWebAssemblyBinary(this._preamble, this._sections); }
 433 WebAssembly() { return BuildWebAssembly.Binary(this._preamble, this._sections); }
258434};

JSTests/wasm/Builder_WebAssemblyBinary.js

 1/*
 2 * Copyright (C) 2016 Apple Inc. All rights reserved.
 3 *
 4 * Redistribution and use in source and binary forms, with or without
 5 * modification, are permitted provided that the following conditions
 6 * are met:
 7 * 1. Redistributions of source code must retain the above copyright
 8 * notice, this list of conditions and the following disclaimer.
 9 * 2. Redistributions in binary form must reproduce the above copyright
 10 * notice, this list of conditions and the following disclaimer in the
 11 * documentation and/or other materials provided with the distribution.
 12 *
 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 24 */
 25
 26import LowLevelBinary from 'LowLevelBinary.js';
 27import * as WASM from 'WASM.js';
 28
 29const put = (bin, type, value) => bin[type](value);
 30
 31const emitters = {
 32 Type: (section, bin) => {
 33 put(bin, "varuint", section.data.length);
 34 for (const entry of section.data) {
 35 const funcTypeConstructor = -0x20; // FIXME Move this to wasm.json.
 36 put(bin, "varint7", funcTypeConstructor);
 37 put(bin, "varuint", entry.params.length);
 38 for (const param of entry.params)
 39 put(bin, "uint8", WASM.valueTypeValue[param]);
 40 if (entry.ret === "void")
 41 put(bin, "varuint1", 0);
 42 else {
 43 put(bin, "varuint1", 1);
 44 put(bin, "uint8", WASM.valueTypeValue[entry.ret]);
 45 }
 46 }
 47 },
 48 Import: (section, bin) => {
 49 put(bin, "varuint", section.data.length);
 50 for (const entry of section.data) {
 51 put(bin, "string", entry.module);
 52 put(bin, "string", entry.field);
 53 put(bin, "uint8", WASM.externalKindValue[entry.kind]);
 54 switch (entry.kind) {
 55 default: throw new Error(`Implementation problem: unexpected kind ${entry.kind}`);
 56 case "Function": put(bin, "varuint", entry.type); break;
 57 case "Table": throw new Error(`Not yet implemented`);
 58 case "Memory": throw new Error(`Not yet implemented`);
 59 case "Global": throw new Error(`Not yet implemented`);
 60 }
 61 }
 62 },
 63 Function: (section, bin) => { throw new Error(`Not yet implemented`); },
 64 Table: (section, bin) => { throw new Error(`Not yet implemented`); },
 65 Memory: (section, bin) => { throw new Error(`Not yet implemented`); },
 66 Global: (section, bin) => { throw new Error(`Not yet implemented`); },
 67 Export: (section, bin) => { throw new Error(`Not yet implemented`); },
 68 Start: (section, bin) => { throw new Error(`Not yet implemented`); },
 69 Element: (section, bin) => { throw new Error(`Not yet implemented`); },
 70 Code: (section, bin) => {
 71 put(bin, "varuint", section.data.length);
 72 for (const func of section.data) {
 73 let funcBin = bin.newPatchable("varuint");
 74 const localCount = func.locals.length;
 75 put(funcBin, "varuint", localCount);
 76 if (localCount !== 0) throw new Error(`Unimplemented: locals`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
 77 for (const op of func.code) {
 78 put(funcBin, "uint8", op.value);
 79 if (op.arguments.length !== 0) throw new Error(`Unimplemented: arguments`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
 80 if (op.immediates.length !== 0) throw new Error(`Unimplemented: immediates`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
 81 }
 82 funcBin.apply();
 83 }
 84 },
 85 Data: (section, bin) => { throw new Error(`Not yet implemented`); },
 86};
 87
 88export const Binary = (preamble, sections) => {
 89 let wasmBin = new LowLevelBinary();
 90 for (const p of WASM.description.preamble)
 91 put(wasmBin, p.type, preamble[p.name]);
 92 for (const section of sections) {
 93 put(wasmBin, WASM.sectionEncodingType, section.id);
 94 let sectionBin = wasmBin.newPatchable("varuint");
 95 const emitter = emitters[section.name];
 96 if (emitter)
 97 emitter(section, sectionBin);
 98 else {
 99 // Unknown section.
 100 put(sectionBin, "string", section.name);
 101 for (const byte of section.data)
 102 put(sectionBin, "uint8", byte);
 103 }
 104 sectionBin.apply();
 105 }
 106 return wasmBin;
 107};

JSTests/wasm/LowLevelBinary.js

@@const _initialAllocationSize = 1024;
2727const _growAllocationSize = allocated => allocated * 2;
2828
2929export const varuintMin = 0;
 30export const varint7Min = -0b1000000;
 31export const varint7Max = 0b111111;
3032export const varuint7Max = 0b1111111;
3133export const varuintMax = ((((1 << 31) >>> 0) - 1) * 2) + 1;
3234export const varintMin = -((1 << 31) >>> 0);

@@export default class LowLevelBinary {
129131 this.uint8(0x80 | b);
130132 } while (true);
131133 }
 134 varuint1(v) {
 135 if (v !== 0 && v !== 1)
 136 throw new RangeError(`Invalid varuint1 ${v} range is [0, 1]`);
 137 this.varuint(v);
 138 }
 139 varint7(v) {
 140 if (v < varint7Min || varint7Max < v)
 141 throw new RangeError(`Invalid varint7 ${v} range is [${varint7Min}, ${varint7Max}]`);
 142 this.varint(v);
 143 }
132144 varuint7(v) {
133145 if (v < varuintMin || varuint7Max < v)
134146 throw new RangeError(`Invalid varuint7 ${v} range is [${varuintMin}, ${varuint7Max}]`);

JSTests/wasm/WASM.js

2525
2626import * as utilities from 'utilities.js';
2727
 28const _mapValues = from => {
 29 let values = {};
 30 for (const key in from)
 31 values[key] = from[key].value;
 32 return values;
 33};
 34
2835export const description = utilities.json("wasm.json");
2936export const valueType = Object.keys(description.value_type);
3037const _valueTypeSet = new Set(valueType);
3138export const isValidValueType = v => _valueTypeSet.has(v);
 39export const valueTypeValue = _mapValues(description.value_type);
 40export const externalKindValue = _mapValues(description.external_kind);
3241export const sections = Object.keys(description.section);
3342export const sectionEncodingType = description.section[sections[0]].type;

JSTests/wasm/assert.js

@@const _isUndef = (v) => {
3434};
3535
3636const _eq = (lhs, rhs) => {
 37 if (Array.isArray(lhs) && Array.isArray(rhs) && (lhs.length === rhs.length)) {
 38 for (let i = 0; i !== lhs.length; ++i)
 39 _eq(lhs[i], rhs[i]);
 40 return;
 41 }
3742 if (lhs !== rhs)
3843 throw new Error(`Not the same: "${lhs}" and "${rhs}"`);
3944};

JSTests/wasm/js-api/test_Module.js

@@import Builder from '../Builder.js';
77 const module = new WebAssembly.Module(bin);
88 assert.instanceof(module, WebAssembly.Module);
99})();
 10
 11(function ModuleWithImports() {
 12 const builder = (new Builder())
 13 .Type().End()
 14 .Import()
 15 .Function("foo", "bar", { params: [] })
 16 .End();
 17 const bin = builder.WebAssembly().get();
 18 const module = new WebAssembly.Module(bin);
 19})();

JSTests/wasm/self-test/test_BuilderJSON.js

@@import * as assert from '../assert.js';
22import Builder from '../Builder.js';
33
44const assertOpThrows = (opFn, message) => {
5  let f = (new Builder()).Code().Function();
 5 let f = (new Builder()).Type().End().Code().Function();
66 assert.throws(opFn, Error, message, f);
77};
88

@@const assertOpThrows = (opFn, message) => {
8686 assert.eq(j.section[1].data[0], 0x11);
8787})();
8888
 89(function SectionsWithSameCustomName() {
 90 const b = (new Builder()).Unknown("foo").End();
 91 assert.throws(() => b.Unknown("foo"), Error, `Cannot have to sections with the same name "foo" and ID 0`);
 92})();
 93
 94(function EmptyTypeSection() {
 95 const b = (new Builder()).Type().End();
 96 const j = JSON.parse(b.json());
 97 assert.eq(j.section.length, 1);
 98 assert.eq(j.section[0].name, "Type");
 99 assert.eq(j.section[0].data.length, 0);
 100})();
 101
 102(function TwoTypeSections() {
 103 const b = (new Builder()).Type().End();
 104 assert.throws(() => b.Type(), Error, `Cannot have to sections with the same name "Type" and ID 1`);
 105})();
 106
 107(function SimpleTypeSection() {
 108 const b = (new Builder()).Type()
 109 .Func([])
 110 .Func([], "void")
 111 .Func([], "i32")
 112 .Func([], "i64")
 113 .Func([], "f32")
 114 .Func([], "f64")
 115 .Func(["i32", "i64", "f32", "f64"])
 116 .End();
 117 const j = JSON.parse(b.json());
 118 assert.eq(j.section[0].data.length, 7);
 119 assert.eq(j.section[0].data[0].params, []);
 120 assert.eq(j.section[0].data[0].ret, "void");
 121 assert.eq(j.section[0].data[1].params, []);
 122 assert.eq(j.section[0].data[1].ret, "void");
 123 assert.eq(j.section[0].data[2].params, []);
 124 assert.eq(j.section[0].data[2].ret, "i32");
 125 assert.eq(j.section[0].data[3].params, []);
 126 assert.eq(j.section[0].data[3].ret, "i64");
 127 assert.eq(j.section[0].data[4].params, []);
 128 assert.eq(j.section[0].data[4].ret, "f32");
 129 assert.eq(j.section[0].data[5].params, []);
 130 assert.eq(j.section[0].data[5].ret, "f64");
 131 assert.eq(j.section[0].data[6].params, ["i32", "i64", "f32", "f64"]);
 132 assert.eq(j.section[0].data[6].ret, "void");
 133})();
 134
 135(function EmptyImportSection() {
 136 const b = (new Builder()).Import().End();
 137 const j = JSON.parse(b.json());
 138 assert.eq(j.section.length, 1);
 139 assert.eq(j.section[0].name, "Import");
 140 assert.eq(j.section[0].data.length, 0);
 141})();
 142
 143(function ImportBeforeTypeSections() {
 144 const b = (new Builder()).Import().End();
 145 assert.throws(() => b.Type(), Error, `Bad section ordering: "Import" cannot precede "Type"`);
 146})();
 147
 148(function ImportFunctionWithoutTypeSection() {
 149 const i = (new Builder()).Import();
 150 assert.throws(() => i.Function("foo", "bar", 0), Error, `Can't use type 0 if a type section isn't present`);
 151})();
 152
 153(function ImportFunctionWithInvalidType() {
 154 const i = (new Builder()).Type().End().Import();
 155 assert.throws(() => i.Function("foo", "bar", 0), Error, `Type 0 doesn't exist in type section`);
 156})();
 157
 158(function ImportFunction() {
 159 const b = (new Builder())
 160 .Type().Func([]).End()
 161 .Import()
 162 .Function("foo", "bar", 0)
 163 .End();
 164 const j = JSON.parse(b.json());
 165 assert.eq(j.section[1].data.length, 1);
 166 assert.eq(j.section[1].data[0].module, "foo");
 167 assert.eq(j.section[1].data[0].field, "bar");
 168 assert.eq(j.section[1].data[0].type, 0);
 169 assert.eq(j.section[1].data[0].kind, "Function");
 170})();
 171
 172(function ImportFunctionsWithExistingTypes() {
 173 const b = (new Builder())
 174 .Type()
 175 .Func([])
 176 .Func([], "i32")
 177 .Func(["i64", "i32"])
 178 .Func(["i64", "i64"])
 179 .End()
 180 .Import()
 181 .Function("foo", "bar", { params: [] })
 182 .Function("foo", "baz", { params: [], ret: "i32" })
 183 .Function("foo", "boo", { params: ["i64", "i64"] })
 184 .End();
 185 const j = JSON.parse(b.json());
 186 assert.eq(j.section[0].data.length, 4);
 187 assert.eq(j.section[1].data.length, 3);
 188 assert.eq(j.section[1].data[0].type, 0);
 189 assert.eq(j.section[1].data[1].type, 1);
 190 assert.eq(j.section[1].data[2].type, 3);
 191})();
 192
 193(function ImportFunctionWithNewType() {
 194 const b = (new Builder())
 195 .Type().End()
 196 .Import()
 197 .Function("foo", "bar", { params: [] })
 198 .Function("foo", "baz", { params: [], ret: "i32" })
 199 .Function("foo", "boo", { params: ["i64", "i64"] })
 200 .End();
 201 const j = JSON.parse(b.json());
 202 assert.eq(j.section[0].data.length, 3);
 203 assert.eq(j.section[0].data[0].ret, "void");
 204 assert.eq(j.section[0].data[0].params, []);
 205 assert.eq(j.section[0].data[1].ret, "i32");
 206 assert.eq(j.section[0].data[1].params, []);
 207 assert.eq(j.section[0].data[2].ret, "void");
 208 assert.eq(j.section[0].data[2].params, ["i64", "i64"]);
 209})();
 210
 211(function EmptyExportSection() {
 212 const b = (new Builder()).Export().End();
 213 const j = JSON.parse(b.json());
 214 assert.eq(j.section.length, 1);
 215 assert.eq(j.section[0].name, "Export");
 216 assert.eq(j.section[0].data.length, 0);
 217})();
 218
 219(function ExportFunctionWithoutTypeSection() {
 220 const e = (new Builder()).Export();
 221 assert.throws(() => e.Function("foo", 0, 0), Error, `Can't use type 0 if a type section isn't present`);
 222})();
 223
 224(function ExportFunctionWithInvalidType() {
 225 const e = (new Builder()).Type().End().Export();
 226 assert.throws(() => e.Function("foo", 0, 0), Error, `Type 0 doesn't exist in type section`);
 227})();
 228
 229(function ExportAnImport() {
 230 const b = (new Builder())
 231 .Type().End()
 232 .Import().Function("foo", "bar", { params: [] }).End()
 233 .Export().Function("ExportAnImport", { module: "foo", field: "bar" }).End();
 234 const j = JSON.parse(b.json());
 235 assert.eq(j.section[2].name, "Export");
 236 assert.eq(j.section[2].data.length, 1);
 237 assert.eq(j.section[2].data[0].field, "ExportAnImport");
 238 assert.eq(j.section[2].data[0].type, 0);
 239 assert.eq(j.section[2].data[0].index, 0);
 240 assert.eq(j.section[2].data[0].kind, "Function");
 241})();
 242
 243(function ExportMismatchedImport() {
 244 const e = (new Builder())
 245 .Type().End()
 246 .Import().Function("foo", "bar", { params: [] }).End()
 247 .Export();
 248 assert.throws(() => e.Function("foo", 0, { params: ["i32"] }), Error, `Re-exporting import "bar" as "foo" has mismatching type`);
 249})();
 250
89251(function EmptyCodeSection() {
90252 const b = new Builder();
91253 b.Code();

@@const assertOpThrows = (opFn, message) => {
97259
98260(function CodeSectionWithEmptyFunction() {
99261 const b = new Builder();
100  b.Code()
101  .Function();
 262 b.Type().End()
 263 .Code()
 264 .Function();
102265 const j = JSON.parse(b.json());
103  assert.eq(j.section.length, 1);
104  assert.eq(j.section[0].name, "Code");
 266 assert.eq(j.section.length, 2);
 267 assert.eq(j.section[0].name, "Type");
105268 assert.eq(j.section[0].data.length, 1);
106  assert.eq(j.section[0].data[0].parameterCount, 0);
107  assert.eq(j.section[0].data[0].locals.length, 0);
108  assert.eq(j.section[0].data[0].code.length, 0);
 269 assert.eq(j.section[0].data[0].params, []);
 270 assert.eq(j.section[0].data[0].ret, "void");
 271 assert.eq(j.section[1].name, "Code");
 272 assert.eq(j.section[1].data.length, 1);
 273 assert.eq(j.section[1].data[0].name, undefined);
 274 assert.eq(j.section[1].data[0].type, 0);
 275 assert.eq(j.section[1].data[0].parameterCount, 0);
 276 assert.eq(j.section[1].data[0].locals.length, 0);
 277 assert.eq(j.section[1].data[0].code.length, 0);
109278})();
110279
111280(function CodeSectionWithEmptyFunctionWithParameters() {
112281 const b = new Builder();
113  b.Code()
114  .Function(["i32", "i64", "f32", "f64"]);
 282 b.Type().End()
 283 .Code()
 284 .Function({ params: ["i32", "i64", "f32", "f64"] });
115285 const j = JSON.parse(b.json());
116  assert.eq(j.section.length, 1);
117  assert.eq(j.section[0].name, "Code");
 286 assert.eq(j.section.length, 2);
118287 assert.eq(j.section[0].data.length, 1);
119  assert.eq(j.section[0].data[0].parameterCount, 4);
120  assert.eq(j.section[0].data[0].locals[0], "i32");
121  assert.eq(j.section[0].data[0].locals[1], "i64");
122  assert.eq(j.section[0].data[0].locals[2], "f32");
123  assert.eq(j.section[0].data[0].locals[3], "f64");
124  assert.eq(j.section[0].data[0].code.length, 0);
 288 assert.eq(j.section[0].data[0].params, ["i32", "i64", "f32", "f64"]);
 289 assert.eq(j.section[0].data[0].ret, "void");
 290 assert.eq(j.section[1].data.length, 1);
 291 assert.eq(j.section[1].data[0].type, 0);
 292 assert.eq(j.section[1].data[0].parameterCount, 4);
 293 assert.eq(j.section[1].data[0].locals[0], "i32");
 294 assert.eq(j.section[1].data[0].locals[1], "i64");
 295 assert.eq(j.section[1].data[0].locals[2], "f32");
 296 assert.eq(j.section[1].data[0].locals[3], "f64");
 297 assert.eq(j.section[1].data[0].code.length, 0);
125298})();
126299
127300(function InvalidFunctionParameters() {
128  for (let invalid in ["", "void", "bool", "any", "struct"]) {
 301 for (let invalid of ["", "void", "bool", "any", "struct", 0, 3.14, undefined, [], {}]) {
129302 const c = (new Builder()).Code();
130  try {
131  c.Function([invalid]);
132  } catch (e) {
133  if (e instanceof Error) { continue; }
134  throw new Error(`Expected an Error, got ${e}`);
135  }
136  throw new Error(`Expected to throw an Error for ${invalid}`);
 303 assert.throws(() => c.Function({ params: [invalid] }), Error, `Type parameter ${invalid} isn't a valid value type`);
137304 }
138305})();
139306
140307(function SimpleFunction() {
141308 const b = new Builder();
142  b.Code()
143  .Function()
144  .Nop()
145  .Nop()
146  .End();
 309 b.Type().End()
 310 .Code()
 311 .Function()
 312 .Nop()
 313 .Nop()
 314 .End();
147315 const j = JSON.parse(b.json());
148  assert.eq(j.section[0].data.length, 1);
149  assert.eq(j.section[0].data[0].locals.length, 0);
150  assert.eq(j.section[0].data[0].code.length, 3);
151  assert.eq(j.section[0].data[0].code[0].name, "nop");
152  assert.eq(j.section[0].data[0].code[1].name, "nop");
153  assert.eq(j.section[0].data[0].code[2].name, "end");
 316 assert.eq(j.section[1].data.length, 1);
 317 assert.eq(j.section[1].data[0].locals.length, 0);
 318 assert.eq(j.section[1].data[0].code.length, 3);
 319 assert.eq(j.section[1].data[0].code[0].name, "nop");
 320 assert.eq(j.section[1].data[0].code[1].name, "nop");
 321 assert.eq(j.section[1].data[0].code[2].name, "end");
154322})();
155323
156324(function TwoSimpleFunctions() {
157325 const b = new Builder();
158  b.Code()
159  .Function()
160  .Nop()
161  .Nop()
 326 b.Type().End()
 327 .Code()
 328 .Function()
 329 .Nop()
 330 .Nop()
 331 .End()
 332 .Function()
 333 .Return()
 334 .End();
 335 const j = JSON.parse(b.json());
 336 assert.eq(j.section[1].data.length, 2);
 337 assert.eq(j.section[1].data[0].locals.length, 0);
 338 assert.eq(j.section[1].data[0].code.length, 3);
 339 assert.eq(j.section[1].data[0].code[0].name, "nop");
 340 assert.eq(j.section[1].data[0].code[1].name, "nop");
 341 assert.eq(j.section[1].data[0].code[2].name, "end");
 342 assert.eq(j.section[1].data[1].locals.length, 0);
 343 assert.eq(j.section[1].data[1].code.length, 2);
 344 assert.eq(j.section[1].data[1].code[0].name, "return");
 345 assert.eq(j.section[1].data[1].code[1].name, "end");
 346})();
 347
 348(function NamedFunctions() {
 349 const b = new Builder().Type().End().Code()
 350 .Function("hello").End()
 351 .Function("world", { params: ["i32"] }).End()
 352 .End();
 353 const j = JSON.parse(b.json());
 354 assert.eq(j.section[1].data[0].name, "hello");
 355 assert.eq(j.section[1].data[0].parameterCount, 0);
 356 assert.eq(j.section[1].data[1].name, "world");
 357 assert.eq(j.section[1].data[1].parameterCount, 1);
 358})();
 359
 360(function ExportSimpleFunctions() {
 361 const b = (new Builder())
 362 .Type().End()
 363 .Export()
 364 .Function("foo", 0, { params: [] })
 365 .Function("bar")
 366 .Function("betterNameForBar", "bar")
162367 .End()
163  .Function()
164  .Return()
 368 .Code()
 369 .Function({ params: [] }).Nop().End()
 370 .Function("bar", { params: [] }).Nop().End()
165371 .End();
166372 const j = JSON.parse(b.json());
167  assert.eq(j.section[0].data.length, 2);
168  assert.eq(j.section[0].data[0].locals.length, 0);
169  assert.eq(j.section[0].data[0].code.length, 3);
170  assert.eq(j.section[0].data[0].code[0].name, "nop");
171  assert.eq(j.section[0].data[0].code[1].name, "nop");
172  assert.eq(j.section[0].data[0].code[2].name, "end");
173  assert.eq(j.section[0].data[1].locals.length, 0);
174  assert.eq(j.section[0].data[1].code.length, 2);
175  assert.eq(j.section[0].data[1].code[0].name, "return");
176  assert.eq(j.section[0].data[1].code[1].name, "end");
 373 assert.eq(j.section[0].data.length, 1);
 374 assert.eq(j.section[0].data[0].ret, "void");
 375 assert.eq(j.section[0].data[0].params, []);
 376 assert.eq(j.section[1].data.length, 3);
 377 assert.eq(j.section[1].data[0].field, "foo");
 378 assert.eq(j.section[1].data[0].type, 0);
 379 assert.eq(j.section[1].data[0].index, 0);
 380 assert.eq(j.section[1].data[0].kind, "Function");
 381 assert.eq(j.section[1].data[1].field, "bar");
 382 assert.eq(j.section[1].data[1].type, 0);
 383 assert.eq(j.section[1].data[1].index, 1);
 384 assert.eq(j.section[1].data[1].kind, "Function");
 385 assert.eq(j.section[1].data[2].field, "betterNameForBar");
 386 assert.eq(j.section[1].data[2].type, 0);
 387 assert.eq(j.section[1].data[2].index, 1);
 388 assert.eq(j.section[1].data[2].kind, "Function");
 389})();
 390
 391(function ExportUndefinedFunction() {
 392 const c = (new Builder()).Type().End().Export().Function("foo").End().Code();
 393 assert.throws(() => c.End(), Error, `Export section contains undefined function "foo"`);
177394})();
178395
179396(function TwoBuildersAtTheSameTime() {
180397 const b = [new Builder(), new Builder()];
181  const f = b.map(builder => builder.Code().Function());
 398 const f = b.map(builder => builder.Type().End().Code().Function());
182399 f[0].Nop();
183400 f[1].Return().End().End();
184401 f[0].Nop().End().End();
185402 const j = b.map(builder => JSON.parse(builder.json()));
186  assert.eq(j[0].section[0].data[0].code.length, 3);
187  assert.eq(j[0].section[0].data[0].code[0].name, "nop");
188  assert.eq(j[0].section[0].data[0].code[1].name, "nop");
189  assert.eq(j[0].section[0].data[0].code[2].name, "end");
190  assert.eq(j[1].section[0].data[0].code.length, 2);
191  assert.eq(j[1].section[0].data[0].code[0].name, "return");
192  assert.eq(j[1].section[0].data[0].code[1].name, "end");
 403 assert.eq(j[0].section[1].data[0].code.length, 3);
 404 assert.eq(j[0].section[1].data[0].code[0].name, "nop");
 405 assert.eq(j[0].section[1].data[0].code[1].name, "nop");
 406 assert.eq(j[0].section[1].data[0].code[2].name, "end");
 407 assert.eq(j[1].section[1].data[0].code.length, 2);
 408 assert.eq(j[1].section[1].data[0].code[0].name, "return");
 409 assert.eq(j[1].section[1].data[0].code[1].name, "end");
193410})();
194411
195412(function CheckedOpcodeArgumentsTooMany() {

@@const assertOpThrows = (opFn, message) => {
197414})();
198415
199416(function UncheckedOpcodeArgumentsTooMany() {
200  (new Builder()).setChecked(false).Code().Function().Nop("This is fine.", "I'm OK with the events that are unfolding currently.");
 417 (new Builder()).setChecked(false).Type().End().Code().Function().Nop("This is fine.", "I'm OK with the events that are unfolding currently.");
201418})();
202419
203420(function CheckedOpcodeArgumentsNotEnough() {

@@const assertOpThrows = (opFn, message) => {
205422})();
206423
207424(function UncheckedOpcodeArgumentsNotEnough() {
208  (new Builder()).setChecked(false).Code().Function().I32Const();
 425 (new Builder()).setChecked(false).Type().End().Code().Function().I32Const();
209426})();
210427
211428(function CallNoArguments() {
212  const b = (new Builder()).Code().Function().Call(0).End().End();
 429 const b = (new Builder()).Type().End().Code().Function().Call(0).End().End();
213430 const j = JSON.parse(b.json());
214  assert.eq(j.section[0].data[0].code.length, 2);
215  assert.eq(j.section[0].data[0].code[0].name, "call");
216  assert.eq(j.section[0].data[0].code[0].arguments.length, 0);
217  assert.eq(j.section[0].data[0].code[0].immediates.length, 1);
218  assert.eq(j.section[0].data[0].code[0].immediates[0], 0);
219  assert.eq(j.section[0].data[0].code[1].name, "end");
 431 assert.eq(j.section[1].data[0].code.length, 2);
 432 assert.eq(j.section[1].data[0].code[0].name, "call");
 433 assert.eq(j.section[1].data[0].code[0].arguments.length, 0);
 434 assert.eq(j.section[1].data[0].code[0].immediates.length, 1);
 435 assert.eq(j.section[1].data[0].code[0].immediates[0], 0);
 436 assert.eq(j.section[1].data[0].code[1].name, "end");
220437})();
221438
222439(function CallInvalid() {

@@const assertOpThrows = (opFn, message) => {
226443
227444(function I32ConstValid() {
228445 for (let c of [0, 1, 2, 42, 1337, 0xFF, 0xFFFF, 0x7FFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF]) {
229  const b = (new Builder()).Code().Function().I32Const(c).Return().End().End();
 446 const b = (new Builder()).Type().End().Code().Function().I32Const(c).Return().End().End();
230447 const j = JSON.parse(b.json());
231  assert.eq(j.section[0].data[0].code[0].name, "i32.const");
232  assert.eq(j.section[0].data[0].code[0].arguments.length, 0);
233  assert.eq(j.section[0].data[0].code[0].immediates.length, 1);
234  assert.eq(j.section[0].data[0].code[0].immediates[0], c);
 448 assert.eq(j.section[1].data[0].code[0].name, "i32.const");
 449 assert.eq(j.section[1].data[0].code[0].arguments.length, 0);
 450 assert.eq(j.section[1].data[0].code[0].immediates.length, 1);
 451 assert.eq(j.section[1].data[0].code[0].immediates[0], c);
235452 }
236453})();
237454

@@const assertOpThrows = (opFn, message) => {
244461
245462(function F32ConstValid() {
246463 for (let c of [0, -0., 0.2, Math.PI, 0x100000000]) {
247  const b = (new Builder()).Code().Function().F32Const(c).Return().End().End();
 464 const b = (new Builder()).Type().End().Code().Function().F32Const(c).Return().End().End();
248465 const j = JSON.parse(b.json());
249  assert.eq(j.section[0].data[0].code[0].name, "f32.const");
250  assert.eq(j.section[0].data[0].code[0].arguments.length, 0);
251  assert.eq(j.section[0].data[0].code[0].immediates.length, 1);
252  assert.eq(j.section[0].data[0].code[0].immediates[0], c);
 466 assert.eq(j.section[1].data[0].code[0].name, "f32.const");
 467 assert.eq(j.section[1].data[0].code[0].arguments.length, 0);
 468 assert.eq(j.section[1].data[0].code[0].immediates.length, 1);
 469 assert.eq(j.section[1].data[0].code[0].immediates[0], c);
253470 }
254471})();
255472

@@const assertOpThrows = (opFn, message) => {
260477
261478(function F64ConstValid() {
262479 for (let c of [0, -0., 0.2, Math.PI, 0x100000000]) {
263  const b = (new Builder()).Code().Function().F64Const(c).Return().End().End();
 480 const b = (new Builder()).Type().End().Code().Function().F64Const(c).Return().End().End();
264481 const j = JSON.parse(b.json());
265  assert.eq(j.section[0].data[0].code[0].name, "f64.const");
266  assert.eq(j.section[0].data[0].code[0].arguments.length, 0);
267  assert.eq(j.section[0].data[0].code[0].immediates.length, 1);
268  assert.eq(j.section[0].data[0].code[0].immediates[0], c);
 482 assert.eq(j.section[1].data[0].code[0].name, "f64.const");
 483 assert.eq(j.section[1].data[0].code[0].arguments.length, 0);
 484 assert.eq(j.section[1].data[0].code[0].immediates.length, 1);
 485 assert.eq(j.section[1].data[0].code[0].immediates[0], c);
269486 }
270487})();
271488

@@const assertOpThrows = (opFn, message) => {
275492})();
276493
277494(function CallOneFromStack() {
278  const b = (new Builder()).Code()
279  .Function(["i32"])
 495 const b = (new Builder()).Type().End().Code()
 496 .Function({ params: ["i32"] })
280497 .I32Const(42)
281498 .Call(0)
282499 .End()
283500 .End();
284501 const j = JSON.parse(b.json());
285  assert.eq(j.section[0].data[0].code.length, 3);
286  assert.eq(j.section[0].data[0].code[0].name, "i32.const");
287  assert.eq(j.section[0].data[0].code[0].immediates[0], 42);
288  assert.eq(j.section[0].data[0].code[1].name, "call");
289  // FIXME: assert.eq(j.section[0].data[0].code[1].arguments.length, 1); https://bugs.webkit.org/show_bug.cgi?id=163267
290  assert.eq(j.section[0].data[0].code[1].immediates.length, 1);
291  assert.eq(j.section[0].data[0].code[1].immediates[0], 0);
292  assert.eq(j.section[0].data[0].code[2].name, "end");
 502 assert.eq(j.section[1].data[0].code.length, 3);
 503 assert.eq(j.section[1].data[0].code[0].name, "i32.const");
 504 assert.eq(j.section[1].data[0].code[0].immediates[0], 42);
 505 assert.eq(j.section[1].data[0].code[1].name, "call");
 506 // FIXME: assert.eq(j.section[1].data[0].code[1].arguments.length, 1); https://bugs.webkit.org/show_bug.cgi?id=163267
 507 assert.eq(j.section[1].data[0].code[1].immediates.length, 1);
 508 assert.eq(j.section[1].data[0].code[1].immediates[0], 0);
 509 assert.eq(j.section[1].data[0].code[2].name, "end");
293510})();
294511
295512// FIXME https://bugs.webkit.org/show_bug.cgi?id=163267 all of these:

@@const assertOpThrows = (opFn, message) => {
301518// test function names (both setting and calling them).
302519
303520(function CallManyFromStack() {
304  const b = (new Builder()).Code()
305  .Function(["i32", "i32", "i32", "i32"])
 521 const b = (new Builder()).Type().End().Code()
 522 .Function({ params: ["i32", "i32", "i32", "i32"] })
306523 .I32Const(42).I32Const(1337).I32Const(0xBEEF).I32Const(0xFFFF)
307524 .Call(0)
308525 .End()
309526 .End();
310527 const j = JSON.parse(b.json());
311  assert.eq(j.section[0].data[0].code.length, 6);
312  assert.eq(j.section[0].data[0].code[4].name, "call");
313  // FIXME: assert.eq(j.section[0].data[0].code[4].arguments.length, 4); https://bugs.webkit.org/show_bug.cgi?id=163267
314  assert.eq(j.section[0].data[0].code[4].immediates.length, 1);
315  assert.eq(j.section[0].data[0].code[4].immediates[0], 0);
 528 assert.eq(j.section[1].data[0].code.length, 6);
 529 assert.eq(j.section[1].data[0].code[4].name, "call");
 530 // FIXME: assert.eq(j.section[1].data[0].code[4].arguments.length, 4); https://bugs.webkit.org/show_bug.cgi?id=163267
 531 assert.eq(j.section[1].data[0].code[4].immediates.length, 1);
 532 assert.eq(j.section[1].data[0].code[4].immediates[0], 0);
316533})();
317534
318535(function OpcodeAdd() {
319  const b = (new Builder()).Code()
 536 const b = (new Builder()).Type().End().Code()
320537 .Function()
321538 .I32Const(42).I32Const(1337)
322539 .I32Add()

@@const assertOpThrows = (opFn, message) => {
324541 .End()
325542 .End();
326543 const j = JSON.parse(b.json());
327  assert.eq(j.section[0].data[0].code.length, 5);
328  assert.eq(j.section[0].data[0].code[2].name, "i32.add");
329  // FIXME: assert.eq(j.section[0].data[0].code[2].arguments.length, 2); https://bugs.webkit.org/show_bug.cgi?id=163267
330  assert.eq(j.section[0].data[0].code[3].name, "return");
 544 assert.eq(j.section[1].data[0].code.length, 5);
 545 assert.eq(j.section[1].data[0].code[2].name, "i32.add");
 546 // FIXME: assert.eq(j.section[1].data[0].code[2].arguments.length, 2); https://bugs.webkit.org/show_bug.cgi?id=163267
 547 assert.eq(j.section[1].data[0].code[3].name, "return");
331548 // FIXME check return. https://bugs.webkit.org/show_bug.cgi?id=163267
332549})();
333550
334551(function OpcodeUnreachable() {
335  const b = (new Builder()).Code().Function().Unreachable().End().End();
 552 const b = (new Builder()).Type().End().Code().Function().Unreachable().End().End();
336553 const j = JSON.parse(b.json());
337  assert.eq(j.section[0].data[0].code.length, 2);
338  assert.eq(j.section[0].data[0].code[0].name, "unreachable");
 554 assert.eq(j.section[1].data[0].code.length, 2);
 555 assert.eq(j.section[1].data[0].code[0].name, "unreachable");
339556})();
340557
341558(function OpcodeUnreachableCombinations() {
342  (new Builder()).Code().Function().Nop().Unreachable().End().End();
343  (new Builder()).Code().Function().Unreachable().Nop().End().End();
344  (new Builder()).Code().Function().Return().Unreachable().End().End();
345  (new Builder()).Code().Function().Unreachable().Return().End().End();
346  (new Builder()).Code().Function().Call(0).Unreachable().End().End();
347  (new Builder()).Code().Function().Unreachable().Call(0).End().End();
 559 (new Builder()).Type().End().Code().Function().Nop().Unreachable().End().End().json();
 560 (new Builder()).Type().End().Code().Function().Unreachable().Nop().End().End().json();
 561 (new Builder()).Type().End().Code().Function().Return().Unreachable().End().End().json();
 562 (new Builder()).Type().End().Code().Function().Unreachable().Return().End().End().json();
 563 (new Builder()).Type().End().Code().Function().Call(0).Unreachable().End().End().json();
 564 (new Builder()).Type().End().Code().Function().Unreachable().Call(0).End().End().json();
348565})();
349566
350567(function OpcodeSelect() {
351  const b = (new Builder()).Code().Function()
 568 const b = (new Builder()).Type().End().Code().Function()
352569 .I32Const(1).I32Const(2).I32Const(0)
353570 .Select()
354571 .Return()
355572 .End()
356573 .End();
357574 const j = JSON.parse(b.json());
358  assert.eq(j.section[0].data[0].code.length, 6);
359  assert.eq(j.section[0].data[0].code[3].name, "select");
 575 assert.eq(j.section[1].data[0].code.length, 6);
 576 assert.eq(j.section[1].data[0].code[3].name, "select");
360577})();
361578
362579// FIXME test type mismatch with select. https://bugs.webkit.org/show_bug.cgi?id=163267

JSTests/wasm/self-test/test_BuilderWebAssembly.js

@@import Builder from '../Builder.js';
3030 ["00000000 00 61 73 6d 0c 00 00 00 00 0f 0a 4f 00 48 00 48 |·asm·······O·H·H|",
3131 "00000010 00 41 00 49 00 de ad c0 fe |·A·I····· |"].join("\n"));
3232})();
33 
34 (function Basic() {
35  const bin = (new Builder())
36  .Code()
37  .Function()
38  .Nop()
39  .Nop()
40  .End()
41  .End()
42  .WebAssembly();
43  assert.eq(bin.hexdump().trim(),
44  "00000000 00 61 73 6d 0c 00 00 00 0a 06 01 04 00 0a 0a 0f |·asm············|");
45 })();

Source/JavaScriptCore/CMakeLists.txt

@@else ()
11321132 )
11331133endif ()
11341134
 1135# WebAssembly generator
 1136
 1137macro(GENERATE_PYTHON _generator _input _output)
 1138 add_custom_command(
 1139 OUTPUT ${_output}
 1140 MAIN_DEPENDENCY ${_generator}
 1141 DEPENDS ${_input}
 1142 COMMAND ${PYTHON_EXECUTABLE} ${_generator} ${_input} ${_output}
 1143 VERBATIM)
 1144 list(APPEND JavaScriptCore_HEADERS ${_output})
 1145 ADD_SOURCE_DEPENDENCIES(${_input} ${_output})
 1146endmacro()
 1147GENERATE_PYTHON(${CMAKE_CURRENT_SOURCE_DIR}/wasm/generateWasmOpsHeader.py ${CMAKE_CURRENT_SOURCE_DIR}/wasm/wasm.json ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/WasmOps.h)
 1148GENERATE_PYTHON(${CMAKE_CURRENT_SOURCE_DIR}/wasm/generateWasmValidateInlinesHeader.py ${CMAKE_CURRENT_SOURCE_DIR}/wasm/wasm.json ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/WasmValidateInlines.h)
 1149
 1150# LUT generator
 1151
11351152set(HASH_LUT_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/create_hash_table)
11361153macro(GENERATE_HASH_LUT _input _output)
11371154 add_custom_command(

Source/JavaScriptCore/ChangeLog

 12016-11-02 JF Bastien <jfbastien@apple.com>
 2
 3 WebAssembly JS API: implement more sections
 4
 5 On the JSC side:
 6
 7 - Put in parser stubs for all WebAssembly sections.
 8 - Parse Import, Export sections.
 9 - Use tryReserveCapacity instead of reserve, and bail out of the parser if it fails. This prevents the parser from bringing everything down when faced with a malicious input.
 10 - Encapsulate all parsed module information into its own structure, making it easier to pass around (from parser to Plan to Module to Instance).
 11 - Create WasmFormat.cpp to hold parsed module information's dtor to avoid including WasmMemory.h needlessly.
 12 - Remove all remainders of polyfill-prototype-1, and update license.
 13 - Add missing WasmOps.h and WasmValidateInlines.h auto-generation for cmake build.
 14
 15 On the Builder.js testing side:
 16
 17 - Implement Type, Import (function only), Export (function only) sections.
 18 - Check section order and uniqueness.
 19 - Optionally auto-generate the Type section from subsequent Export / Import / Code entries.
 20 - Allow re-exporting an import.
 21
 22 WebAssembly JS API: Module should decode strings
 23 https://bugs.webkit.org/show_bug.cgi?id=164023
 24
 25 Reviewed by NOBODY (OOPS!).
 26
 27 * CMakeLists.txt: missing auto-genration
 28 * JavaScriptCore.xcodeproj/project.pbxproj: merge conflict
 29 * testWasm.cpp: update for API changes, no functional change
 30 (checkPlan):
 31 (runWasmTests):
 32 * wasm/WasmFormat.cpp: add a dtor which requires extra headers which I'd rather not include in WasmFormat.h
 33 (JSC::Wasm::ModuleInformation::~ModuleInformation):
 34 * wasm/WasmFormat.h: Add External, Import, Functioninformation, Export, ModuleInformation, CompiledFunction, and remove obsolete stuff which was a holdover from the first implementation (all that code is now gone, so remove its license)
 35 (JSC::Wasm::External::isValid):
 36 * wasm/WasmModuleParser.cpp: simplify some, make names consistent with the WebAssembly section names, check memory allocations so they can fail early
 37 (JSC::Wasm::ModuleParser::parse):
 38 (JSC::Wasm::ModuleParser::parseType):
 39 (JSC::Wasm::ModuleParser::parseImport):
 40 (JSC::Wasm::ModuleParser::parseFunction):
 41 (JSC::Wasm::ModuleParser::parseTable):
 42 (JSC::Wasm::ModuleParser::parseMemory):
 43 (JSC::Wasm::ModuleParser::parseGlobal):
 44 (JSC::Wasm::ModuleParser::parseExport):
 45 (JSC::Wasm::ModuleParser::parseStart):
 46 (JSC::Wasm::ModuleParser::parseElement):
 47 (JSC::Wasm::ModuleParser::parseCode): avoid overflow through function size.
 48 (JSC::Wasm::ModuleParser::parseData):
 49 * wasm/WasmModuleParser.h:
 50 (JSC::Wasm::ModuleParser::moduleInformation):
 51 * wasm/WasmParser.h:
 52 (JSC::Wasm::Parser::consumeUTF8String): add as required by spec
 53 (JSC::Wasm::Parser::parseExternalKind): add as per spec
 54 * wasm/WasmPlan.cpp:
 55 (JSC::Wasm::Plan::Plan): fix some ownership, improve some error messages
 56 * wasm/WasmPlan.h: fix some ownership
 57 (JSC::Wasm::Plan::getModuleInformation):
 58 (JSC::Wasm::Plan::getMemory):
 59 (JSC::Wasm::Plan::compiledFunctionCount):
 60 (JSC::Wasm::Plan::compiledFunction):
 61 (JSC::Wasm::Plan::getCompiledFunctions):
 62 * wasm/WasmSections.h: macroize with description, so that error messages are super pretty. This could be auto-generated.
 63 * wasm/js/JSWebAssemblyModule.cpp:
 64 (JSC::JSWebAssemblyModule::create): take module information
 65 (JSC::JSWebAssemblyModule::JSWebAssemblyModule): ditto
 66 * wasm/js/JSWebAssemblyModule.h:
 67 (JSC::JSWebAssemblyModule::moduleInformation):
 68 * wasm/js/WebAssemblyInstanceConstructor.cpp:
 69 (JSC::constructJSWebAssemblyInstance): check that modules with imports are instantiated with an import object, as per spec. This needs to be tested.
 70 * wasm/js/WebAssemblyMemoryConstructor.cpp:
 71 (JSC::constructJSWebAssemblyMemory):
 72 * wasm/js/WebAssemblyModuleConstructor.cpp:
 73 (JSC::constructJSWebAssemblyModule):
 74 * wasm/js/WebAssemblyTableConstructor.cpp:
 75 (JSC::constructJSWebAssemblyTable):
 76
1772016-11-02 Geoffrey Garen <ggaren@apple.com>
278
379 One file per class for CodeBlock.h/.cpp

Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

12781278 53FD04D41D7AB291003287D3 /* WasmCallingConvention.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */; };
12791279 53FF7F991DBFCD9000A26CCC /* WasmValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */; };
12801280 53FF7F9B1DBFD2B900A26CCC /* WasmValidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */; };
1281  53FF7F9D1DC00DB100A26CCC /* WasmFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */; };
12821281 5B70CFDE1DB69E6600EC23F9 /* JSAsyncFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */; };
12831282 5B70CFDF1DB69E6600EC23F9 /* JSAsyncFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */; };
12841283 5B70CFE01DB69E6600EC23F9 /* AsyncFunctionPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B70CFDA1DB69E5C00EC23F9 /* AsyncFunctionPrototype.h */; };

19731972 AD2FCC2D1DB838FD00B3E736 /* WebAssemblyPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = AD2FCC271DB838C400B3E736 /* WebAssemblyPrototype.h */; };
19741973 AD2FCC301DB83D4900B3E736 /* JSWebAssembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCC2E1DB839F700B3E736 /* JSWebAssembly.cpp */; };
19751974 AD2FCC311DB83D4900B3E736 /* JSWebAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = AD2FCC2F1DB839F700B3E736 /* JSWebAssembly.h */; };
 1975 AD2FCC331DC4045400B3E736 /* WasmFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */; };
19761976 AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
19771977 ADDB1F6318D77DBE009B58A8 /* OpaqueRootSet.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
19781978 ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD1CF06816DCAB2D00B97123 /* PropertyTable.cpp */; };

36273627 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmCallingConvention.h; sourceTree = "<group>"; };
36283628 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmValidate.h; sourceTree = "<group>"; };
36293629 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmValidate.cpp; sourceTree = "<group>"; };
3630  53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFormat.cpp; sourceTree = "<group>"; };
36313630 5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAsyncFunction.h; sourceTree = "<group>"; };
36323631 5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAsyncFunction.cpp; sourceTree = "<group>"; };
36333632 5B70CFDA1DB69E5C00EC23F9 /* AsyncFunctionPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AsyncFunctionPrototype.h; sourceTree = "<group>"; };

44044403 AD2FCC271DB838C400B3E736 /* WebAssemblyPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyPrototype.h; path = js/WebAssemblyPrototype.h; sourceTree = "<group>"; };
44054404 AD2FCC2E1DB839F700B3E736 /* JSWebAssembly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebAssembly.cpp; sourceTree = "<group>"; };
44064405 AD2FCC2F1DB839F700B3E736 /* JSWebAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebAssembly.h; sourceTree = "<group>"; };
 4406 AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFormat.cpp; sourceTree = "<group>"; };
44074407 AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCMapInlines.h; sourceTree = "<group>"; };
44084408 ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueRootSet.h; sourceTree = "<group>"; };
44094409 B59F89371891AD3300D5CCDC /* UnlinkedInstructionStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnlinkedInstructionStream.h; sourceTree = "<group>"; };

59195919 53F40E921D5A4AB30099A1B6 /* WasmB3IRGenerator.h */,
59205920 53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */,
59215921 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */,
5922  53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */,
 5922 AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */,
59235923 7BC547D21B69599B00959B58 /* WasmFormat.h */,
59245924 53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */,
59255925 535557151D9DFA32006D583B /* WasmMemory.cpp */,

98079807 0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */,
98089808 0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */,
98099809 0FF8BDEA1AD4CF7100DFE884 /* InferredValue.cpp in Sources */,
 9810 AD2FCC331DC4045400B3E736 /* WasmFormat.cpp in Sources */,
98109811 9E729407190F01A5001A91B5 /* InitializeThreading.cpp in Sources */,
98119812 A513E5B7185B8BD3007E95AD /* InjectedScript.cpp in Sources */,
98129813 A514B2C2185A684400F3C7CB /* InjectedScriptBase.cpp in Sources */,

Source/JavaScriptCore/testWasm.cpp

@@static void checkPlan(Plan& plan, unsigned expectedNumberOfFunctions)
276276 CRASH();
277277 }
278278
279  if (plan.resultSize() != expectedNumberOfFunctions) {
 279 if (plan.compiledFunctionCount() != expectedNumberOfFunctions) {
280280 dataLogLn("Incorrect number of functions");
281281 CRASH();
282282 }
283283
284284 for (unsigned i = 0; i < expectedNumberOfFunctions; ++i) {
285  if (!plan.result(i)) {
 285 if (!plan.compiledFunction(i)) {
286286 dataLogLn("Function at index, " , i, " failed to compile correctly");
287287 CRASH();
288288 }

@@static void runWasmTests()
314314 checkPlan(plan, 2);
315315
316316 // Test this doesn't crash.
317  CHECK(isIdentical(invoke<float>(*plan.result(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
318  CHECK(isIdentical(invoke<float>(*plan.result(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
319  CHECK(isIdentical(invoke<float>(*plan.result(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
320  CHECK(isIdentical(invoke<float>(*plan.result(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
 317 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
 318 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
 319 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));
 320 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));
321321 }
322322
323323 {

@@static void runWasmTests()
340340 checkPlan(plan, 2);
341341
342342 // Test this doesn't crash.
343  CHECK(isIdentical(invoke<float>(*plan.result(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
344  CHECK(isIdentical(invoke<float>(*plan.result(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
345  CHECK(isIdentical(invoke<float>(*plan.result(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
346  CHECK(isIdentical(invoke<float>(*plan.result(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
 343 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
 344 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
 345 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));
 346 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));
347347 }
348348
349349 {

@@static void runWasmTests()
371371 checkPlan(plan, 2);
372372
373373 // Test this doesn't crash.
374  CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(0) }), 0);
375  CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(100) }), 1200);
376  CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(1) }), 12);
377  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(12) }), 78);
378  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(100) }), 166);
 374 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0) }), 0);
 375 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100) }), 1200);
 376 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1) }), 12);
 377 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(12) }), 78);
 378 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2), box(3), box(4), box(5), box(6), box(7), box(8), box(9), box(10), box(11), box(100) }), 166);
379379 }
380380
381381 {

@@static void runWasmTests()
402402 checkPlan(plan, 1);
403403
404404 // Test this doesn't crash.
405  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 1);
406  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 1);
407  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2) }), 2);
408  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(4) }), 24);
 405 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 1);
 406 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
 407 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2) }), 2);
 408 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(4) }), 24);
409409 }
410410
411411 {

@@static void runWasmTests()
425425 };
426426
427427 Plan plan(*vm, vector);
428  if (plan.resultSize() != 2 || !plan.result(0) || !plan.result(1)) {
 428 if (plan.compiledFunctionCount() != 2 || !plan.compiledFunction(0) || !plan.compiledFunction(1)) {
429429 dataLogLn("Module failed to compile correctly.");
430430 CRASH();
431431 }
432432
433433 // Test this doesn't crash.
434  CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(0), box(0) }), 0);
435  CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(100), box(0) }), 100);
436  CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(1), box(15) }), 16);
437  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
438  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100) }), 200);
439  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 2);
 434 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0), box(0) }), 0);
 435 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100), box(0) }), 100);
 436 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1), box(15) }), 16);
 437 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
 438 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 200);
 439 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 2);
440440 }
441441
442442 {

@@static void runWasmTests()
459459 checkPlan(plan, 2);
460460
461461 // Test this doesn't crash.
462  CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(0) }), 0);
463  CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(100) }), 100);
464  CHECK_EQ(invoke<int>(*plan.result(1)->jsEntryPoint, { box(1) }), 1);
465  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
466  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100) }), 100);
467  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 1);
 462 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0) }), 0);
 463 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100) }), 100);
 464 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1) }), 1);
 465 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
 466 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100);
 467 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
468468 }
469469
470470 {

@@static void runWasmTests()
488488 checkPlan(plan, 1);
489489
490490 // Test this doesn't crash.
491  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
492  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
493  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
 491 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
 492 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
 493 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
494494 }
495495
496496 {

@@static void runWasmTests()
515515 checkPlan(plan, 1);
516516
517517 // Test this doesn't crash.
518  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
519  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
520  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
 518 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
 519 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
 520 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
521521 }
522522
523523 {

@@static void runWasmTests()
550550
551551 Plan plan(*vm, vector);
552552 checkPlan(plan, 1);
553  ASSERT(plan.memory()->size());
 553 ASSERT(plan.getMemory()->size());
554554
555555 // Test this doesn't crash.
556556 unsigned length = 5;
557557 unsigned offset = sizeof(uint32_t);
558  uint32_t* memory = static_cast<uint32_t*>(plan.memory()->memory());
559  invoke<void>(*plan.result(0)->jsEntryPoint, { box(100), box(offset), box(length) });
 558 uint32_t* memory = static_cast<uint32_t*>(plan.getMemory()->memory());
 559 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
560560 offset /= sizeof(uint32_t);
561561 CHECK_EQ(memory[offset - 1], 0u);
562562 CHECK_EQ(memory[offset + length], 0u);

@@static void runWasmTests()
565565
566566 length = 10;
567567 offset = 5 * sizeof(uint32_t);
568  invoke<void>(*plan.result(0)->jsEntryPoint, { box(5), box(offset), box(length) });
 568 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
569569 offset /= sizeof(uint32_t);
570570 CHECK_EQ(memory[offset - 1], 100u);
571571 CHECK_EQ(memory[offset + length], 0u);

@@static void runWasmTests()
602602
603603 Plan plan(*vm, vector);
604604 checkPlan(plan, 1);
605  ASSERT(plan.memory()->size());
 605 ASSERT(plan.getMemory()->size());
606606
607607 // Test this doesn't crash.
608608 unsigned length = 5;
609609 unsigned offset = 1;
610  uint8_t* memory = static_cast<uint8_t*>(plan.memory()->memory());
611  invoke<void>(*plan.result(0)->jsEntryPoint, { box(100), box(offset), box(length) });
 610 uint8_t* memory = static_cast<uint8_t*>(plan.getMemory()->memory());
 611 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
612612 CHECK_EQ(memory[offset - 1], 0u);
613613 CHECK_EQ(memory[offset + length], 0u);
614614 for (unsigned i = 0; i < length; ++i)

@@static void runWasmTests()
616616
617617 length = 10;
618618 offset = 5;
619  invoke<void>(*plan.result(0)->jsEntryPoint, { box(5), box(offset), box(length) });
 619 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
620620 CHECK_EQ(memory[offset - 1], 100u);
621621 CHECK_EQ(memory[offset + length], 0u);
622622 for (unsigned i = 0; i < length; ++i)

@@static void runWasmTests()
643643
644644 Plan plan(*vm, vector);
645645 checkPlan(plan, 1);
646  ASSERT(plan.memory()->size());
 646 ASSERT(plan.getMemory()->size());
647647
648648 // Test this doesn't crash.
649  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
650  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
651  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
 649 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
 650 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
 651 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
652652 }
653653
654654 {

@@static void runWasmTests()
673673 checkPlan(plan, 1);
674674
675675 // Test this doesn't crash.
676  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
677  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100) }), 100);
678  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 1);
 676 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
 677 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100);
 678 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
679679 }
680680
681681 {

@@static void runWasmTests()
700700 checkPlan(plan, 1);
701701
702702 // Test this doesn't crash.
703  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
704  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
705  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
706  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(-12), box(plan.memory()->size() - sizeof(uint64_t)) }), -12);
 703 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
 704 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
 705 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
 706 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-12), box(plan.getMemory()->size() - sizeof(uint64_t)) }), -12);
707707 }
708708
709709 {

@@static void runWasmTests()
728728 checkPlan(plan, 1);
729729
730730 // Test this doesn't crash.
731  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
732  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
733  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
 731 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
 732 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
 733 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
734734 }
735735
736736 {

@@static void runWasmTests()
763763
764764 Plan plan(*vm, vector);
765765 checkPlan(plan, 1);
766  ASSERT(plan.memory()->size());
 766 ASSERT(plan.getMemory()->size());
767767
768768 // Test this doesn't crash.
769769 unsigned length = 5;
770770 unsigned offset = sizeof(uint32_t);
771  uint32_t* memory = static_cast<uint32_t*>(plan.memory()->memory());
772  invoke<void>(*plan.result(0)->jsEntryPoint, { box(100), box(offset), box(length) });
 771 uint32_t* memory = static_cast<uint32_t*>(plan.getMemory()->memory());
 772 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
773773 offset /= sizeof(uint32_t);
774774 CHECK_EQ(memory[offset - 1], 0u);
775775 CHECK_EQ(memory[offset + length], 0u);

@@static void runWasmTests()
778778
779779 length = 10;
780780 offset = 5 * sizeof(uint32_t);
781  invoke<void>(*plan.result(0)->jsEntryPoint, { box(5), box(offset), box(length) });
 781 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
782782 offset /= sizeof(uint32_t);
783783 CHECK_EQ(memory[offset - 1], 100u);
784784 CHECK_EQ(memory[offset + length], 0u);

@@static void runWasmTests()
815815
816816 Plan plan(*vm, vector);
817817 checkPlan(plan, 1);
818  ASSERT(plan.memory()->size());
 818 ASSERT(plan.getMemory()->size());
819819
820820 // Test this doesn't crash.
821821 unsigned length = 5;
822822 unsigned offset = 1;
823  uint8_t* memory = static_cast<uint8_t*>(plan.memory()->memory());
824  invoke<void>(*plan.result(0)->jsEntryPoint, { box(100), box(offset), box(length) });
 823 uint8_t* memory = static_cast<uint8_t*>(plan.getMemory()->memory());
 824 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) });
825825 CHECK_EQ(memory[offset - 1], 0u);
826826 CHECK_EQ(memory[offset + length], 0u);
827827 for (unsigned i = 0; i < length; ++i)

@@static void runWasmTests()
829829
830830 length = 10;
831831 offset = 5;
832  invoke<void>(*plan.result(0)->jsEntryPoint, { box(5), box(offset), box(length) });
 832 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) });
833833 CHECK_EQ(memory[offset - 1], 100u);
834834 CHECK_EQ(memory[offset + length], 0u);
835835 for (unsigned i = 0; i < length; ++i)

@@static void runWasmTests()
856856
857857 Plan plan(*vm, vector);
858858 checkPlan(plan, 1);
859  ASSERT(plan.memory()->size());
 859 ASSERT(plan.getMemory()->size());
860860
861861 // Test this doesn't crash.
862  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(10) }), 0);
863  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(2) }), 100);
864  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(100) }), 1);
 862 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0);
 863 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100);
 864 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1);
865865 }
866866
867867 {

@@static void runWasmTests()
886886 checkPlan(plan, 1);
887887
888888 // Test this doesn't crash.
889  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
890  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100) }), 100);
891  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 1);
 889 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
 890 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100);
 891 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
892892 }
893893
894894 {

@@static void runWasmTests()
913913 checkPlan(plan, 1);
914914
915915 // Test this doesn't crash.
916  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(1) }), 1);
917  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(0) }), 1);
918  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(1) }), 1);
919  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2) }), 1);
920  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(2) }), 0);
921  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(1) }), 0);
922  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(6) }), 1);
923  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(6) }), 1);
 916 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
 917 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 1);
 918 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 1);
 919 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
 920 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
 921 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
 922 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
 923 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 1);
924924 }
925925
926926 {

@@static void runWasmTests()
951951 checkPlan(plan, 1);
952952
953953 // Test this doesn't crash.
954  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(1) }), 1);
955  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(0) }), 0);
956  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(1) }), 0);
957  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2) }), 1);
958  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(2) }), 0);
959  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(1) }), 0);
960  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(6) }), 1);
961  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(6) }), 0);
 954 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
 955 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
 956 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0);
 957 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
 958 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
 959 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
 960 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
 961 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0);
962962 }
963963
964964

@@static void runWasmTests()
975975 checkPlan(plan, 1);
976976
977977 // Test this doesn't crash.
978  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { }), 5);
 978 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 5);
979979 }
980980
981981

@@static void runWasmTests()
993993 checkPlan(plan, 1);
994994
995995 // Test this doesn't crash.
996  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { }), 11);
 996 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11);
997997 }
998998
999999 {

@@static void runWasmTests()
10101010 checkPlan(plan, 1);
10111011
10121012 // Test this doesn't crash.
1013  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { }), 11);
 1013 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11);
10141014 }
10151015
10161016 {

@@static void runWasmTests()
10271027 checkPlan(plan, 1);
10281028
10291029 // Test this doesn't crash.
1030  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { }), 11);
 1030 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11);
10311031 }
10321032
10331033 {

@@static void runWasmTests()
10431043 checkPlan(plan, 1);
10441044
10451045 // Test this doesn't crash.
1046  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(1) }), 1);
1047  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(1) }), 101);
1048  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(-1), box(1)}), 0);
1049  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());
 1046 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
 1047 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(1) }), 101);
 1048 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-1), box(1)}), 0);
 1049 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());
10501050 }
10511051
10521052 {

@@static void runWasmTests()
10691069 checkPlan(plan, 1);
10701070
10711071 // Test this doesn't crash.
1072  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
1073  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(10) }), 10);
 1072 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
 1073 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(10) }), 10);
10741074 }
10751075
10761076 {

@@static void runWasmTests()
11021102 checkPlan(plan, 1);
11031103
11041104 // Test this doesn't crash.
1105  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0) }), 0);
1106  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1) }), 1);
1107  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2)}), 3);
1108  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100) }), 5050);
 1105 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0);
 1106 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1);
 1107 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2)}), 3);
 1108 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 5050);
11091109 }
11101110
11111111 {

@@static void runWasmTests()
11431143 checkPlan(plan, 1);
11441144
11451145 // Test this doesn't crash.
1146  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(1) }), 0);
1147  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(0) }), 0);
1148  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(1) }), 2);
1149  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2) }), 2);
1150  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(2) }), 4);
1151  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(6) }), 12);
1152  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(6) }), 600);
1153  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(100) }), 10000);
 1146 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 0);
 1147 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
 1148 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 2);
 1149 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 2);
 1150 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 4);
 1151 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 12);
 1152 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 600);
 1153 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(100) }), 10000);
11541154 }
11551155
11561156 {

@@static void runWasmTests()
11931193 checkPlan(plan, 1);
11941194
11951195 // Test this doesn't crash.
1196  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(0), box(1) }), 1);
1197  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(0) }), 0);
1198  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(1) }), 0);
1199  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(2) }), 1);
1200  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(2) }), 0);
1201  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(1), box(1) }), 0);
1202  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(2), box(6) }), 1);
1203  CHECK_EQ(invoke<int>(*plan.result(0)->jsEntryPoint, { box(100), box(6) }), 0);
 1196 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1);
 1197 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0);
 1198 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0);
 1199 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1);
 1200 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0);
 1201 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0);
 1202 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1);
 1203 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0);
12041204 }
12051205
12061206}

Source/JavaScriptCore/wasm/WasmFormat.cpp

2424 */
2525
2626#include "config.h"
 27
2728#include "WasmFormat.h"
2829
2930#if ENABLE(WEBASSEMBLY)
3031
 32#include "WasmMemory.h"
 33
3134namespace JSC { namespace Wasm {
3235
3336const char* toString(Type type)

@@const char* toString(Type type)
4649 }
4750}
4851
 52ModuleInformation::~ModuleInformation() { }
 53
4954} } // namespace JSC::Wasm
5055
51 #endif // ENABLE(B3_JIT)
 56#endif // ENABLE(WEBASSEMBLY)

Source/JavaScriptCore/wasm/WasmFormat.h

2121 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2222 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2323 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * =========================================================================
26  *
27  * Copyright (c) 2015 by the repository authors of
28  * WebAssembly/polyfill-prototype-1.
29  *
30  * Licensed under the Apache License, Version 2.0 (the "License");
31  * you may not use this file except in compliance with the License.
32  * You may obtain a copy of the License at
33  *
34  * http://www.apache.org/licenses/LICENSE-2.0
35  *
36  * Unless required by applicable law or agreed to in writing, software
37  * distributed under the License is distributed on an "AS IS" BASIS,
38  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
39  * See the License for the specific language governing permissions and
40  * limitations under the License.
4124 */
4225
4326#pragma once

@@inline bool isValueType(Type type)
9881}
9982
10083const char* toString(Type);
 84
 85struct External {
 86 enum Kind : uint8_t {
 87 Function = 0,
 88 Table = 1,
 89 Memory = 2,
 90 Global = 3,
 91 };
 92 template<typename Int>
 93 static bool isValid(Int val)
 94 {
 95 switch (val) {
 96 case Function:
 97 case Table:
 98 case Memory:
 99 case Global:
 100 return true;
 101 default:
 102 return false;
 103 }
 104 }
 105
 106 static_assert(Function == 0, "Wasm needs Function to have the value 0");
 107 static_assert(Table == 1, "Wasm needs Table to have the value 1");
 108 static_assert(Memory == 2, "Wasm needs Memory to have the value 2");
 109 static_assert(Global == 3, "Wasm needs Global to have the value 3");
 110};
101111
102112struct Signature {
103113 Type returnType;
104114 Vector<Type> arguments;
105115};
106 
107 struct FunctionImport {
108  String functionName;
 116
 117struct Import {
 118 String module;
 119 String field;
 120 External::Kind kind;
 121 union {
 122 Signature* functionSignature;
 123 // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=164135
 124 // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=164134
 125 // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
 126 };
109127};
110128
111 struct FunctionImportSignature {
112  uint32_t signatureIndex;
113  uint32_t functionImportIndex;
 129struct FunctionInformation {
 130 Signature* signature;
 131 size_t start;
 132 size_t end;
114133};
115134
116 struct FunctionDeclaration {
117  uint32_t signatureIndex;
 135class Memory;
 136
 137struct Export {
 138 String field;
 139 External::Kind kind;
 140 union {
 141 Signature* functionSignature;
 142 // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=164135
 143 // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=164134
 144 // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
 145 };
118146};
119147
120 struct FunctionPointerTable {
121  uint32_t signatureIndex;
122  Vector<uint32_t> functionIndices;
123  Vector<JSFunction*> functions;
124 };
 148struct ModuleInformation {
 149 Vector<Signature> signatures;
 150 Vector<Import> imports;
 151 Vector<FunctionInformation> functions;
 152 std::unique_ptr<Memory> memory;
 153 Vector<Export> exports;
125154
126 struct FunctionInformation {
127  Signature* signature;
128  size_t start;
129  size_t end;
 155 ~ModuleInformation();
130156};
131157
 158struct FunctionCompilation;
 159typedef Vector<std::unique_ptr<FunctionCompilation>> CompiledFunctions;
 160
132161struct UnlinkedCall {
133162 CodeLocationCall callLocation;
134163 size_t functionIndex;

Source/JavaScriptCore/wasm/WasmModuleParser.cpp

2929#if ENABLE(WEBASSEMBLY)
3030
3131#include "WasmFormat.h"
 32#include "WasmMemory.h"
3233#include "WasmOps.h"
3334#include "WasmSections.h"
3435

@@static const bool verbose = false;
4041
4142bool ModuleParser::parse()
4243{
 44 m_module = std::make_unique<ModuleInformation>();
 45
4346 const size_t minSize = 8;
4447 if (length() < minSize) {
4548 m_errorMessage = "Module is " + String::number(length()) + " bytes, expected at least " + String::number(minSize) + " bytes";

@@bool ModuleParser::parse()
111114 auto end = m_offset + sectionLength;
112115
113116 switch (section) {
114 
115  case Sections::Memory: {
116  if (verbose)
117  dataLogLn("Parsing Memory.");
118  if (!parseMemory()) {
119  // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
120  m_errorMessage = "couldn't parse memory";
121  return false;
122  }
123  break;
124  }
125 
126  case Sections::FunctionTypes: {
127  if (verbose)
128  dataLogLn("Parsing types.");
129  if (!parseFunctionTypes()) {
130  // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
131  m_errorMessage = "couldn't parse types";
132  return false;
133  }
134  break;
135  }
136 
137  case Sections::Signatures: {
138  if (verbose)
139  dataLogLn("Parsing function signatures.");
140  if (!parseFunctionSignatures()) {
141  // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
142  m_errorMessage = "couldn't parse function signatures";
143  return false;
144  }
145  break;
146  }
147 
148  case Sections::Definitions: {
149  if (verbose)
150  dataLogLn("Parsing function definitions.");
151  if (!parseFunctionDefinitions()) {
152  // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
153  m_errorMessage = "couldn't parse function definitions";
154  return false;
155  }
156  break;
157  }
158 
159  case Sections::Unknown:
160  // FIXME: Delete this when we support all the sections.
161  default: {
 117 // FIXME improve error message in macro below https://bugs.webkit.org/show_bug.cgi?id=163919
 118#define WASM_SECTION_PARSE(NAME, ID, DESCRIPTION) \
 119 case Sections::NAME: { \
 120 if (verbose) \
 121 dataLogLn("Parsing " DESCRIPTION); \
 122 if (!parse ## NAME()) { \
 123 m_errorMessage = "couldn't parse section " #NAME ": " DESCRIPTION; \
 124 return false; \
 125 } \
 126 } break;
 127 FOR_EACH_WASM_SECTION(WASM_SECTION_PARSE)
 128#undef WASM_SECTION_PARSE
 129
 130 case Sections::Unknown: {
162131 if (verbose)
163132 dataLogLn("Unknown section, skipping.");
164133 // Ignore section's name LEB and bytes: they're already included in sectionLength.

@@bool ModuleParser::parse()
184153 return true;
185154}
186155
187 bool ModuleParser::parseMemory()
188 {
189  uint8_t flags;
190  if (!parseVarUInt1(flags))
191  return false;
192 
193  uint32_t size;
194  if (!parseVarUInt32(size))
195  return false;
196  if (size > maxPageCount)
197  return false;
198 
199  uint32_t capacity = maxPageCount;
200  if (flags) {
201  if (!parseVarUInt32(capacity))
202  return false;
203  if (size > capacity || capacity > maxPageCount)
204  return false;
205  }
206 
207  capacity *= pageSize;
208  size *= pageSize;
209 
210  Vector<unsigned> pinnedSizes = { 0 };
211  m_memory = std::make_unique<Memory>(size, capacity, pinnedSizes);
212  return m_memory->memory();
213 }
214 
215 bool ModuleParser::parseFunctionTypes()
 156bool ModuleParser::parseType()
216157{
217158 uint32_t count;
218159 if (!parseVarUInt32(count))
219160 return false;
220 
221161 if (verbose)
222162 dataLogLn("count: ", count);
223 
224  m_signatures.resize(count);
225 
 163 if (!m_module->signatures.tryReserveCapacity(count))
 164 return false;
 165
226166 for (uint32_t i = 0; i < count; ++i) {
227  uint8_t type;
228  if (!parseUInt7(type))
 167 int8_t type;
 168 if (!parseInt7(type))
229169 return false;
230  if (type != 0x40) // Function type constant.
 170 if (type != -0x20) // Function type constant.
231171 return false;
232 
 172
233173 if (verbose)
234174 dataLogLn("Got function type.");
235 
 175
236176 uint32_t argumentCount;
237177 if (!parseVarUInt32(argumentCount))
238178 return false;
239 
 179
240180 if (verbose)
241181 dataLogLn("argumentCount: ", argumentCount);
242 
 182
243183 Vector<Type> argumentTypes;
244  argumentTypes.resize(argumentCount);
 184 if (!argumentTypes.tryReserveCapacity(argumentCount))
 185 return false;
245186
246  for (unsigned i = 0; i < argumentCount; ++i) {
247  if (!parseUInt7(type) || !isValueType(static_cast<Type>(type)))
 187 for (unsigned i = 0; i != argumentCount; ++i) {
 188 uint8_t argumentType;
 189 if (!parseUInt7(argumentType) || !isValueType(static_cast<Type>(argumentType)))
248190 return false;
249  argumentTypes[i] = static_cast<Type>(type);
 191 argumentTypes.uncheckedAppend(static_cast<Type>(argumentType));
250192 }
251193
252  if (!parseVarUInt1(type))
 194 uint8_t returnCount;
 195 if (!parseVarUInt1(returnCount))
253196 return false;
254197 Type returnType;
255 
 198
256199 if (verbose)
257  dataLogLn(type);
258 
259  if (type) {
 200 dataLogLn(returnCount);
 201
 202 if (returnCount) {
260203 Type value;
261204 if (!parseValueType(value))
262205 return false;

@@bool ModuleParser::parseFunctionTypes()
264207 } else
265208 returnType = Type::Void;
266209
267  m_signatures[i] = { returnType, WTFMove(argumentTypes) };
 210 m_module->signatures.uncheckedAppend({ returnType, WTFMove(argumentTypes) });
268211 }
269212 return true;
270213}
271214
272 bool ModuleParser::parseFunctionSignatures()
 215bool ModuleParser::parseImport()
273216{
274  uint32_t count;
275  if (!parseVarUInt32(count))
 217 uint32_t importCount;
 218 if (!parseVarUInt32(importCount))
 219 return false;
 220 if (!m_module->imports.tryReserveCapacity(importCount))
276221 return false;
277222
278  m_functions.resize(count);
 223 for (uint32_t importNumber = 0; importNumber != importCount; ++importNumber) {
 224 Import i;
 225 uint32_t moduleLen;
 226 uint32_t fieldLen;
 227 if (!parseVarUInt32(moduleLen))
 228 return false;
 229 if (!consumeUTF8String(i.module, moduleLen))
 230 return false;
 231 if (!parseVarUInt32(fieldLen))
 232 return false;
 233 if (!consumeUTF8String(i.field, fieldLen))
 234 return false;
 235 if (!parseExternalKind(i.kind))
 236 return false;
 237 switch (i.kind) {
 238 case External::Function: {
 239 uint32_t functionSignatureIndex;
 240 if (!parseVarUInt32(functionSignatureIndex))
 241 return false;
 242 if (functionSignatureIndex > m_module->signatures.size())
 243 return false;
 244 i.functionSignature = &m_module->signatures[functionSignatureIndex];
 245 } break;
 246 case External::Table:
 247 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135
 248 break;
 249 case External::Memory:
 250 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164134
 251 break;
 252 case External::Global:
 253 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
 254 // In the MVP, only immutable global variables can be imported.
 255 break;
 256 }
279257
280  for (uint32_t i = 0; i < count; ++i) {
 258 m_module->imports.uncheckedAppend(i);
 259 }
 260
 261 return true;
 262}
 263
 264bool ModuleParser::parseFunction()
 265{
 266 uint32_t count;
 267 if (!parseVarUInt32(count))
 268 return false;
 269 if (!m_module->functions.tryReserveCapacity(count))
 270 return false;
 271
 272 for (uint32_t i = 0; i != count; ++i) {
281273 uint32_t typeNumber;
282274 if (!parseVarUInt32(typeNumber))
283275 return false;
284 
285  if (typeNumber >= m_signatures.size())
 276
 277 if (typeNumber >= m_module->signatures.size())
286278 return false;
287279
288  m_functions[i].signature = &m_signatures[typeNumber];
 280 m_module->functions.uncheckedAppend({ &m_module->signatures[typeNumber], 0, 0 });
 281 }
 282
 283 return true;
 284}
 285
 286bool ModuleParser::parseTable()
 287{
 288 // FIXME
 289 return true;
 290}
 291
 292bool ModuleParser::parseMemory()
 293{
 294 uint8_t flags;
 295 if (!parseVarUInt1(flags))
 296 return false;
 297
 298 uint32_t size;
 299 if (!parseVarUInt32(size))
 300 return false;
 301 if (size > maxPageCount)
 302 return false;
 303
 304 uint32_t capacity = maxPageCount;
 305 if (flags) {
 306 if (!parseVarUInt32(capacity))
 307 return false;
 308 if (size > capacity || capacity > maxPageCount)
 309 return false;
289310 }
290311
 312 capacity *= pageSize;
 313 size *= pageSize;
 314
 315 Vector<unsigned> pinnedSizes = { 0 };
 316 m_module->memory = std::make_unique<Memory>(size, capacity, pinnedSizes);
 317 return m_module->memory->memory();
 318}
 319
 320bool ModuleParser::parseGlobal()
 321{
 322 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
 323 return true;
 324}
 325
 326bool ModuleParser::parseExport()
 327{
 328 uint32_t exportCount;
 329 if (!parseVarUInt32(exportCount))
 330 return false;
 331 if (!m_module->exports.tryReserveCapacity(exportCount))
 332 return false;
 333
 334 for (uint32_t exportNumber = 0; exportNumber != exportCount; ++exportNumber) {
 335 Export e;
 336 uint32_t fieldLen;
 337 if (!parseVarUInt32(fieldLen))
 338 return false;
 339 if (!consumeUTF8String(e.field, fieldLen))
 340 return false;
 341 if (!parseExternalKind(e.kind))
 342 return false;
 343 switch (e.kind) {
 344 case External::Function: {
 345 uint32_t functionSignatureIndex;
 346 if (!parseVarUInt32(functionSignatureIndex))
 347 return false;
 348 if (functionSignatureIndex > m_module->signatures.size())
 349 return false;
 350 e.functionSignature = &m_module->signatures[functionSignatureIndex];
 351 } break;
 352 case External::Table:
 353 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135
 354 break;
 355 case External::Memory:
 356 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164134
 357 break;
 358 case External::Global:
 359 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
 360 // In the MVP, only immutable global variables can be exported.
 361 break;
 362 }
 363
 364 m_module->exports.uncheckedAppend(e);
 365 }
 366
 367 return true;
 368}
 369
 370bool ModuleParser::parseStart()
 371{
 372 // FIXME
 373 return true;
 374}
 375
 376bool ModuleParser::parseElement()
 377{
 378 // FIXME
291379 return true;
292380}
293381
294 bool ModuleParser::parseFunctionDefinitions()
 382bool ModuleParser::parseCode()
295383{
296384 uint32_t count;
297385 if (!parseVarUInt32(count))
298386 return false;
299387
300  if (count != m_functions.size())
 388 if (count != m_module->functions.size())
301389 return false;
302390
303  for (uint32_t i = 0; i < count; ++i) {
 391 for (uint32_t i = 0; i != count; ++i) {
304392 uint32_t functionSize;
305393 if (!parseVarUInt32(functionSize))
306394 return false;
 395 if (functionSize > length() || functionSize > length() - m_offset)
 396 return false;
307397
308  FunctionInformation& info = m_functions[i];
 398 FunctionInformation& info = m_module->functions[i];
309399 info.start = m_offset;
310400 info.end = m_offset + functionSize;
311401 m_offset = info.end;

@@bool ModuleParser::parseFunctionDefinitions()
313403
314404 return true;
315405}
 406
 407bool ModuleParser::parseData()
 408{
 409 // FIXME
 410 return true;
 411}
316412
317413} } // namespace JSC::Wasm
318414

Source/JavaScriptCore/wasm/WasmModuleParser.h

2727
2828#if ENABLE(WEBASSEMBLY)
2929
30 #include "WasmMemory.h"
 30#include "WasmFormat.h"
3131#include "WasmOps.h"
3232#include "WasmParser.h"
3333#include <wtf/Vector.h>

@@public:
5656 return m_errorMessage;
5757 }
5858
59  const Vector<FunctionInformation>& functionInformation() const
 59 std::unique_ptr<ModuleInformation>& moduleInformation()
6060 {
6161 RELEASE_ASSERT(!failed());
62  return m_functions;
63  }
64  std::unique_ptr<Memory>& memory()
65  {
66  RELEASE_ASSERT(!failed());
67  return m_memory;
 62 return m_module;
6863 }
6964
7065private:
71  bool WARN_UNUSED_RETURN parseMemory();
72  bool WARN_UNUSED_RETURN parseFunctionTypes();
73  bool WARN_UNUSED_RETURN parseFunctionSignatures();
74  bool WARN_UNUSED_RETURN parseFunctionDefinitions();
75  bool WARN_UNUSED_RETURN parseFunctionDefinition(uint32_t number);
 66#define WASM_SECTION_DECLARE_PARSER(NAME, ID, DESCRIPTION) bool WARN_UNUSED_RETURN parse ## NAME();
 67 FOR_EACH_WASM_SECTION(WASM_SECTION_DECLARE_PARSER)
 68#undef WASM_SECTION_DECLARE_PARSER
7669
77  Vector<FunctionInformation> m_functions;
78  Vector<Signature> m_signatures;
79  std::unique_ptr<Memory> m_memory;
 70 std::unique_ptr<ModuleInformation> m_module;
8071 bool m_failed { true };
8172 String m_errorMessage;
8273};

Source/JavaScriptCore/wasm/WasmParser.h

3333#include "WasmOps.h"
3434#include "WasmSections.h"
3535#include <wtf/LEBDecoder.h>
 36#include <wtf/StdLibExtras.h>
 37#include <wtf/text/WTFString.h>
3638
3739namespace JSC { namespace Wasm {
3840

@@protected:
4244
4345 bool WARN_UNUSED_RETURN consumeCharacter(char);
4446 bool WARN_UNUSED_RETURN consumeString(const char*);
 47 bool WARN_UNUSED_RETURN consumeUTF8String(String &, size_t);
4548
4649 bool WARN_UNUSED_RETURN parseVarUInt1(uint8_t& result);
 50 bool WARN_UNUSED_RETURN parseInt7(int8_t& result);
4751 bool WARN_UNUSED_RETURN parseUInt7(uint8_t& result);
4852 bool WARN_UNUSED_RETURN parseUInt32(uint32_t& result);
4953 bool WARN_UNUSED_RETURN parseVarUInt32(uint32_t& result) { return WTF::LEBDecoder::decodeUInt32(m_source, m_sourceLength, m_offset, result); }
5054 bool WARN_UNUSED_RETURN parseVarUInt64(uint64_t& result) { return WTF::LEBDecoder::decodeUInt64(m_source, m_sourceLength, m_offset, result); }
5155
5256 bool WARN_UNUSED_RETURN parseValueType(Type& result);
 57 bool WARN_UNUSED_RETURN parseExternalKind(External::Kind& result);
5358
5459 const uint8_t* source() const { return m_source; }
5560 size_t length() const { return m_sourceLength; }

@@ALWAYS_INLINE bool Parser::consumeString(const char* str)
9297 return true;
9398}
9499
 100ALWAYS_INLINE bool Parser::consumeUTF8String(String &result, size_t stringLength)
 101{
 102 if (stringLength == 0) {
 103 result = String();
 104 return true;
 105 }
 106 if (length() < stringLength || m_offset > length() - stringLength)
 107 return false;
 108 result = String::fromUTF8(static_cast<const LChar*>(&source()[m_offset]), stringLength);
 109 m_offset += stringLength;
 110 if (result.isEmpty())
 111 return false;
 112 return true;
 113}
 114
95115ALWAYS_INLINE bool Parser::parseUInt32(uint32_t& result)
96116{
97117 if (length() < 4 || m_offset > length() - 4)

@@ALWAYS_INLINE bool Parser::parseUInt32(uint32_t& result)
101121 return true;
102122}
103123
 124ALWAYS_INLINE bool Parser::parseInt7(int8_t& result)
 125{
 126 if (m_offset >= length())
 127 return false;
 128 uint8_t v = source()[m_offset++];
 129 result = (v & 0x40) ? WTF::bitwise_cast<int8_t>(uint8_t(v | 0x80)) : v;
 130 return (v & 0x80) == 0;
 131}
 132
104133ALWAYS_INLINE bool Parser::parseUInt7(uint8_t& result)
105134{
106135 if (m_offset >= length())

@@ALWAYS_INLINE bool Parser::parseValueType(Type& result)
128157 result = static_cast<Type>(value);
129158 return true;
130159}
 160
 161ALWAYS_INLINE bool Parser::parseExternalKind(External::Kind& result)
 162{
 163 uint8_t value;
 164 if (!parseUInt7(value))
 165 return false;
 166 if (!External::isValid(value))
 167 return false;
 168 result = static_cast<External::Kind>(value);
 169 return true;
 170}
131171
132172} } // namespace JSC::Wasm
133173

Source/JavaScriptCore/wasm/WasmPlan.cpp

3131#include "B3Compilation.h"
3232#include "WasmB3IRGenerator.h"
3333#include "WasmCallingConvention.h"
 34#include "WasmMemory.h"
3435#include "WasmModuleParser.h"
3536#include "WasmValidate.h"
3637#include <wtf/DataLog.h>
 38#include <wtf/text/StringBuilder.h>
3739
3840namespace JSC { namespace Wasm {
3941

@@Plan::Plan(VM& vm, const uint8_t* source, size_t sourceLength)
4850{
4951 if (verbose)
5052 dataLogLn("Starting plan.");
51  ModuleParser moduleParser(source, sourceLength);
52  if (!moduleParser.parse()) {
53  dataLogLn("Parsing module failed: ", moduleParser.errorMessage());
54  m_errorMessage = moduleParser.errorMessage();
55  return;
 53 {
 54 ModuleParser moduleParser(source, sourceLength);
 55 if (!moduleParser.parse()) {
 56 dataLogLn("Parsing module failed: ", moduleParser.errorMessage());
 57 m_errorMessage = moduleParser.errorMessage();
 58 return;
 59 }
 60 m_moduleInformation = WTFMove(moduleParser.moduleInformation());
5661 }
57 
5862 if (verbose)
5963 dataLogLn("Parsed module.");
6064
61  for (const FunctionInformation& info : moduleParser.functionInformation()) {
 65 if (!m_compiledFunctions.tryReserveCapacity(m_moduleInformation->functions.size())) {
 66 StringBuilder builder;
 67 builder.appendLiteral("Failed allocating enough space for ");
 68 builder.appendNumber(m_moduleInformation->functions.size());
 69 builder.appendLiteral(" compiled functions");
 70 m_errorMessage = builder.toString();
 71 return;
 72 }
 73
 74 for (const FunctionInformation& info : m_moduleInformation->functions) {
6275 if (verbose)
63  dataLogLn("Processing funcion starting at: ", info.start, " and ending at: ", info.end);
 76 dataLogLn("Processing function starting at: ", info.start, " and ending at: ", info.end);
6477 const uint8_t* functionStart = source + info.start;
6578 size_t functionLength = info.end - info.start;
6679 ASSERT(functionLength <= sourceLength);
6780
68  String error = validateFunction(functionStart, functionLength, info.signature, moduleParser.functionInformation());
 81 String error = validateFunction(functionStart, functionLength, info.signature, m_moduleInformation->functions);
6982 if (!error.isNull()) {
7083 m_errorMessage = error;
7184 return;
7285 }
7386
74  m_result.append(parseAndCompile(vm, functionStart, functionLength, moduleParser.memory().get(), info.signature, moduleParser.functionInformation()));
 87 m_compiledFunctions.uncheckedAppend(parseAndCompile(vm, functionStart, functionLength, m_moduleInformation->memory.get(), info.signature, m_moduleInformation->functions));
7588 }
7689
7790 // Patch the call sites for each function.
78  for (std::unique_ptr<FunctionCompilation>& functionPtr : m_result) {
 91 for (std::unique_ptr<FunctionCompilation>& functionPtr : m_compiledFunctions) {
7992 FunctionCompilation* function = functionPtr.get();
8093 for (auto& call : function->unlinkedCalls)
81  MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_result[call.functionIndex]->code->code()));
 94 MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_compiledFunctions[call.functionIndex]->code->code()));
8295 }
8396
84  m_memory = WTFMove(moduleParser.memory());
8597 m_failed = false;
8698}
8799

Source/JavaScriptCore/wasm/WasmPlan.h

@@class Memory;
3838
3939class Plan {
4040public:
41  typedef Vector<std::unique_ptr<FunctionCompilation>> CompiledFunctions;
42 
4341 JS_EXPORT_PRIVATE Plan(VM&, Vector<uint8_t>);
4442 JS_EXPORT_PRIVATE Plan(VM&, const uint8_t*, size_t);
4543 JS_EXPORT_PRIVATE ~Plan();

@@public:
5048 RELEASE_ASSERT(failed());
5149 return m_errorMessage;
5250 }
53  size_t resultSize() const
 51
 52 std::unique_ptr<ModuleInformation>& getModuleInformation()
5453 {
5554 RELEASE_ASSERT(!failed());
56  return m_result.size();
 55 return m_moduleInformation;
5756 }
58  const FunctionCompilation* result(size_t n) const
 57 const Memory* getMemory() const
5958 {
6059 RELEASE_ASSERT(!failed());
61  return m_result.at(n).get();
 60 return m_moduleInformation->memory.get();
6261 }
63  const Memory* memory() const
 62 size_t compiledFunctionCount() const
6463 {
6564 RELEASE_ASSERT(!failed());
66  return m_memory.get();
 65 return m_compiledFunctions.size();
6766 }
68 
69  CompiledFunctions* getFunctions()
 67 const FunctionCompilation* compiledFunction(size_t i) const
7068 {
7169 RELEASE_ASSERT(!failed());
72  return &m_result;
 70 return m_compiledFunctions.at(i).get();
7371 }
74  std::unique_ptr<Memory>* getMemory()
 72 CompiledFunctions& getCompiledFunctions()
7573 {
7674 RELEASE_ASSERT(!failed());
77  return &m_memory;
 75 return m_compiledFunctions;
7876 }
7977
8078private:
81  CompiledFunctions m_result;
82  std::unique_ptr<Memory> m_memory;
 79 std::unique_ptr<ModuleInformation> m_moduleInformation;
 80 CompiledFunctions m_compiledFunctions;
 81
8382 bool m_failed { true };
8483 String m_errorMessage;
8584};

Source/JavaScriptCore/wasm/WasmSections.h

2929
3030namespace JSC { namespace Wasm {
3131
 32#define FOR_EACH_WASM_SECTION(macro) \
 33 macro(Type, 1, "Function signature declarations") \
 34 macro(Import, 2, "Import declarations") \
 35 macro(Function, 3, "Function declarations") \
 36 macro(Table, 4, "Indirect function table and other tables") \
 37 macro(Memory, 5, "Memory attributes") \
 38 macro(Global, 6, "Global declarations") \
 39 macro(Export, 7, "Exports") \
 40 macro(Start, 8, "Start function declaration") \
 41 macro(Element, 9, "Elements section") \
 42 macro(Code, 10, "Function bodies (code)") \
 43 macro(Data, 11, "Data segments")
 44
3245struct Sections {
3346 enum Section : uint8_t {
34  FunctionTypes = 1,
35  Signatures = 3,
36  Memory = 5,
37  Definitions = 10,
 47#define DEFINE_WASM_SECTION_ENUM(NAME, ID, DESCRIPTION) NAME = ID,
 48 FOR_EACH_WASM_SECTION(DEFINE_WASM_SECTION_ENUM)
 49#undef DEFINE_WASM_SECTION_ENUM
3850 Unknown
3951 };
4052 static bool validateOrder(Section previous, Section next)

Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp

3535
3636namespace JSC {
3737
38 JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, Vector<std::unique_ptr<Wasm::FunctionCompilation>>* compiledFunctions, std::unique_ptr<Wasm::Memory>* memory)
 38JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>& moduleInformation, Wasm::CompiledFunctions& compiledFunctions)
3939{
40  auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap)) JSWebAssemblyModule(vm, structure, compiledFunctions, memory);
 40 auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap)) JSWebAssemblyModule(vm, structure, moduleInformation, compiledFunctions);
4141 instance->finishCreation(vm);
4242 return instance;
4343}

@@Structure* JSWebAssemblyModule::createStructure(VM& vm, JSGlobalObject* globalOb
4747 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
4848}
4949
50 JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, Vector<std::unique_ptr<Wasm::FunctionCompilation>>* compiledFunctions, std::unique_ptr<Wasm::Memory>* memory)
 50JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>& moduleInformation, Wasm::CompiledFunctions& compiledFunctions)
5151 : Base(vm, structure)
52  , m_compiledFunctions(WTFMove(*compiledFunctions))
53  , m_memory(WTFMove(*memory))
 52 , m_moduleInformation(WTFMove(moduleInformation))
 53 , m_compiledFunctions(WTFMove(compiledFunctions))
5454{
5555}
5656

Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h

2929
3030#include "JSDestructibleObject.h"
3131#include "JSObject.h"
 32#include "WasmFormat.h"
3233
3334namespace JSC {
3435
35 namespace Wasm {
36 struct FunctionCompilation;
37 class Memory;
38 }
39 
4036class JSWebAssemblyModule : public JSDestructibleObject {
4137public:
4238 typedef JSDestructibleObject Base;
4339
44  static JSWebAssemblyModule* create(VM&, Structure*, Vector<std::unique_ptr<Wasm::FunctionCompilation>>*, std::unique_ptr<Wasm::Memory>*);
 40 static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, Wasm::CompiledFunctions&);
4541 static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
4642
4743 DECLARE_INFO;
4844
 45 const Wasm::ModuleInformation* moduleInformation() const
 46 {
 47 return m_moduleInformation.get();
 48 }
 49
4950protected:
50  JSWebAssemblyModule(VM&, Structure*, Vector<std::unique_ptr<Wasm::FunctionCompilation>>*, std::unique_ptr<Wasm::Memory>*);
 51 JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&, Wasm::CompiledFunctions&);
5152 void finishCreation(VM&);
5253 static void destroy(JSCell*);
5354 static void visitChildren(JSCell*, SlotVisitor&);
54 
5555private:
56  Vector<std::unique_ptr<Wasm::FunctionCompilation>> m_compiledFunctions;
57  std::unique_ptr<Wasm::Memory> m_memory;
 56 std::unique_ptr<Wasm::ModuleInformation> m_moduleInformation;
 57 Wasm::CompiledFunctions m_compiledFunctions;
5858};
5959
6060} // namespace JSC

Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp

@@static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* st
6464 if (!importArgument.isUndefined() && !importObject)
6565 return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("second argument to WebAssembly.Instance must be undefined or an Object"), defaultSourceAppender, runtimeTypeForValue(importArgument))));
6666
67  // FIXME use the importObject. https://bugs.webkit.org/show_bug.cgi?id=164039
6867 // If the list of module.imports is not empty and Type(importObject) is not Object, a TypeError is thrown.
 68 if (module->moduleInformation()->imports.size() && !importObject)
 69 return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("second argument to WebAssembly.Instance must be Object because the WebAssembly.Module has imports"), defaultSourceAppender, runtimeTypeForValue(importArgument))));
6970
7071 // FIXME String things from https://bugs.webkit.org/show_bug.cgi?id=164023
7172 // Let exports be a list of (string, JS value) pairs that is mapped from each external value e in instance.exports as follows:

Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp

@@static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyMemory(ExecState* stat
4747{
4848 VM& vm = state->vm();
4949 auto scope = DECLARE_THROW_SCOPE(vm);
 50 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164134
5051 return JSValue::encode(throwException(state, scope, createError(state, ASCIILiteral("WebAssembly doesn't yet implement the Memory constructor property"))));
5152}
5253

Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp

@@static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyModule(ExecState* stat
7373 if (plan.failed())
7474 return JSValue::encode(throwException(state, scope, createWebAssemblyCompileError(state, plan.errorMessage())));
7575
76  // The spec string values inside Ast.module are decoded as UTF8 as described in Web.md. FIXME https://bugs.webkit.org/show_bug.cgi?id=164023
77 
7876 // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module.
7977 auto* structure = InternalFunction::createSubclassStructure(state, state->newTarget(), asInternalFunction(state->callee())->globalObject()->WebAssemblyModuleStructure());
8078 RETURN_IF_EXCEPTION(scope, encodedJSValue());
8179
82  return JSValue::encode(JSWebAssemblyModule::create(vm, structure, plan.getFunctions(), plan.getMemory()));
 80 return JSValue::encode(JSWebAssemblyModule::create(vm, structure, plan.getModuleInformation(), plan.getCompiledFunctions()));
8381}
8482
8583static EncodedJSValue JSC_HOST_CALL callJSWebAssemblyModule(ExecState* state)

Source/JavaScriptCore/wasm/js/WebAssemblyTableConstructor.cpp

@@static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyTable(ExecState* state
4747{
4848 VM& vm = state->vm();
4949 auto scope = DECLARE_THROW_SCOPE(vm);
 50 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135
5051 return JSValue::encode(throwException(state, scope, createError(state, ASCIILiteral("WebAssembly doesn't yet implement the Table constructor property"))));
5152}
5253