Changeset 208401 in webkit
- Timestamp:
- Nov 4, 2016 3:12:12 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JSTests/ChangeLog
r208377 r208401 1 2016-11-04 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly JS API: implement more sections 4 https://bugs.webkit.org/show_bug.cgi?id=164023 5 6 Reviewed by Keith Miller. 7 8 On the JSC side: 9 10 - Put in parser stubs for all WebAssembly sections. 11 - Parse Import, Export sections. 12 - 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. 13 - Encapsulate all parsed module information into its own structure, making it easier to pass around (from parser to Plan to Module to Instance). 14 - Create WasmFormat.cpp to hold parsed module information's dtor to avoid including WasmMemory.h needlessly. 15 - parseCode: avoid overflow through function size. 16 - Remove all remainders of polyfill-prototype-1, and update license. 17 - Add missing WasmOps.h and WasmValidateInlines.h auto-generation for cmake build. 18 19 On the Builder.js testing side: 20 21 - Implement Type, Import (function only), Export (function only) sections. 22 - Check section order and uniqueness. 23 - Optionally auto-generate the Type section from subsequent Export / Import / Code entries. 24 - Allow re-exporting an import. 25 26 * wasm/Builder.js: build type, import, and export sections 27 (const._normalizeFunctionSignature): 28 * wasm/Builder_WebAssemblyBinary.js: Added. Forked from Builder.js 29 (const.emitters.Type): 30 (const.emitters.Import): 31 (const.emitters.Function): 32 (const.emitters.Table): 33 (const.emitters.Memory): 34 (const.emitters.Global): 35 (const.emitters.Export): 36 (const.emitters.Start): 37 (const.emitters.Element): 38 (const.emitters.Code): 39 (const.emitters.Data): 40 (export.const.Binary): 41 * wasm/LowLevelBinary.js: Add a few useful outputs 42 (export.default.LowLevelBinary.prototype.varuint1): 43 (export.default.LowLevelBinary.prototype.varint7): 44 * wasm/WASM.js: value type and external kind helpers 45 * wasm/assert.js: array element-wise equality comparison 46 (const._eq): 47 * wasm/js-api/test_Module.js: 48 (ModuleWithImports): 49 * 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 50 (const.assertOpThrows): 51 (SectionsWithSameCustomName): 52 (TwoTypeSections): 53 (EmptyImportSection): 54 (ImportBeforeTypeSections): 55 * wasm/self-test/test_BuilderWebAssembly.js: remove a test which wasn't helpful and is now obsolete 56 (CustomSection): 57 1 58 2016-11-03 Mark Lam <mark.lam@apple.com> 2 59 -
trunk/JSTests/wasm/Builder.js
r207363 r208401 24 24 */ 25 25 26 import LowLevelBinary from 'LowLevelBinary.js'; 26 import * as assert from 'assert.js'; 27 import * as BuildWebAssembly from 'Builder_WebAssemblyBinary.js'; 27 28 import * as WASM from 'WASM.js'; 28 29 … … 44 45 const _unknownSectionId = 0; 45 46 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 47 const _normalizeFunctionSignature = (params, ret) => { 48 assert.isArray(params); 49 for (const p of params) 50 assert.truthy(WASM.isValidValueType(p), `Type parameter ${p} needs a valid value type`); 51 if (typeof(ret) === "undefined") 52 ret = "void"; 53 assert.isNotArray(ret, `Multiple return values not supported by WebAssembly yet`); 54 assert.falsy(ret !== "void" && !WASM.isValidValueType(ret), `Type return ${ret} must be valid value type`); 55 return [params, ret]; 56 }; 57 58 const _maybeRegisterType = (builder, type) => { 59 const typeSection = builder._getSection("Type"); 60 if (typeof(type) === "number") { 61 // Type numbers already refer to the type section, no need to register them. 62 if (builder._checked) { 63 assert.isNotUndef(typeSection, `Can't use type ${type} if a type section isn't present`); 64 assert.isNotUndef(typeSection.data[type], `Type ${type} doesn't exist in type section`); 65 } 66 return type; 67 } 68 assert.hasObjectProperty(type, "params", `Expected type to be a number or object with 'params' and optionally 'ret' fields`); 69 const [params, ret] = _normalizeFunctionSignature(type.params, type.ret); 70 assert.isNotUndef(typeSection, `Can't add type if a type section isn't present`); 71 // Try reusing an equivalent type from the type section. 72 types: 73 for (let i = 0; i !== typeSection.data.length; ++i) { 74 const t = typeSection.data[i]; 75 if (t.ret === ret && params.length === t.params.length) { 76 for (let j = 0; j !== t.params.length; ++j) { 77 if (params[j] !== t.params[j]) 78 continue types; 79 } 80 type = i; 81 break; 82 } 83 } 84 if (typeof(type) !== "number") { 85 // Couldn't reuse a pre-existing type, register this type in the type section. 86 typeSection.data.push({ params: params, ret: ret }); 87 type = typeSection.data.length - 1; 88 } 89 return type; 90 }; 91 92 const _importFunctionContinuation = (builder, section, nextBuilder) => { 93 return (module, field, type) => { 94 assert.isString(module, `Import function module should be a string, got "${module}"`); 95 assert.isString(field, `Import function field should be a string, got "${field}"`); 96 const typeSection = builder._getSection("Type"); 97 type = _maybeRegisterType(builder, type); 98 section.data.push({ field: field, type: type, kind: "Function", module: module }); 99 // Imports also count in the function index space. Map them as objects to avoid clashing with Code functions' names. 100 builder._registerFunctionToIndexSpace({ module: module, field: field }); 101 return nextBuilder; 102 }; 103 }; 104 105 const _exportFunctionContinuation = (builder, section, nextBuilder) => { 106 return (field, index, type) => { 107 assert.isString(field, `Export function field should be a string, got "${field}"`); 108 const typeSection = builder._getSection("Type"); 109 if (typeof(type) !== "undefined") { 110 // Exports can leave the type unspecified, letting the Code builder patch them up later. 111 type = _maybeRegisterType(builder, type); 112 } 113 // We can't check much about "index" here because the Code section succeeds the Export section. More work is done at Code().End() time. 114 switch (typeof(index)) { 115 case "string": break; // Assume it's a function name which will be revealed in the Code section. 116 case "number": break; // Assume it's a number in the "function index space". 117 case "object": 118 // Re-exporting an import. 119 assert.hasObjectProperty(index, "module", `Re-exporting "${field}" from an import`); 120 assert.hasObjectProperty(index, "field", `Re-exporting "${field}" from an import`); 121 break; 122 case "undefined": 123 // Assume it's the same as the field (i.e. it's not being renamed). 124 index = field; 125 break; 126 default: throw new Error(`Export section's index must be a string or a number, got ${index}`); 127 } 128 const correspondingImport = builder._getFunctionFromIndexSpace(index); 129 const importSection = builder._getSection("Import"); 130 if (typeof(index) === "object") { 131 // Re-exporting an import using its module+field name. 132 assert.isNotUndef(correspondingImport, `Re-exporting "${field}" couldn't find import from module "${index.module}" field "${index.field}"`); 133 index = correspondingImport; 134 if (typeof(type) === "undefined") 135 type = importSection.data[index].type; 136 if (builder._checked) 137 assert.eq(type, importSection.data[index].type, `Re-exporting import "${importSection.data[index].field}" as "${field}" has mismatching type`); 138 } else if (typeof(correspondingImport) !== "undefined") { 139 // Re-exporting an import using its index. 140 let exportedImport; 141 for (const i of importSection.data) { 142 if (i.module === correspondingImport.module && i.field === correspondingImport.field) { 143 exportedImport = i; 144 break; 76 145 } 77 funcBin.apply();78 146 } 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; 87 } 88 sectionBin.apply(); 89 } 90 return wasmBin; 147 if (typeof(type) === "undefined") 148 type = exportedImport.type; 149 if (builder._checked) 150 assert.eq(type, exportedImport.type, `Re-exporting import "${exportedImport.field}" as "${field}" has mismatching type`); 151 } 152 section.data.push({ field: field, type: type, kind: "Function", index: index }); 153 return nextBuilder; 154 }; 91 155 }; 92 156 … … 99 163 this.setPreamble(preamble); 100 164 this._sections = []; 165 this._functionIndexSpace = {}; 166 this._functionIndexSpaceCount = 0; 101 167 this._registerSectionBuilders(); 102 168 } … … 109 175 return this; 110 176 } 177 _registerFunctionToIndexSpace(name) { 178 if (typeof(name) === "undefined") { 179 // Registering a nameless function still adds it to the function index space. Register it as something that can't normally be registered. 180 name = {}; 181 } 182 // Collisions are fine: we'll simply count the function and forget the previous one. 183 this._functionIndexSpace[name] = this._functionIndexSpaceCount++; 184 // Map it both ways, the number space is distinct from the name space. 185 this._functionIndexSpace[this._functionIndexSpace[name]] = name; 186 } 187 _getFunctionFromIndexSpace(name) { 188 return this._functionIndexSpace[name]; 189 } 111 190 _registerSectionBuilders() { 112 191 for (const section in WASM.description.section) { 113 192 switch (section) { 193 case "Type": 194 this[section] = function() { 195 const s = this._addSection(section); 196 const builder = this; 197 const typeBuilder = { 198 End: () => builder, 199 Func: (params, ret) => { 200 [params, ret] = _normalizeFunctionSignature(params, ret); 201 s.data.push({ params: params, ret: ret }); 202 return typeBuilder; 203 }, 204 }; 205 return typeBuilder; 206 }; 207 break; 208 case "Import": 209 this[section] = function() { 210 const s = this._addSection(section); 211 const importBuilder = { 212 End: () => this, 213 Table: () => { throw new Error(`Unimplemented: import table`); }, 214 Memory: () => { throw new Error(`Unimplemented: import memory`); }, 215 Global: () => { throw new Error(`Unimplemented: import global`); }, 216 }; 217 importBuilder.Function = _importFunctionContinuation(this, s, importBuilder); 218 return importBuilder; 219 }; 220 break; 221 case "Export": 222 this[section] = function() { 223 const s = this._addSection(section); 224 const exportBuilder = { 225 End: () => this, 226 Table: () => { throw new Error(`Unimplemented: export table`); }, 227 Memory: () => { throw new Error(`Unimplemented: export memory`); }, 228 Global: () => { throw new Error(`Unimplemented: export global`); }, 229 }; 230 exportBuilder.Function = _exportFunctionContinuation(this, s, exportBuilder); 231 return exportBuilder; 232 }; 233 break; 114 234 case "Code": 115 235 this[section] = function() { … … 117 237 const builder = this; 118 238 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}]`); 239 End: () => { 240 // We now have enough information to remap the export section's "type" and "index" according to the Code section we're currently ending. 241 const typeSection = builder._getSection("Type"); 242 const importSection = builder._getSection("Import"); 243 const exportSection = builder._getSection("Export"); 244 const codeSection = s; 245 if (exportSection) { 246 for (const e of exportSection.data) { 247 switch (typeof(e.index)) { 248 default: throw new Error(`Unexpected export index "${e.index}"`); 249 case "string": { 250 const index = builder._getFunctionFromIndexSpace(e.index); 251 assert.isNumber(index, `Export section contains undefined function "${e.index}"`); 252 e.index = index; 253 } // Fallthrough. 254 case "number": { 255 const index = builder._getFunctionFromIndexSpace(e.index); 256 if (builder._checked) 257 assert.isNotUndef(index, `Export "${e.field}" doesn't correspond to a defined value in the function index space`); 258 } break; 259 case "undefined": 260 throw new Error(`Unimplemented: Function().End() with undefined export index`); // FIXME 261 } 262 if (typeof(e.type) === "undefined") { 263 // This must be a function export from the Code section (re-exports were handled earlier). 264 const functionIndexSpaceOffset = importSection ? importSection.data.length : 0; 265 const functionIndex = e.index - functionIndexSpaceOffset; 266 e.type = codeSection.data[functionIndex].type; 267 } 268 } 269 } 270 return builder; 271 }, 272 Function: (a0, a1) => { 273 let signature = typeof(a0) === "string" ? a1 : a0; 274 const functionName = typeof(a0) === "string" ? a0 : undefined; 275 if (typeof(signature) === "undefined") 276 signature = { params: [] }; 277 assert.hasObjectProperty(signature, "params", `Expect function signature to be an object with a "params" field, got "${signature}"`); 278 const [params, ret] = _normalizeFunctionSignature(signature.params, signature.ret); 279 signature = { params: params, ret: ret }; 124 280 const func = { 125 locals: parameters, // Parameters are the first locals. 126 parameterCount: parameters.length, 281 name: functionName, 282 type: _maybeRegisterType(builder, signature), 283 signature: signature, 284 locals: params, // Parameters are the first locals. 285 parameterCount: params.length, 127 286 code: [] 128 287 }; 129 288 s.data.push(func); 289 builder._registerFunctionToIndexSpace(functionName); 130 290 let functionBuilder = {}; 131 291 for (const op in WASM.description.opcode) { … … 175 335 } : () => {}; 176 336 const checkImms = builder._checked ? (op, imms) => { 177 if (imms.length != imm.length) throw new Error(`"${op}" expects ${imm.length} immediates, got ${imms.length}`);337 assert.eq(imms.length, imm.length, `"${op}" expects ${imm.length} immediates, got ${imms.length}`); 178 338 for (let idx = 0; idx !== imm.length; ++idx) { 179 339 const got = imms[idx]; … … 181 341 switch (expect.name) { 182 342 case "function_index": 183 if (!_isValidValue(got, "i32")) throw new Error(`Invalid value on ${op}: got "${got}", expected i32`);343 assert.truthy(_isValidValue(got, "i32"), `Invalid value on ${op}: got "${got}", expected i32`); 184 344 // FIXME check function indices. https://bugs.webkit.org/show_bug.cgi?id=163421 185 345 break; … … 187 347 case "global_index": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`); 188 348 case "type_index": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`); 189 case "value": if (!_isValidValue(got, ret[0])) throw new Error(`Invalid value on ${op}: got "${got}", expected ${ret[0]}`); break; 349 case "value": 350 assert.truthy(_isValidValue(got, ret[0]), `Invalid value on ${op}: got "${got}", expected ${ret[0]}`); 351 break; 190 352 case "flags": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`); 191 353 case "offset": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`); … … 227 389 const unknownBuilder = { 228 390 End: () => builder, 229 Byte: b => { if ((b & 0xFF) !== b) throw new RangeError(`Unknown section expected byte, got: "${b}"`); s.data.push(b); return unknownBuilder; } 391 Byte: b => { 392 assert.eq(b & 0xFF, b, `Unknown section expected byte, got: "${b}"`); 393 s.data.push(b); 394 return unknownBuilder; 395 } 230 396 }; 231 397 return unknownBuilder; … … 235 401 const name = typeof(nameOrNumber) === "string" ? nameOrNumber : ""; 236 402 const number = typeof(nameOrNumber) === "number" ? nameOrNumber : (WASM.description.section[name] ? WASM.description.section[name].value : _unknownSectionId); 403 if (this._checked) { 404 // Check uniqueness. 405 for (const s of this._sections) 406 assert.falsy(s.name === name && s.id === number, `Cannot have two sections with the same name "${name}" and ID ${number}`); 407 // Check ordering. 408 if ((number !== _unknownSectionId) && (this._sections.length !== 0)) { 409 for (let i = this._sections.length - 1; i >= 0; --i) { 410 if (this._sections[i].id === _unknownSectionId) 411 continue; 412 assert.le(this._sections[i].id, number, `Bad section ordering: "${this._sections[i].name}" cannot precede "${name}"`); 413 break; 414 } 415 } 416 } 237 417 const s = Object.assign({ name: name, id: number, data: [] }, extraObject || {}); 238 418 this._sections.push(s); 239 419 return s; 420 } 421 _getSection(nameOrNumber) { 422 switch (typeof(nameOrNumber)) { 423 default: throw new Error(`Implementation problem: can't get section "${nameOrNumber}"`); 424 case "string": 425 for (const s of this._sections) 426 if (s.name === nameOrNumber) 427 return s; 428 return undefined; 429 case "number": 430 for (const s of this._sections) 431 if (s.id === nameOrNumber) 432 return s; 433 return undefined; 434 } 240 435 } 241 436 optimize() { … … 255 450 throw new Error("asm.js not implemented yet"); 256 451 } 257 WebAssembly() { return _BuildWebAssemblyBinary(this._preamble, this._sections); }258 }; 452 WebAssembly() { return BuildWebAssembly.Binary(this._preamble, this._sections); } 453 }; -
trunk/JSTests/wasm/LowLevelBinary.js
r207846 r208401 28 28 29 29 export const varuintMin = 0; 30 export const varint7Min = -0b1000000; 31 export const varint7Max = 0b111111; 30 32 export const varuint7Max = 0b1111111; 31 33 export const varuintMax = ((((1 << 31) >>> 0) - 1) * 2) + 1; … … 130 132 } while (true); 131 133 } 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 } 132 144 varuint7(v) { 133 145 if (v < varuintMin || varuint7Max < v) -
trunk/JSTests/wasm/WASM.js
r207363 r208401 26 26 import * as utilities from 'utilities.js'; 27 27 28 const _mapValues = from => { 29 let values = {}; 30 for (const key in from) 31 values[key] = from[key].value; 32 return values; 33 }; 34 28 35 export const description = utilities.json("wasm.json"); 29 36 export const valueType = Object.keys(description.value_type); 30 37 const _valueTypeSet = new Set(valueType); 31 38 export const isValidValueType = v => _valueTypeSet.has(v); 39 export const valueTypeValue = _mapValues(description.value_type); 40 export const externalKindValue = _mapValues(description.external_kind); 32 41 export const sections = Object.keys(description.section); 33 42 export const sectionEncodingType = description.section[sections[0]].type; -
trunk/JSTests/wasm/assert.js
r207825 r208401 24 24 */ 25 25 26 const _notUndef = (v) => { 27 if (typeof v === "undefined") 28 throw new Error("Shouldn't be undefined"); 26 const _fail = (msg, extra) => { 27 throw new Error(msg + (extra ? ": " + extra : "")); 29 28 }; 30 29 31 const _isUndef = (v) => {32 if (typeof v !== "undefined")33 throw new Error("Should be undefined");30 export const isNotA = (v, t, msg) => { 31 if (typeof v === t) 32 _fail(`Shouldn't be ${t}`, msg); 34 33 }; 35 34 36 const _eq = (lhs, rhs) => {37 if ( lhs !== rhs)38 throw new Error(`Not the same: "${lhs}" and "${rhs}"`);35 export const isA = (v, t, msg) => { 36 if (typeof v !== t) 37 _fail(`Should be ${t}, got ${typeof(v)}`, msg); 39 38 }; 40 39 41 const _ge = (lhs, rhs) => { 42 _notUndef(lhs); 43 _notUndef(rhs); 40 export const isNotUndef = (v, msg) => isNotA(v, "undefined", msg); 41 export const isUndef = (v, msg) => isA(v, "undefined", msg); 42 export const notObject = (v, msg) => isNotA(v, "object", msg); 43 export const isObject = (v, msg) => isA(v, "object", msg); 44 export const notString = (v, msg) => isNotA(v, "string", msg); 45 export const isString = (v, msg) => isA(v, "string", msg); 46 export const notNumber = (v, msg) => isNotA(v, "number", msg); 47 export const isNumber = (v, msg) => isA(v, "number", msg); 48 49 export const hasObjectProperty = (o, p, msg) => { 50 isObject(o, msg); 51 isNotUndef(o[p], msg, `expected object to have property ${p}`); 52 }; 53 54 export const isArray = (v, msg) => { 55 if (!Array.isArray(v)) 56 _fail(`Expected an array, got ${typeof(v)}`, msg); 57 }; 58 59 export const isNotArray = (v, msg) => { 60 if (Array.isArray(v)) 61 _fail(`Expected to not be an array`, msg); 62 }; 63 64 export const truthy = (v, msg) => { 65 if (!v) 66 _fail(`Expected truthy`, msg); 67 }; 68 69 export const falsy = (v, msg) => { 70 if (v) 71 _fail(`Expected falsy`, msg); 72 }; 73 74 export const eq = (lhs, rhs, msg) => { 75 if (Array.isArray(lhs) && Array.isArray(rhs) && (lhs.length === rhs.length)) { 76 for (let i = 0; i !== lhs.length; ++i) 77 eq(lhs[i], rhs[i], msg); 78 } else if (lhs !== rhs) 79 _fail(`Not the same: "${lhs}" and "${rhs}"`, msg); 80 }; 81 82 export const ge = (lhs, rhs, msg) => { 83 isNotUndef(lhs); 84 isNotUndef(rhs); 44 85 if (!(lhs >= rhs)) 45 throw new Error(`Expected: "${lhs}" < "${rhs}"`); 86 _fail(`Expected: "${lhs}" < "${rhs}"`, msg); 87 }; 88 89 export const le = (lhs, rhs, msg) => { 90 isNotUndef(lhs); 91 isNotUndef(rhs); 92 if (!(lhs <= rhs)) 93 _fail(`Expected: "${lhs}" > "${rhs}"`, msg); 46 94 }; 47 95 … … 52 100 if (e instanceof type && e.message === message) 53 101 return; 54 throw new Error(`Expected to throw a ${type.name} with message "${message}", got ${e.name} with message "${e.message}"`);102 _fail(`Expected to throw a ${type.name} with message "${message}", got ${e.name} with message "${e.message}"`); 55 103 } 56 throw new Error(`Expected to throw a ${type.name} with message "${message}"`);104 _fail(`Expected to throw a ${type.name} with message "${message}"`); 57 105 }; 58 106 59 const _instanceof = (obj, type) => obj instanceof type; 107 const _instanceof = (obj, type, msg) => { 108 if (!(obj instanceof type)) 109 _fail(`Expected a ${typeof(type)}, got ${typeof obj}`); 110 }; 60 111 61 112 // Use underscore names to avoid clashing with builtin names. 62 113 export { 63 _notUndef as notUndef,64 _isUndef as isUndef,65 _eq as eq,66 _ge as ge,67 114 _throws as throws, 68 115 _instanceof as instanceof, -
trunk/JSTests/wasm/js-api/test_Module.js
r207846 r208401 8 8 assert.instanceof(module, WebAssembly.Module); 9 9 })(); 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 })(); -
trunk/JSTests/wasm/js-api/test_basic_api.js
r207929 r208401 29 29 30 30 31 assert. notUndef(WebAssembly);31 assert.isNotUndef(WebAssembly); 32 32 checkOwnPropertyDescriptor(utilities.global, "WebAssembly", { typeofvalue: "object", writable: true, configurable: true, enumerable: false }); 33 33 assert.eq(String(WebAssembly), "[object WebAssembly]"); … … 38 38 39 39 for (const f in functionProperties) { 40 assert. notUndef(WebAssembly[f]);40 assert.isNotUndef(WebAssembly[f]); 41 41 assert.eq(WebAssembly[f].name, f); 42 42 assert.eq(WebAssembly[f].length, functionProperties[f].length); … … 44 44 45 45 for (const c in constructorProperties) { 46 assert. notUndef(WebAssembly[c]);46 assert.isNotUndef(WebAssembly[c]); 47 47 assert.eq(WebAssembly[c].name, c); 48 48 assert.eq(WebAssembly[c].length, constructorProperties[c].length); … … 67 67 for (const invalid of invalidInstanceImports) 68 68 assert.throws(() => new WebAssembly[c](new WebAssembly.Module(emptyModuleArray), invalid), TypeError, `second argument to WebAssembly.Instance must be undefined or an Object (evaluating 'new WebAssembly[c](new WebAssembly.Module(emptyModuleArray), invalid)')`); 69 assert. notUndef(instance.exports);69 assert.isNotUndef(instance.exports); 70 70 checkOwnPropertyDescriptor(instance, "exports", { typeofvalue: "object", writable: true, configurable: true, enumerable: true }); 71 71 assert.isUndef(instance.exports.__proto__); -
trunk/JSTests/wasm/self-test/test_BuilderJSON.js
r207572 r208401 3 3 4 4 const assertOpThrows = (opFn, message) => { 5 let f = (new Builder()). Code().Function();5 let f = (new Builder()).Type().End().Code().Function(); 6 6 assert.throws(opFn, Error, message, f); 7 7 }; … … 10 10 const b = new Builder(); 11 11 const j = JSON.parse(b.json()); 12 assert. notUndef(j.preamble);13 assert. notUndef(j.preamble["magic number"]);14 assert. notUndef(j.preamble.version);15 assert. notUndef(j.section);12 assert.isNotUndef(j.preamble); 13 assert.isNotUndef(j.preamble["magic number"]); 14 assert.isNotUndef(j.preamble.version); 15 assert.isNotUndef(j.section); 16 16 assert.eq(j.section.length, 0); 17 17 })(); … … 21 21 const j = JSON.parse(b.json()); 22 22 assert.eq(j.preamble["magic number"], 1337); 23 assert. notUndef(j.preamble.version);23 assert.isNotUndef(j.preamble.version); 24 24 })(); 25 25 … … 28 28 const j = JSON.parse(b.json()); 29 29 assert.eq(j.preamble["version"], 1337); 30 assert. notUndef(j.preamble.version);30 assert.isNotUndef(j.preamble.version); 31 31 })(); 32 32 … … 58 58 59 59 (function CustomSectionInvalidByte() { 60 const b = new Builder(); 61 let u = b.Unknown("custom section"); 62 try { 63 u.Byte(0xFF + 1); 64 } catch (e) { 65 if (e instanceof RangeError) { return; } 66 throw new Error(`Expected a RangeError, got ${e}`); 67 } 68 throw new Error(`Expected to throw a RangeError`); 60 const u = (new Builder()).Unknown("custom section"); 61 assert.throws(() => u.Byte(0xFF + 1), Error, `Not the same: "0" and "256": Unknown section expected byte, got: "256"`); 69 62 })(); 70 63 … … 87 80 })(); 88 81 82 (function SectionsWithSameCustomName() { 83 const b = (new Builder()).Unknown("foo").End(); 84 assert.throws(() => b.Unknown("foo"), Error, `Expected falsy: Cannot have two sections with the same name "foo" and ID 0`); 85 })(); 86 87 (function EmptyTypeSection() { 88 const b = (new Builder()).Type().End(); 89 const j = JSON.parse(b.json()); 90 assert.eq(j.section.length, 1); 91 assert.eq(j.section[0].name, "Type"); 92 assert.eq(j.section[0].data.length, 0); 93 })(); 94 95 (function TwoTypeSections() { 96 const b = (new Builder()).Type().End(); 97 assert.throws(() => b.Type(), Error, `Expected falsy: Cannot have two sections with the same name "Type" and ID 1`); 98 })(); 99 100 (function SimpleTypeSection() { 101 const b = (new Builder()).Type() 102 .Func([]) 103 .Func([], "void") 104 .Func([], "i32") 105 .Func([], "i64") 106 .Func([], "f32") 107 .Func([], "f64") 108 .Func(["i32", "i64", "f32", "f64"]) 109 .End(); 110 const j = JSON.parse(b.json()); 111 assert.eq(j.section[0].data.length, 7); 112 assert.eq(j.section[0].data[0].params, []); 113 assert.eq(j.section[0].data[0].ret, "void"); 114 assert.eq(j.section[0].data[1].params, []); 115 assert.eq(j.section[0].data[1].ret, "void"); 116 assert.eq(j.section[0].data[2].params, []); 117 assert.eq(j.section[0].data[2].ret, "i32"); 118 assert.eq(j.section[0].data[3].params, []); 119 assert.eq(j.section[0].data[3].ret, "i64"); 120 assert.eq(j.section[0].data[4].params, []); 121 assert.eq(j.section[0].data[4].ret, "f32"); 122 assert.eq(j.section[0].data[5].params, []); 123 assert.eq(j.section[0].data[5].ret, "f64"); 124 assert.eq(j.section[0].data[6].params, ["i32", "i64", "f32", "f64"]); 125 assert.eq(j.section[0].data[6].ret, "void"); 126 })(); 127 128 (function EmptyImportSection() { 129 const b = (new Builder()).Import().End(); 130 const j = JSON.parse(b.json()); 131 assert.eq(j.section.length, 1); 132 assert.eq(j.section[0].name, "Import"); 133 assert.eq(j.section[0].data.length, 0); 134 })(); 135 136 (function ImportBeforeTypeSections() { 137 const b = (new Builder()).Import().End(); 138 assert.throws(() => b.Type(), Error, `Expected: "2" > "1": Bad section ordering: "Import" cannot precede "Type"`); 139 })(); 140 141 (function ImportFunctionWithoutTypeSection() { 142 const i = (new Builder()).Import(); 143 assert.throws(() => i.Function("foo", "bar", 0), Error, `Shouldn't be undefined: Can't use type 0 if a type section isn't present`); 144 })(); 145 146 (function ImportFunctionWithInvalidType() { 147 const i = (new Builder()).Type().End().Import(); 148 assert.throws(() => i.Function("foo", "bar", 0), Error, `Shouldn't be undefined: Type 0 doesn't exist in type section`); 149 })(); 150 151 (function ImportFunction() { 152 const b = (new Builder()) 153 .Type().Func([]).End() 154 .Import() 155 .Function("foo", "bar", 0) 156 .End(); 157 const j = JSON.parse(b.json()); 158 assert.eq(j.section[1].data.length, 1); 159 assert.eq(j.section[1].data[0].module, "foo"); 160 assert.eq(j.section[1].data[0].field, "bar"); 161 assert.eq(j.section[1].data[0].type, 0); 162 assert.eq(j.section[1].data[0].kind, "Function"); 163 })(); 164 165 (function ImportFunctionsWithExistingTypes() { 166 const b = (new Builder()) 167 .Type() 168 .Func([]) 169 .Func([], "i32") 170 .Func(["i64", "i32"]) 171 .Func(["i64", "i64"]) 172 .End() 173 .Import() 174 .Function("foo", "bar", { params: [] }) 175 .Function("foo", "baz", { params: [], ret: "i32" }) 176 .Function("foo", "boo", { params: ["i64", "i64"] }) 177 .End(); 178 const j = JSON.parse(b.json()); 179 assert.eq(j.section[0].data.length, 4); 180 assert.eq(j.section[1].data.length, 3); 181 assert.eq(j.section[1].data[0].type, 0); 182 assert.eq(j.section[1].data[1].type, 1); 183 assert.eq(j.section[1].data[2].type, 3); 184 })(); 185 186 (function ImportFunctionWithNewType() { 187 const b = (new Builder()) 188 .Type().End() 189 .Import() 190 .Function("foo", "bar", { params: [] }) 191 .Function("foo", "baz", { params: [], ret: "i32" }) 192 .Function("foo", "boo", { params: ["i64", "i64"] }) 193 .End(); 194 const j = JSON.parse(b.json()); 195 assert.eq(j.section[0].data.length, 3); 196 assert.eq(j.section[0].data[0].ret, "void"); 197 assert.eq(j.section[0].data[0].params, []); 198 assert.eq(j.section[0].data[1].ret, "i32"); 199 assert.eq(j.section[0].data[1].params, []); 200 assert.eq(j.section[0].data[2].ret, "void"); 201 assert.eq(j.section[0].data[2].params, ["i64", "i64"]); 202 })(); 203 204 (function EmptyExportSection() { 205 const b = (new Builder()).Export().End(); 206 const j = JSON.parse(b.json()); 207 assert.eq(j.section.length, 1); 208 assert.eq(j.section[0].name, "Export"); 209 assert.eq(j.section[0].data.length, 0); 210 })(); 211 212 (function ExportFunctionWithoutTypeSection() { 213 const e = (new Builder()).Export(); 214 assert.throws(() => e.Function("foo", 0, 0), Error, `Shouldn't be undefined: Can't use type 0 if a type section isn't present`); 215 })(); 216 217 (function ExportFunctionWithInvalidType() { 218 const e = (new Builder()).Type().End().Export(); 219 assert.throws(() => e.Function("foo", 0, 0), Error, `Shouldn't be undefined: Type 0 doesn't exist in type section`); 220 })(); 221 222 (function ExportAnImport() { 223 const b = (new Builder()) 224 .Type().End() 225 .Import().Function("foo", "bar", { params: [] }).End() 226 .Export().Function("ExportAnImport", { module: "foo", field: "bar" }).End(); 227 const j = JSON.parse(b.json()); 228 assert.eq(j.section[2].name, "Export"); 229 assert.eq(j.section[2].data.length, 1); 230 assert.eq(j.section[2].data[0].field, "ExportAnImport"); 231 assert.eq(j.section[2].data[0].type, 0); 232 assert.eq(j.section[2].data[0].index, 0); 233 assert.eq(j.section[2].data[0].kind, "Function"); 234 })(); 235 236 (function ExportMismatchedImport() { 237 const e = (new Builder()) 238 .Type().End() 239 .Import().Function("foo", "bar", { params: [] }).End() 240 .Export(); 241 assert.throws(() => e.Function("foo", 0, { params: ["i32"] }), Error, `Not the same: "1" and "0": Re-exporting import "bar" as "foo" has mismatching type`); 242 })(); 243 89 244 (function EmptyCodeSection() { 90 245 const b = new Builder(); … … 98 253 (function CodeSectionWithEmptyFunction() { 99 254 const b = new Builder(); 100 b.Code() 101 .Function(); 102 const j = JSON.parse(b.json()); 103 assert.eq(j.section.length, 1); 104 assert.eq(j.section[0].name, "Code"); 255 b.Type().End() 256 .Code() 257 .Function(); 258 const j = JSON.parse(b.json()); 259 assert.eq(j.section.length, 2); 260 assert.eq(j.section[0].name, "Type"); 105 261 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); 262 assert.eq(j.section[0].data[0].params, []); 263 assert.eq(j.section[0].data[0].ret, "void"); 264 assert.eq(j.section[1].name, "Code"); 265 assert.eq(j.section[1].data.length, 1); 266 assert.eq(j.section[1].data[0].name, undefined); 267 assert.eq(j.section[1].data[0].type, 0); 268 assert.eq(j.section[1].data[0].parameterCount, 0); 269 assert.eq(j.section[1].data[0].locals.length, 0); 270 assert.eq(j.section[1].data[0].code.length, 0); 109 271 })(); 110 272 111 273 (function CodeSectionWithEmptyFunctionWithParameters() { 112 274 const b = new Builder(); 113 b. Code()114 . Function(["i32", "i64", "f32", "f64"]);115 const j = JSON.parse(b.json());116 assert.eq(j.section.length, 1);117 assert.eq(j.section [0].name, "Code");275 b.Type().End() 276 .Code() 277 .Function({ params: ["i32", "i64", "f32", "f64"] }); 278 const j = JSON.parse(b.json()); 279 assert.eq(j.section.length, 2); 118 280 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); 281 assert.eq(j.section[0].data[0].params, ["i32", "i64", "f32", "f64"]); 282 assert.eq(j.section[0].data[0].ret, "void"); 283 assert.eq(j.section[1].data.length, 1); 284 assert.eq(j.section[1].data[0].type, 0); 285 assert.eq(j.section[1].data[0].parameterCount, 4); 286 assert.eq(j.section[1].data[0].locals[0], "i32"); 287 assert.eq(j.section[1].data[0].locals[1], "i64"); 288 assert.eq(j.section[1].data[0].locals[2], "f32"); 289 assert.eq(j.section[1].data[0].locals[3], "f64"); 290 assert.eq(j.section[1].data[0].code.length, 0); 125 291 })(); 126 292 127 293 (function InvalidFunctionParameters() { 128 for (let invalid in ["", "void", "bool", "any", "struct"]) {294 for (let invalid of ["", "void", "bool", "any", "struct", 0, 3.14, undefined, [], {}]) { 129 295 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}`); 296 assert.throws(() => c.Function({ params: [invalid] }), Error, `Expected truthy: Type parameter ${invalid} needs a valid value type`); 137 297 } 138 298 })(); … … 140 300 (function SimpleFunction() { 141 301 const b = new Builder(); 142 b.Code() 143 .Function() 144 .Nop() 145 .Nop() 302 b.Type().End() 303 .Code() 304 .Function() 305 .Nop() 306 .Nop() 307 .End(); 308 const j = JSON.parse(b.json()); 309 assert.eq(j.section[1].data.length, 1); 310 assert.eq(j.section[1].data[0].locals.length, 0); 311 assert.eq(j.section[1].data[0].code.length, 3); 312 assert.eq(j.section[1].data[0].code[0].name, "nop"); 313 assert.eq(j.section[1].data[0].code[1].name, "nop"); 314 assert.eq(j.section[1].data[0].code[2].name, "end"); 315 })(); 316 317 (function TwoSimpleFunctions() { 318 const b = new Builder(); 319 b.Type().End() 320 .Code() 321 .Function() 322 .Nop() 323 .Nop() 324 .End() 325 .Function() 326 .Return() 327 .End(); 328 const j = JSON.parse(b.json()); 329 assert.eq(j.section[1].data.length, 2); 330 assert.eq(j.section[1].data[0].locals.length, 0); 331 assert.eq(j.section[1].data[0].code.length, 3); 332 assert.eq(j.section[1].data[0].code[0].name, "nop"); 333 assert.eq(j.section[1].data[0].code[1].name, "nop"); 334 assert.eq(j.section[1].data[0].code[2].name, "end"); 335 assert.eq(j.section[1].data[1].locals.length, 0); 336 assert.eq(j.section[1].data[1].code.length, 2); 337 assert.eq(j.section[1].data[1].code[0].name, "return"); 338 assert.eq(j.section[1].data[1].code[1].name, "end"); 339 })(); 340 341 (function NamedFunctions() { 342 const b = new Builder().Type().End().Code() 343 .Function("hello").End() 344 .Function("world", { params: ["i32"] }).End() 345 .End(); 346 const j = JSON.parse(b.json()); 347 assert.eq(j.section[1].data[0].name, "hello"); 348 assert.eq(j.section[1].data[0].parameterCount, 0); 349 assert.eq(j.section[1].data[1].name, "world"); 350 assert.eq(j.section[1].data[1].parameterCount, 1); 351 })(); 352 353 (function ExportSimpleFunctions() { 354 const b = (new Builder()) 355 .Type().End() 356 .Export() 357 .Function("foo", 0, { params: [] }) 358 .Function("bar") 359 .Function("betterNameForBar", "bar") 360 .End() 361 .Code() 362 .Function({ params: [] }).Nop().End() 363 .Function("bar", { params: [] }).Nop().End() 146 364 .End(); 147 365 const j = JSON.parse(b.json()); 148 366 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"); 154 })(); 155 156 (function TwoSimpleFunctions() { 157 const b = new Builder(); 158 b.Code() 159 .Function() 160 .Nop() 161 .Nop() 162 .End() 163 .Function() 164 .Return() 165 .End(); 166 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"); 367 assert.eq(j.section[0].data[0].ret, "void"); 368 assert.eq(j.section[0].data[0].params, []); 369 assert.eq(j.section[1].data.length, 3); 370 assert.eq(j.section[1].data[0].field, "foo"); 371 assert.eq(j.section[1].data[0].type, 0); 372 assert.eq(j.section[1].data[0].index, 0); 373 assert.eq(j.section[1].data[0].kind, "Function"); 374 assert.eq(j.section[1].data[1].field, "bar"); 375 assert.eq(j.section[1].data[1].type, 0); 376 assert.eq(j.section[1].data[1].index, 1); 377 assert.eq(j.section[1].data[1].kind, "Function"); 378 assert.eq(j.section[1].data[2].field, "betterNameForBar"); 379 assert.eq(j.section[1].data[2].type, 0); 380 assert.eq(j.section[1].data[2].index, 1); 381 assert.eq(j.section[1].data[2].kind, "Function"); 382 })(); 383 384 (function ExportUndefinedFunction() { 385 const c = (new Builder()).Type().End().Export().Function("foo").End().Code(); 386 assert.throws(() => c.End(), Error, `Should be number, got undefined: Export section contains undefined function "foo"`); 177 387 })(); 178 388 179 389 (function TwoBuildersAtTheSameTime() { 180 390 const b = [new Builder(), new Builder()]; 181 const f = b.map(builder => builder. Code().Function());391 const f = b.map(builder => builder.Type().End().Code().Function()); 182 392 f[0].Nop(); 183 393 f[1].Return().End().End(); 184 394 f[0].Nop().End().End(); 185 395 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");396 assert.eq(j[0].section[1].data[0].code.length, 3); 397 assert.eq(j[0].section[1].data[0].code[0].name, "nop"); 398 assert.eq(j[0].section[1].data[0].code[1].name, "nop"); 399 assert.eq(j[0].section[1].data[0].code[2].name, "end"); 400 assert.eq(j[1].section[1].data[0].code.length, 2); 401 assert.eq(j[1].section[1].data[0].code[0].name, "return"); 402 assert.eq(j[1].section[1].data[0].code[1].name, "end"); 193 403 })(); 194 404 195 405 (function CheckedOpcodeArgumentsTooMany() { 196 assertOpThrows(f => f.Nop("uh-oh!"), ` "nop" expects 0 immediates, got 1`);406 assertOpThrows(f => f.Nop("uh-oh!"), `Not the same: "1" and "0": "nop" expects 0 immediates, got 1`); 197 407 })(); 198 408 199 409 (function UncheckedOpcodeArgumentsTooMany() { 200 (new Builder()).setChecked(false). Code().Function().Nop("This is fine.", "I'm OK with the events that are unfolding currently.");410 (new Builder()).setChecked(false).Type().End().Code().Function().Nop("This is fine.", "I'm OK with the events that are unfolding currently."); 201 411 })(); 202 412 203 413 (function CheckedOpcodeArgumentsNotEnough() { 204 assertOpThrows(f => f.I32Const(), ` "i32.const" expects 1 immediates, got 0`);414 assertOpThrows(f => f.I32Const(), `Not the same: "0" and "1": "i32.const" expects 1 immediates, got 0`); 205 415 })(); 206 416 207 417 (function UncheckedOpcodeArgumentsNotEnough() { 208 (new Builder()).setChecked(false). Code().Function().I32Const();418 (new Builder()).setChecked(false).Type().End().Code().Function().I32Const(); 209 419 })(); 210 420 211 421 (function CallNoArguments() { 212 const b = (new Builder()). Code().Function().Call(0).End().End();213 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");422 const b = (new Builder()).Type().End().Code().Function().Call(0).End().End(); 423 const j = JSON.parse(b.json()); 424 assert.eq(j.section[1].data[0].code.length, 2); 425 assert.eq(j.section[1].data[0].code[0].name, "call"); 426 assert.eq(j.section[1].data[0].code[0].arguments.length, 0); 427 assert.eq(j.section[1].data[0].code[0].immediates.length, 1); 428 assert.eq(j.section[1].data[0].code[0].immediates[0], 0); 429 assert.eq(j.section[1].data[0].code[1].name, "end"); 220 430 })(); 221 431 222 432 (function CallInvalid() { 223 433 for (let c of [-1, 0x100000000, "0", {}, Infinity, -Infinity, NaN, -NaN, null]) 224 assertOpThrows(f => f.Call(c), ` Invalid value on call: got "${c}", expected i32`);434 assertOpThrows(f => f.Call(c), `Expected truthy: Invalid value on call: got "${c}", expected i32`); 225 435 })(); 226 436 227 437 (function I32ConstValid() { 228 438 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();439 const b = (new Builder()).Type().End().Code().Function().I32Const(c).Return().End().End(); 230 440 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);441 assert.eq(j.section[1].data[0].code[0].name, "i32.const"); 442 assert.eq(j.section[1].data[0].code[0].arguments.length, 0); 443 assert.eq(j.section[1].data[0].code[0].immediates.length, 1); 444 assert.eq(j.section[1].data[0].code[0].immediates[0], c); 235 445 } 236 446 })(); … … 238 448 (function I32ConstInvalid() { 239 449 for (let c of [-1, 0x100000000, 0.1, -0.1, "0", {}, Infinity, null]) 240 assertOpThrows(f => f.I32Const(c), ` Invalid value on i32.const: got "${c}", expected i32`);450 assertOpThrows(f => f.I32Const(c), `Expected truthy: Invalid value on i32.const: got "${c}", expected i32`); 241 451 })(); 242 452 … … 245 455 (function F32ConstValid() { 246 456 for (let c of [0, -0., 0.2, Math.PI, 0x100000000]) { 247 const b = (new Builder()). Code().Function().F32Const(c).Return().End().End();457 const b = (new Builder()).Type().End().Code().Function().F32Const(c).Return().End().End(); 248 458 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);459 assert.eq(j.section[1].data[0].code[0].name, "f32.const"); 460 assert.eq(j.section[1].data[0].code[0].arguments.length, 0); 461 assert.eq(j.section[1].data[0].code[0].immediates.length, 1); 462 assert.eq(j.section[1].data[0].code[0].immediates[0], c); 253 463 } 254 464 })(); … … 256 466 (function F32ConstInvalid() { 257 467 for (let c of ["0", {}, Infinity, -Infinity, NaN, -NaN, null]) 258 assertOpThrows(f => f.F32Const(c), ` Invalid value on f32.const: got "${c}", expected f32`);468 assertOpThrows(f => f.F32Const(c), `Expected truthy: Invalid value on f32.const: got "${c}", expected f32`); 259 469 })(); 260 470 261 471 (function F64ConstValid() { 262 472 for (let c of [0, -0., 0.2, Math.PI, 0x100000000]) { 263 const b = (new Builder()). Code().Function().F64Const(c).Return().End().End();473 const b = (new Builder()).Type().End().Code().Function().F64Const(c).Return().End().End(); 264 474 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);475 assert.eq(j.section[1].data[0].code[0].name, "f64.const"); 476 assert.eq(j.section[1].data[0].code[0].arguments.length, 0); 477 assert.eq(j.section[1].data[0].code[0].immediates.length, 1); 478 assert.eq(j.section[1].data[0].code[0].immediates[0], c); 269 479 } 270 480 })(); … … 272 482 (function F64ConstInvalid() { 273 483 for (let c of ["0", {}, Infinity, -Infinity, NaN, -NaN, null]) 274 assertOpThrows(f => f.F64Const(c), ` Invalid value on f64.const: got "${c}", expected f64`);484 assertOpThrows(f => f.F64Const(c), `Expected truthy: Invalid value on f64.const: got "${c}", expected f64`); 275 485 })(); 276 486 277 487 (function CallOneFromStack() { 278 const b = (new Builder()). Code()279 .Function( ["i32"])488 const b = (new Builder()).Type().End().Code() 489 .Function({ params: ["i32"] }) 280 490 .I32Const(42) 281 491 .Call(0) … … 283 493 .End(); 284 494 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=163267290 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");495 assert.eq(j.section[1].data[0].code.length, 3); 496 assert.eq(j.section[1].data[0].code[0].name, "i32.const"); 497 assert.eq(j.section[1].data[0].code[0].immediates[0], 42); 498 assert.eq(j.section[1].data[0].code[1].name, "call"); 499 // FIXME: assert.eq(j.section[1].data[0].code[1].arguments.length, 1); https://bugs.webkit.org/show_bug.cgi?id=163267 500 assert.eq(j.section[1].data[0].code[1].immediates.length, 1); 501 assert.eq(j.section[1].data[0].code[1].immediates[0], 0); 502 assert.eq(j.section[1].data[0].code[2].name, "end"); 293 503 })(); 294 504 … … 302 512 303 513 (function CallManyFromStack() { 304 const b = (new Builder()). Code()305 .Function(["i32", "i32", "i32", "i32"])514 const b = (new Builder()).Type().End().Code() 515 .Function({ params: ["i32", "i32", "i32", "i32"] }) 306 516 .I32Const(42).I32Const(1337).I32Const(0xBEEF).I32Const(0xFFFF) 307 517 .Call(0) … … 309 519 .End(); 310 520 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=163267314 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);521 assert.eq(j.section[1].data[0].code.length, 6); 522 assert.eq(j.section[1].data[0].code[4].name, "call"); 523 // FIXME: assert.eq(j.section[1].data[0].code[4].arguments.length, 4); https://bugs.webkit.org/show_bug.cgi?id=163267 524 assert.eq(j.section[1].data[0].code[4].immediates.length, 1); 525 assert.eq(j.section[1].data[0].code[4].immediates[0], 0); 316 526 })(); 317 527 318 528 (function OpcodeAdd() { 319 const b = (new Builder()). Code()529 const b = (new Builder()).Type().End().Code() 320 530 .Function() 321 531 .I32Const(42).I32Const(1337) … … 325 535 .End(); 326 536 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=163267330 assert.eq(j.section[ 0].data[0].code[3].name, "return");537 assert.eq(j.section[1].data[0].code.length, 5); 538 assert.eq(j.section[1].data[0].code[2].name, "i32.add"); 539 // FIXME: assert.eq(j.section[1].data[0].code[2].arguments.length, 2); https://bugs.webkit.org/show_bug.cgi?id=163267 540 assert.eq(j.section[1].data[0].code[3].name, "return"); 331 541 // FIXME check return. https://bugs.webkit.org/show_bug.cgi?id=163267 332 542 })(); 333 543 334 544 (function OpcodeUnreachable() { 335 const b = (new Builder()). Code().Function().Unreachable().End().End();336 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");545 const b = (new Builder()).Type().End().Code().Function().Unreachable().End().End(); 546 const j = JSON.parse(b.json()); 547 assert.eq(j.section[1].data[0].code.length, 2); 548 assert.eq(j.section[1].data[0].code[0].name, "unreachable"); 339 549 })(); 340 550 341 551 (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();552 (new Builder()).Type().End().Code().Function().Nop().Unreachable().End().End().json(); 553 (new Builder()).Type().End().Code().Function().Unreachable().Nop().End().End().json(); 554 (new Builder()).Type().End().Code().Function().Return().Unreachable().End().End().json(); 555 (new Builder()).Type().End().Code().Function().Unreachable().Return().End().End().json(); 556 (new Builder()).Type().End().Code().Function().Call(0).Unreachable().End().End().json(); 557 (new Builder()).Type().End().Code().Function().Unreachable().Call(0).End().End().json(); 348 558 })(); 349 559 350 560 (function OpcodeSelect() { 351 const b = (new Builder()). Code().Function()561 const b = (new Builder()).Type().End().Code().Function() 352 562 .I32Const(1).I32Const(2).I32Const(0) 353 563 .Select() … … 356 566 .End(); 357 567 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");568 assert.eq(j.section[1].data[0].code.length, 6); 569 assert.eq(j.section[1].data[0].code[3].name, "select"); 360 570 })(); 361 571 -
trunk/JSTests/wasm/self-test/test_BuilderWebAssembly.js
r207363 r208401 31 31 "00000010 00 41 00 49 00 de ad c0 fe |·A·I····· |"].join("\n")); 32 32 })(); 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 })(); -
trunk/JSTests/wasm/self-test/test_WASM.js
r207363 r208401 2 2 import * as WASM from '../WASM.js'; 3 3 4 assert. notUndef(WASM.description);5 assert. notUndef(WASM.valueType);4 assert.isNotUndef(WASM.description); 5 assert.isNotUndef(WASM.valueType); 6 6 assert.ge(WASM.valueType.length, 4); 7 7 … … 19 19 ]; 20 20 for (const e of expectedFields) { 21 assert. notUndef(WASM.description[e]);21 assert.isNotUndef(WASM.description[e]); 22 22 if (typeof(WASM.description[e]) !== "object") 23 23 throw new Error(`Expected description to contain field "${e}"`); … … 33 33 for (const op in WASM.description.opcode) 34 34 for (const e of expectedOpFields) 35 assert. notUndef(WASM.description.opcode[op][e]);35 assert.isNotUndef(WASM.description.opcode[op][e]); 36 36 37 37 // FIXME: test for field "b3op" when all arithmetic/ comparison ops have them. https://bugs.webkit.org/show_bug.cgi?id=146064 38 38 39 assert. notUndef(WASM.sections);40 assert. notUndef(WASM.sectionEncodingType);39 assert.isNotUndef(WASM.sections); 40 assert.isNotUndef(WASM.sectionEncodingType); 41 41 for (const section of WASM.sections) 42 42 assert.eq(WASM.sectionEncodingType, WASM.description.section[section].type); -
trunk/Source/JavaScriptCore/CMakeLists.txt
r208373 r208401 1140 1140 endif () 1141 1141 1142 # WebAssembly generator 1143 1144 macro(GENERATE_PYTHON _generator _input _output) 1145 add_custom_command( 1146 OUTPUT ${_output} 1147 MAIN_DEPENDENCY ${_generator} 1148 DEPENDS ${_input} 1149 COMMAND ${PYTHON_EXECUTABLE} ${_generator} ${_input} ${_output} 1150 VERBATIM) 1151 list(APPEND JavaScriptCore_HEADERS ${_output}) 1152 ADD_SOURCE_DEPENDENCIES(${_input} ${_output}) 1153 endmacro() 1154 GENERATE_PYTHON(${CMAKE_CURRENT_SOURCE_DIR}/wasm/generateWasmOpsHeader.py ${CMAKE_CURRENT_SOURCE_DIR}/wasm/wasm.json ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/WasmOps.h) 1155 GENERATE_PYTHON(${CMAKE_CURRENT_SOURCE_DIR}/wasm/generateWasmValidateInlinesHeader.py ${CMAKE_CURRENT_SOURCE_DIR}/wasm/wasm.json ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/WasmValidateInlines.h) 1156 1157 # LUT generator 1158 1142 1159 set(HASH_LUT_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/create_hash_table) 1143 1160 macro(GENERATE_HASH_LUT _input _output) -
trunk/Source/JavaScriptCore/ChangeLog
r208377 r208401 1 2016-11-04 JF Bastien <jfbastien@apple.com> 2 3 WebAssembly JS API: implement more sections 4 https://bugs.webkit.org/show_bug.cgi?id=164023 5 6 Reviewed by Keith Miller. 7 8 On the JSC side: 9 10 - Put in parser stubs for all WebAssembly sections. 11 - Parse Import, Export sections. 12 - 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. 13 - Encapsulate all parsed module information into its own structure, making it easier to pass around (from parser to Plan to Module to Instance). 14 - Create WasmFormat.cpp to hold parsed module information's dtor to avoid including WasmMemory.h needlessly. 15 - Remove all remainders of polyfill-prototype-1, and update license. 16 - Add missing WasmOps.h and WasmValidateInlines.h auto-generation for cmake build. 17 18 On the Builder.js testing side: 19 20 - Implement Type, Import (function only), Export (function only) sections. 21 - Check section order and uniqueness. 22 - Optionally auto-generate the Type section from subsequent Export / Import / Code entries. 23 - Allow re-exporting an import. 24 25 * CMakeLists.txt: missing auto-genration 26 * JavaScriptCore.xcodeproj/project.pbxproj: merge conflict 27 * testWasm.cpp: update for API changes, no functional change 28 (checkPlan): 29 (runWasmTests): 30 * wasm/WasmFormat.cpp: add a dtor which requires extra headers which I'd rather not include in WasmFormat.h 31 (JSC::Wasm::ModuleInformation::~ModuleInformation): 32 * 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) 33 (JSC::Wasm::External::isValid): 34 * wasm/WasmModuleParser.cpp: simplify some, make names consistent with the WebAssembly section names, check memory allocations so they can fail early 35 (JSC::Wasm::ModuleParser::parse): 36 (JSC::Wasm::ModuleParser::parseType): 37 (JSC::Wasm::ModuleParser::parseImport): 38 (JSC::Wasm::ModuleParser::parseFunction): 39 (JSC::Wasm::ModuleParser::parseTable): 40 (JSC::Wasm::ModuleParser::parseMemory): 41 (JSC::Wasm::ModuleParser::parseGlobal): 42 (JSC::Wasm::ModuleParser::parseExport): 43 (JSC::Wasm::ModuleParser::parseStart): 44 (JSC::Wasm::ModuleParser::parseElement): 45 (JSC::Wasm::ModuleParser::parseCode): avoid overflow through function size. 46 (JSC::Wasm::ModuleParser::parseData): 47 * wasm/WasmModuleParser.h: 48 (JSC::Wasm::ModuleParser::moduleInformation): 49 * wasm/WasmParser.h: 50 (JSC::Wasm::Parser::consumeUTF8String): add as required by spec 51 (JSC::Wasm::Parser::parseExternalKind): add as per spec 52 * wasm/WasmPlan.cpp: 53 (JSC::Wasm::Plan::Plan): fix some ownership, improve some error messages 54 * wasm/WasmPlan.h: fix some ownership 55 (JSC::Wasm::Plan::getModuleInformation): 56 (JSC::Wasm::Plan::getMemory): 57 (JSC::Wasm::Plan::compiledFunctionCount): 58 (JSC::Wasm::Plan::compiledFunction): 59 (JSC::Wasm::Plan::getCompiledFunctions): 60 * wasm/WasmSections.h: macroize with description, so that error messages are super pretty. This could be auto-generated. 61 * wasm/js/JSWebAssemblyModule.cpp: 62 (JSC::JSWebAssemblyModule::create): take module information 63 (JSC::JSWebAssemblyModule::JSWebAssemblyModule): ditto 64 * wasm/js/JSWebAssemblyModule.h: 65 (JSC::JSWebAssemblyModule::moduleInformation): 66 * wasm/js/WebAssemblyInstanceConstructor.cpp: 67 (JSC::constructJSWebAssemblyInstance): check that modules with imports are instantiated with an import object, as per spec. This needs to be tested. 68 * wasm/js/WebAssemblyMemoryConstructor.cpp: 69 (JSC::constructJSWebAssemblyMemory): 70 * wasm/js/WebAssemblyModuleConstructor.cpp: 71 (JSC::constructJSWebAssemblyModule): 72 * wasm/js/WebAssemblyTableConstructor.cpp: 73 (JSC::constructJSWebAssemblyTable): 74 1 75 2016-11-03 Mark Lam <mark.lam@apple.com> 2 76 -
trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
r208373 r208401 1296 1296 53FF7F991DBFCD9000A26CCC /* WasmValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */; }; 1297 1297 53FF7F9B1DBFD2B900A26CCC /* WasmValidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */; }; 1298 53FF7F9D1DC00DB100A26CCC /* WasmFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */; };1299 1298 5B70CFDE1DB69E6600EC23F9 /* JSAsyncFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */; }; 1300 1299 5B70CFDF1DB69E6600EC23F9 /* JSAsyncFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */; }; … … 1991 1990 AD2FCC301DB83D4900B3E736 /* JSWebAssembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCC2E1DB839F700B3E736 /* JSWebAssembly.cpp */; }; 1992 1991 AD2FCC311DB83D4900B3E736 /* JSWebAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = AD2FCC2F1DB839F700B3E736 /* JSWebAssembly.h */; }; 1992 AD2FCC331DC4045400B3E736 /* WasmFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */; }; 1993 1993 AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1994 1994 ADDB1F6318D77DBE009B58A8 /* OpaqueRootSet.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 3663 3663 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmValidate.h; sourceTree = "<group>"; }; 3664 3664 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmValidate.cpp; sourceTree = "<group>"; }; 3665 53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFormat.cpp; sourceTree = "<group>"; };3666 3665 5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAsyncFunction.h; sourceTree = "<group>"; }; 3667 3666 5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAsyncFunction.cpp; sourceTree = "<group>"; }; … … 4440 4439 AD2FCC2E1DB839F700B3E736 /* JSWebAssembly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebAssembly.cpp; sourceTree = "<group>"; }; 4441 4440 AD2FCC2F1DB839F700B3E736 /* JSWebAssembly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebAssembly.h; sourceTree = "<group>"; }; 4441 AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmFormat.cpp; sourceTree = "<group>"; }; 4442 4442 AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCMapInlines.h; sourceTree = "<group>"; }; 4443 4443 ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueRootSet.h; sourceTree = "<group>"; }; … … 5956 5956 53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */, 5957 5957 53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */, 5958 53FF7F9C1DC00DB100A26CCC/* WasmFormat.cpp */,5958 AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */, 5959 5959 7BC547D21B69599B00959B58 /* WasmFormat.h */, 5960 5960 53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */, … … 9875 9875 0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */, 9876 9876 0FF8BDEA1AD4CF7100DFE884 /* InferredValue.cpp in Sources */, 9877 AD2FCC331DC4045400B3E736 /* WasmFormat.cpp in Sources */, 9877 9878 9E729407190F01A5001A91B5 /* InitializeThreading.cpp in Sources */, 9878 9879 A513E5B7185B8BD3007E95AD /* InjectedScript.cpp in Sources */, -
trunk/Source/JavaScriptCore/testWasm.cpp
r208341 r208401 277 277 } 278 278 279 if (plan. resultSize() != expectedNumberOfFunctions) {279 if (plan.compiledFunctionCount() != expectedNumberOfFunctions) { 280 280 dataLogLn("Incorrect number of functions"); 281 281 CRASH(); … … 283 283 284 284 for (unsigned i = 0; i < expectedNumberOfFunctions; ++i) { 285 if (!plan. result(i)) {285 if (!plan.compiledFunction(i)) { 286 286 dataLogLn("Function at index, " , i, " failed to compile correctly"); 287 287 CRASH(); … … 321 321 322 322 // Test this doesn't crash. 323 CHECK(isIdentical(invoke<int>(*plan. result(0)->jsEntryPoint, { boxf(0), boxf(32) }), 1));324 CHECK(isIdentical(invoke<int>(*plan. result(0)->jsEntryPoint, { boxf(1), boxf(32) }), 2));323 CHECK(isIdentical(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0), boxf(32) }), 1)); 324 CHECK(isIdentical(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(1), boxf(32) }), 2)); 325 325 } 326 326 … … 348 348 349 349 // Test this doesn't crash. 350 CHECK(isIdentical(invoke<int>(*plan. result(0)->jsEntryPoint, { boxf(0), boxf(32) }), 1));351 CHECK(isIdentical(invoke<int>(*plan. result(0)->jsEntryPoint, { boxf(1), boxf(32) }), 2));350 CHECK(isIdentical(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0), boxf(32) }), 1)); 351 CHECK(isIdentical(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(1), boxf(32) }), 2)); 352 352 } 353 353 … … 386 386 387 387 // Test this doesn't crash. 388 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(1) }), 1);389 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(0) }), 0);390 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(1) }), 0);391 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(2) }), 1);392 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(2) }), 0);393 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(1) }), 0);394 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(6) }), 1);395 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(6) }), 0);388 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1); 389 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0); 390 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0); 391 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1); 392 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0); 393 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0); 394 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1); 395 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0); 396 396 } 397 397 … … 416 416 417 417 // Test this doesn't crash. 418 CHECK(isIdentical(invoke<float>(*plan. result(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));419 CHECK(isIdentical(invoke<float>(*plan. result(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));420 CHECK(isIdentical(invoke<float>(*plan. result(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f));421 CHECK(isIdentical(invoke<float>(*plan. result(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f));418 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f)); 419 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f)); 420 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), -1.5f)); 421 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 87.6234f)); 422 422 } 423 423 … … 442 442 443 443 // Test this doesn't crash. 444 CHECK(isIdentical(invoke<float>(*plan. result(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));445 CHECK(isIdentical(invoke<float>(*plan. result(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));446 CHECK(isIdentical(invoke<float>(*plan. result(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f));447 CHECK(isIdentical(invoke<float>(*plan. result(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f));444 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f)); 445 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(1)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f)); 446 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(0.0), boxf(1.5) }), 1.5f)); 447 CHECK(isIdentical(invoke<float>(*plan.compiledFunction(0)->jsEntryPoint, { boxf(100.1234), boxf(12.5) }), 112.6234f)); 448 448 } 449 449 … … 473 473 474 474 // Test this doesn't crash. 475 CHECK_EQ(invoke<int>(*plan. result(1)->jsEntryPoint, { box(0) }), 0);476 CHECK_EQ(invoke<int>(*plan. result(1)->jsEntryPoint, { box(100) }), 1200);477 CHECK_EQ(invoke<int>(*plan. result(1)->jsEntryPoint, { box(1) }), 12);478 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);479 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);475 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0) }), 0); 476 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100) }), 1200); 477 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1) }), 12); 478 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); 479 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); 480 480 } 481 481 … … 504 504 505 505 // Test this doesn't crash. 506 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0) }), 1);507 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1) }), 1);508 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2) }), 2);509 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(4) }), 24);506 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 1); 507 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1); 508 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2) }), 2); 509 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(4) }), 24); 510 510 } 511 511 … … 527 527 528 528 Plan plan(*vm, vector); 529 if (plan. resultSize() != 2 || !plan.result(0) || !plan.result(1)) {529 if (plan.compiledFunctionCount() != 2 || !plan.compiledFunction(0) || !plan.compiledFunction(1)) { 530 530 dataLogLn("Module failed to compile correctly."); 531 531 CRASH(); … … 533 533 534 534 // Test this doesn't crash. 535 CHECK_EQ(invoke<int>(*plan. result(1)->jsEntryPoint, { box(0), box(0) }), 0);536 CHECK_EQ(invoke<int>(*plan. result(1)->jsEntryPoint, { box(100), box(0) }), 100);537 CHECK_EQ(invoke<int>(*plan. result(1)->jsEntryPoint, { box(1), box(15) }), 16);538 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0) }), 0);539 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100) }), 200);540 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1) }), 2);535 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0), box(0) }), 0); 536 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100), box(0) }), 100); 537 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1), box(15) }), 16); 538 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0); 539 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 200); 540 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 2); 541 541 } 542 542 … … 561 561 562 562 // Test this doesn't crash. 563 CHECK_EQ(invoke<int>(*plan. result(1)->jsEntryPoint, { box(0) }), 0);564 CHECK_EQ(invoke<int>(*plan. result(1)->jsEntryPoint, { box(100) }), 100);565 CHECK_EQ(invoke<int>(*plan. result(1)->jsEntryPoint, { box(1) }), 1);566 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0) }), 0);567 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100) }), 100);568 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1) }), 1);563 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(0) }), 0); 564 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(100) }), 100); 565 CHECK_EQ(invoke<int>(*plan.compiledFunction(1)->jsEntryPoint, { box(1) }), 1); 566 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0); 567 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100); 568 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1); 569 569 } 570 570 … … 590 590 591 591 // Test this doesn't crash. 592 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(10) }), 0);593 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(2) }), 100);594 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(100) }), 1);592 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0); 593 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100); 594 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1); 595 595 } 596 596 … … 617 617 618 618 // Test this doesn't crash. 619 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(10) }), 0);620 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(2) }), 100);621 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(100) }), 1);619 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0); 620 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100); 621 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1); 622 622 } 623 623 … … 658 658 unsigned offset = sizeof(uint32_t); 659 659 uint32_t* memory = static_cast<uint32_t*>(plan.memory()->memory()); 660 invoke<void>(*plan. result(0)->jsEntryPoint, { box(100), box(offset), box(length) });660 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) }); 661 661 offset /= sizeof(uint32_t); 662 662 CHECK_EQ(memory[offset - 1], 0u); … … 667 667 length = 10; 668 668 offset = 5 * sizeof(uint32_t); 669 invoke<void>(*plan. result(0)->jsEntryPoint, { box(5), box(offset), box(length) });669 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) }); 670 670 offset /= sizeof(uint32_t); 671 671 CHECK_EQ(memory[offset - 1], 100u); … … 710 710 unsigned offset = 1; 711 711 uint8_t* memory = static_cast<uint8_t*>(plan.memory()->memory()); 712 invoke<void>(*plan. result(0)->jsEntryPoint, { box(100), box(offset), box(length) });712 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) }); 713 713 CHECK_EQ(memory[offset - 1], 0u); 714 714 CHECK_EQ(memory[offset + length], 0u); … … 718 718 length = 10; 719 719 offset = 5; 720 invoke<void>(*plan. result(0)->jsEntryPoint, { box(5), box(offset), box(length) });720 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) }); 721 721 CHECK_EQ(memory[offset - 1], 100u); 722 722 CHECK_EQ(memory[offset + length], 0u); … … 748 748 749 749 // Test this doesn't crash. 750 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(10) }), 0);751 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(2) }), 100);752 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(100) }), 1);750 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0); 751 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100); 752 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1); 753 753 } 754 754 … … 775 775 776 776 // Test this doesn't crash. 777 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0) }), 0);778 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100) }), 100);779 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1) }), 1);777 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0); 778 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100); 779 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1); 780 780 } 781 781 … … 802 802 803 803 // Test this doesn't crash. 804 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(10) }), 0);805 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(2) }), 100);806 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(100) }), 1);807 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(-12), box(plan.memory()->size() - sizeof(uint64_t)) }), -12);804 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0); 805 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100); 806 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1); 807 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-12), box(plan.memory()->size() - sizeof(uint64_t)) }), -12); 808 808 } 809 809 … … 830 830 831 831 // Test this doesn't crash. 832 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(10) }), 0);833 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(2) }), 100);834 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(100) }), 1);832 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0); 833 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100); 834 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1); 835 835 } 836 836 … … 871 871 unsigned offset = sizeof(uint32_t); 872 872 uint32_t* memory = static_cast<uint32_t*>(plan.memory()->memory()); 873 invoke<void>(*plan. result(0)->jsEntryPoint, { box(100), box(offset), box(length) });873 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) }); 874 874 offset /= sizeof(uint32_t); 875 875 CHECK_EQ(memory[offset - 1], 0u); … … 880 880 length = 10; 881 881 offset = 5 * sizeof(uint32_t); 882 invoke<void>(*plan. result(0)->jsEntryPoint, { box(5), box(offset), box(length) });882 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) }); 883 883 offset /= sizeof(uint32_t); 884 884 CHECK_EQ(memory[offset - 1], 100u); … … 923 923 unsigned offset = 1; 924 924 uint8_t* memory = static_cast<uint8_t*>(plan.memory()->memory()); 925 invoke<void>(*plan. result(0)->jsEntryPoint, { box(100), box(offset), box(length) });925 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(offset), box(length) }); 926 926 CHECK_EQ(memory[offset - 1], 0u); 927 927 CHECK_EQ(memory[offset + length], 0u); … … 931 931 length = 10; 932 932 offset = 5; 933 invoke<void>(*plan. result(0)->jsEntryPoint, { box(5), box(offset), box(length) });933 invoke<void>(*plan.compiledFunction(0)->jsEntryPoint, { box(5), box(offset), box(length) }); 934 934 CHECK_EQ(memory[offset - 1], 100u); 935 935 CHECK_EQ(memory[offset + length], 0u); … … 961 961 962 962 // Test this doesn't crash. 963 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(10) }), 0);964 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(2) }), 100);965 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(100) }), 1);963 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(10) }), 0); 964 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(2) }), 100); 965 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(100) }), 1); 966 966 } 967 967 … … 988 988 989 989 // Test this doesn't crash. 990 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0) }), 0);991 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100) }), 100);992 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1) }), 1);990 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0); 991 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 100); 992 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1); 993 993 } 994 994 … … 1015 1015 1016 1016 // Test this doesn't crash. 1017 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(1) }), 1);1018 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(0) }), 1);1019 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(1) }), 1);1020 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(2) }), 1);1021 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(2) }), 0);1022 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(1) }), 0);1023 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(6) }), 1);1024 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(6) }), 1);1017 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1); 1018 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 1); 1019 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 1); 1020 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1); 1021 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0); 1022 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0); 1023 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1); 1024 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 1); 1025 1025 } 1026 1026 … … 1053 1053 1054 1054 // Test this doesn't crash. 1055 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(1) }), 1);1056 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(0) }), 0);1057 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(1) }), 0);1058 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(2) }), 1);1059 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(2) }), 0);1060 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(1) }), 0);1061 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(6) }), 1);1062 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(6) }), 0);1055 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1); 1056 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0); 1057 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0); 1058 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1); 1059 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0); 1060 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0); 1061 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1); 1062 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0); 1063 1063 } 1064 1064 … … 1077 1077 1078 1078 // Test this doesn't crash. 1079 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { }), 5);1079 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 5); 1080 1080 } 1081 1081 … … 1095 1095 1096 1096 // Test this doesn't crash. 1097 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { }), 11);1097 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11); 1098 1098 } 1099 1099 … … 1112 1112 1113 1113 // Test this doesn't crash. 1114 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { }), 11);1114 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11); 1115 1115 } 1116 1116 … … 1129 1129 1130 1130 // Test this doesn't crash. 1131 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { }), 11);1131 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { }), 11); 1132 1132 } 1133 1133 … … 1145 1145 1146 1146 // Test this doesn't crash. 1147 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(1) }), 1);1148 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(1) }), 101);1149 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(-1), box(1)}), 0);1150 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min());1147 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1); 1148 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(1) }), 101); 1149 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(-1), box(1)}), 0); 1150 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(std::numeric_limits<int>::max()), box(1) }), std::numeric_limits<int>::min()); 1151 1151 } 1152 1152 … … 1171 1171 1172 1172 // Test this doesn't crash. 1173 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0) }), 0);1174 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(10) }), 10);1173 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0); 1174 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(10) }), 10); 1175 1175 } 1176 1176 … … 1204 1204 1205 1205 // Test this doesn't crash. 1206 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0) }), 0);1207 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1) }), 1);1208 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2)}), 3);1209 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100) }), 5050);1206 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0) }), 0); 1207 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1) }), 1); 1208 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2)}), 3); 1209 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100) }), 5050); 1210 1210 } 1211 1211 … … 1245 1245 1246 1246 // Test this doesn't crash. 1247 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(1) }), 0);1248 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(0) }), 0);1249 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(1) }), 2);1250 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(2) }), 2);1251 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(2) }), 4);1252 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(6) }), 12);1253 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(6) }), 600);1254 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(100) }), 10000);1247 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 0); 1248 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0); 1249 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 2); 1250 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 2); 1251 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 4); 1252 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 12); 1253 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 600); 1254 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(100) }), 10000); 1255 1255 } 1256 1256 … … 1295 1295 1296 1296 // Test this doesn't crash. 1297 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(0), box(1) }), 1);1298 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(0) }), 0);1299 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(1) }), 0);1300 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(2) }), 1);1301 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(2) }), 0);1302 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(1), box(1) }), 0);1303 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(2), box(6) }), 1);1304 CHECK_EQ(invoke<int>(*plan. result(0)->jsEntryPoint, { box(100), box(6) }), 0);1297 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(0), box(1) }), 1); 1298 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(0) }), 0); 1299 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(1) }), 0); 1300 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(2) }), 1); 1301 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(2) }), 0); 1302 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(1), box(1) }), 0); 1303 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(2), box(6) }), 1); 1304 CHECK_EQ(invoke<int>(*plan.compiledFunction(0)->jsEntryPoint, { box(100), box(6) }), 0); 1305 1305 } 1306 1306 -
trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp
r208238 r208401 25 25 26 26 #include "config.h" 27 27 28 #include "WasmFormat.h" 28 29 29 30 #if ENABLE(WEBASSEMBLY) 31 32 #include "WasmMemory.h" 30 33 31 34 namespace JSC { namespace Wasm { … … 47 50 } 48 51 52 ModuleInformation::~ModuleInformation() { } 53 49 54 } } // namespace JSC::Wasm 50 55 51 #endif // ENABLE( B3_JIT)56 #endif // ENABLE(WEBASSEMBLY) -
trunk/Source/JavaScriptCore/wasm/WasmFormat.h
r208238 r208401 22 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 *25 * =========================================================================26 *27 * Copyright (c) 2015 by the repository authors of28 * 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 at33 *34 * http://www.apache.org/licenses/LICENSE-2.035 *36 * Unless required by applicable law or agreed to in writing, software37 * 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 and40 * limitations under the License.41 24 */ 42 25 … … 99 82 100 83 const char* toString(Type); 84 85 struct 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 }; 101 111 102 112 struct Signature { … … 104 114 Vector<Type> arguments; 105 115 }; 106 107 struct FunctionImport { 108 String functionName; 109 }; 110 111 struct FunctionImportSignature { 112 uint32_t signatureIndex; 113 uint32_t functionImportIndex; 114 }; 115 116 struct FunctionDeclaration { 117 uint32_t signatureIndex; 118 }; 119 120 struct FunctionPointerTable { 121 uint32_t signatureIndex; 122 Vector<uint32_t> functionIndices; 123 Vector<JSFunction*> functions; 116 117 struct 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 }; 124 127 }; 125 128 … … 129 132 size_t end; 130 133 }; 134 135 class Memory; 136 137 struct 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 }; 146 }; 147 148 struct ModuleInformation { 149 Vector<Signature> signatures; 150 Vector<Import> imports; 151 Vector<FunctionInformation> functions; 152 std::unique_ptr<Memory> memory; 153 Vector<Export> exports; 154 155 ~ModuleInformation(); 156 }; 157 158 struct FunctionCompilation; 159 typedef Vector<std::unique_ptr<FunctionCompilation>> CompiledFunctions; 131 160 132 161 struct UnlinkedCall { -
trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp
r207927 r208401 30 30 31 31 #include "WasmFormat.h" 32 #include "WasmMemory.h" 32 33 #include "WasmOps.h" 33 34 #include "WasmSections.h" … … 41 42 bool ModuleParser::parse() 42 43 { 44 m_module = std::make_unique<ModuleInformation>(); 45 43 46 const size_t minSize = 8; 44 47 if (length() < minSize) { … … 112 115 113 116 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: { 162 131 if (verbose) 163 132 dataLogLn("Unknown section, skipping."); … … 185 154 } 186 155 156 bool ModuleParser::parseType() 157 { 158 uint32_t count; 159 if (!parseVarUInt32(count)) 160 return false; 161 if (verbose) 162 dataLogLn("count: ", count); 163 if (!m_module->signatures.tryReserveCapacity(count)) 164 return false; 165 166 for (uint32_t i = 0; i < count; ++i) { 167 int8_t type; 168 if (!parseInt7(type)) 169 return false; 170 if (type != -0x20) // Function type constant. 171 return false; 172 173 if (verbose) 174 dataLogLn("Got function type."); 175 176 uint32_t argumentCount; 177 if (!parseVarUInt32(argumentCount)) 178 return false; 179 180 if (verbose) 181 dataLogLn("argumentCount: ", argumentCount); 182 183 Vector<Type> argumentTypes; 184 if (!argumentTypes.tryReserveCapacity(argumentCount)) 185 return false; 186 187 for (unsigned i = 0; i != argumentCount; ++i) { 188 uint8_t argumentType; 189 if (!parseUInt7(argumentType) || !isValueType(static_cast<Type>(argumentType))) 190 return false; 191 argumentTypes.uncheckedAppend(static_cast<Type>(argumentType)); 192 } 193 194 uint8_t returnCount; 195 if (!parseVarUInt1(returnCount)) 196 return false; 197 Type returnType; 198 199 if (verbose) 200 dataLogLn(returnCount); 201 202 if (returnCount) { 203 Type value; 204 if (!parseValueType(value)) 205 return false; 206 returnType = static_cast<Type>(value); 207 } else 208 returnType = Type::Void; 209 210 m_module->signatures.uncheckedAppend({ returnType, WTFMove(argumentTypes) }); 211 } 212 return true; 213 } 214 215 bool ModuleParser::parseImport() 216 { 217 uint32_t importCount; 218 if (!parseVarUInt32(importCount)) 219 return false; 220 if (!m_module->imports.tryReserveCapacity(importCount)) 221 return false; 222 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 } 257 258 m_module->imports.uncheckedAppend(i); 259 } 260 261 return true; 262 } 263 264 bool 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) { 273 uint32_t typeNumber; 274 if (!parseVarUInt32(typeNumber)) 275 return false; 276 277 if (typeNumber >= m_module->signatures.size()) 278 return false; 279 280 m_module->functions.uncheckedAppend({ &m_module->signatures[typeNumber], 0, 0 }); 281 } 282 283 return true; 284 } 285 286 bool ModuleParser::parseTable() 287 { 288 // FIXME 289 return true; 290 } 291 187 292 bool ModuleParser::parseMemory() 188 293 { … … 209 314 210 315 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() 316 m_module->memory = std::make_unique<Memory>(size, capacity, pinnedSizes); 317 return m_module->memory->memory(); 318 } 319 320 bool ModuleParser::parseGlobal() 321 { 322 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133 323 return true; 324 } 325 326 bool 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 370 bool ModuleParser::parseStart() 371 { 372 // FIXME https://bugs.webkit.org/show_bug.cgi?id=161709 373 return true; 374 } 375 376 bool ModuleParser::parseElement() 377 { 378 // FIXME https://bugs.webkit.org/show_bug.cgi?id=161709 379 return true; 380 } 381 382 bool ModuleParser::parseCode() 216 383 { 217 384 uint32_t count; … … 219 386 return false; 220 387 221 if (verbose) 222 dataLogLn("count: ", count); 223 224 m_signatures.resize(count); 225 226 for (uint32_t i = 0; i < count; ++i) { 227 uint8_t type; 228 if (!parseUInt7(type)) 229 return false; 230 if (type != 0x40) // Function type constant. 231 return false; 232 233 if (verbose) 234 dataLogLn("Got function type."); 235 236 uint32_t argumentCount; 237 if (!parseVarUInt32(argumentCount)) 238 return false; 239 240 if (verbose) 241 dataLogLn("argumentCount: ", argumentCount); 242 243 Vector<Type> argumentTypes; 244 argumentTypes.resize(argumentCount); 245 246 for (unsigned i = 0; i < argumentCount; ++i) { 247 if (!parseUInt7(type) || !isValueType(static_cast<Type>(type))) 248 return false; 249 argumentTypes[i] = static_cast<Type>(type); 250 } 251 252 if (!parseVarUInt1(type)) 253 return false; 254 Type returnType; 255 256 if (verbose) 257 dataLogLn(type); 258 259 if (type) { 260 Type value; 261 if (!parseValueType(value)) 262 return false; 263 returnType = static_cast<Type>(value); 264 } else 265 returnType = Type::Void; 266 267 m_signatures[i] = { returnType, WTFMove(argumentTypes) }; 268 } 269 return true; 270 } 271 272 bool ModuleParser::parseFunctionSignatures() 273 { 274 uint32_t count; 275 if (!parseVarUInt32(count)) 276 return false; 277 278 m_functions.resize(count); 279 280 for (uint32_t i = 0; i < count; ++i) { 281 uint32_t typeNumber; 282 if (!parseVarUInt32(typeNumber)) 283 return false; 284 285 if (typeNumber >= m_signatures.size()) 286 return false; 287 288 m_functions[i].signature = &m_signatures[typeNumber]; 289 } 290 291 return true; 292 } 293 294 bool ModuleParser::parseFunctionDefinitions() 295 { 296 uint32_t count; 297 if (!parseVarUInt32(count)) 298 return false; 299 300 if (count != m_functions.size()) 301 return false; 302 303 for (uint32_t i = 0; i < count; ++i) { 388 if (count != m_module->functions.size()) 389 return false; 390 391 for (uint32_t i = 0; i != count; ++i) { 304 392 uint32_t functionSize; 305 393 if (!parseVarUInt32(functionSize)) 306 394 return false; 307 308 FunctionInformation& info = m_functions[i]; 395 if (functionSize > length() || functionSize > length() - m_offset) 396 return false; 397 398 FunctionInformation& info = m_module->functions[i]; 309 399 info.start = m_offset; 310 400 info.end = m_offset + functionSize; … … 315 405 } 316 406 407 bool ModuleParser::parseData() 408 { 409 // FIXME https://bugs.webkit.org/show_bug.cgi?id=161709 410 return true; 411 } 412 317 413 } } // namespace JSC::Wasm 318 414 -
trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h
r207825 r208401 28 28 #if ENABLE(WEBASSEMBLY) 29 29 30 #include "Wasm Memory.h"30 #include "WasmFormat.h" 31 31 #include "WasmOps.h" 32 32 #include "WasmParser.h" … … 57 57 } 58 58 59 const Vector<FunctionInformation>& functionInformation() const59 std::unique_ptr<ModuleInformation>& moduleInformation() 60 60 { 61 61 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; 68 63 } 69 64 70 65 private: 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 76 69 77 Vector<FunctionInformation> m_functions; 78 Vector<Signature> m_signatures; 79 std::unique_ptr<Memory> m_memory; 70 std::unique_ptr<ModuleInformation> m_module; 80 71 bool m_failed { true }; 81 72 String m_errorMessage; -
trunk/Source/JavaScriptCore/wasm/WasmParser.h
r207825 r208401 34 34 #include "WasmSections.h" 35 35 #include <wtf/LEBDecoder.h> 36 #include <wtf/StdLibExtras.h> 37 #include <wtf/text/WTFString.h> 36 38 37 39 namespace JSC { namespace Wasm { … … 43 45 bool WARN_UNUSED_RETURN consumeCharacter(char); 44 46 bool WARN_UNUSED_RETURN consumeString(const char*); 47 bool WARN_UNUSED_RETURN consumeUTF8String(String&, size_t); 45 48 46 49 bool WARN_UNUSED_RETURN parseVarUInt1(uint8_t& result); 50 bool WARN_UNUSED_RETURN parseInt7(int8_t& result); 47 51 bool WARN_UNUSED_RETURN parseUInt7(uint8_t& result); 48 52 bool WARN_UNUSED_RETURN parseUInt32(uint32_t& result); … … 51 55 52 56 bool WARN_UNUSED_RETURN parseValueType(Type& result); 57 bool WARN_UNUSED_RETURN parseExternalKind(External::Kind& result); 53 58 54 59 const uint8_t* source() const { return m_source; } … … 93 98 } 94 99 100 ALWAYS_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 95 115 ALWAYS_INLINE bool Parser::parseUInt32(uint32_t& result) 96 116 { … … 100 120 m_offset += 4; 101 121 return true; 122 } 123 124 ALWAYS_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; 102 131 } 103 132 … … 129 158 return true; 130 159 } 160 161 ALWAYS_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 } 131 171 132 172 } } // namespace JSC::Wasm -
trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp
r208238 r208401 32 32 #include "WasmB3IRGenerator.h" 33 33 #include "WasmCallingConvention.h" 34 #include "WasmMemory.h" 34 35 #include "WasmModuleParser.h" 35 36 #include "WasmValidate.h" 36 37 #include <wtf/DataLog.h> 38 #include <wtf/text/StringBuilder.h> 37 39 38 40 namespace JSC { namespace Wasm { … … 49 51 if (verbose) 50 52 dataLogLn("Starting plan."); 51 ModuleParser moduleParser(source, sourceLength); 52 if (!moduleParser.parse()) { 53 dataLogLn("Parsing module failed: ", moduleParser.errorMessage()); 54 m_errorMessage = moduleParser.errorMessage(); 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()); 61 } 62 if (verbose) 63 dataLogLn("Parsed module."); 64 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(); 55 71 return; 56 72 } 57 73 58 if (verbose) 59 dataLogLn("Parsed module."); 60 61 for (const FunctionInformation& info : moduleParser.functionInformation()) { 74 for (const FunctionInformation& info : m_moduleInformation->functions) { 62 75 if (verbose) 63 dataLogLn("Processing func ion starting at: ", info.start, " and ending at: ", info.end);76 dataLogLn("Processing function starting at: ", info.start, " and ending at: ", info.end); 64 77 const uint8_t* functionStart = source + info.start; 65 78 size_t functionLength = info.end - info.start; 66 79 ASSERT(functionLength <= sourceLength); 67 80 68 String error = validateFunction(functionStart, functionLength, info.signature, m oduleParser.functionInformation());81 String error = validateFunction(functionStart, functionLength, info.signature, m_moduleInformation->functions); 69 82 if (!error.isNull()) { 70 83 m_errorMessage = error; … … 72 85 } 73 86 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)); 75 88 } 76 89 77 90 // 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) { 79 92 FunctionCompilation* function = functionPtr.get(); 80 93 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())); 82 95 } 83 96 84 m_memory = WTFMove(moduleParser.memory());85 97 m_failed = false; 86 98 } -
trunk/Source/JavaScriptCore/wasm/WasmPlan.h
r207929 r208401 39 39 class Plan { 40 40 public: 41 typedef Vector<std::unique_ptr<FunctionCompilation>> CompiledFunctions;42 43 41 JS_EXPORT_PRIVATE Plan(VM&, Vector<uint8_t>); 44 42 JS_EXPORT_PRIVATE Plan(VM&, const uint8_t*, size_t); … … 51 49 return m_errorMessage; 52 50 } 53 size_t resultSize() const 51 52 std::unique_ptr<ModuleInformation>& getModuleInformation() 54 53 { 55 54 RELEASE_ASSERT(!failed()); 56 return m_result.size(); 57 } 58 const FunctionCompilation* result(size_t n) const 59 { 60 RELEASE_ASSERT(!failed()); 61 return m_result.at(n).get(); 55 return m_moduleInformation; 62 56 } 63 57 const Memory* memory() const 64 58 { 65 59 RELEASE_ASSERT(!failed()); 66 return m_m emory.get();60 return m_moduleInformation->memory.get(); 67 61 } 68 69 CompiledFunctions* getFunctions() 62 size_t compiledFunctionCount() const 70 63 { 71 64 RELEASE_ASSERT(!failed()); 72 return &m_result;65 return m_compiledFunctions.size(); 73 66 } 74 std::unique_ptr<Memory>* getMemory()67 const FunctionCompilation* compiledFunction(size_t i) const 75 68 { 76 69 RELEASE_ASSERT(!failed()); 77 return &m_memory; 70 return m_compiledFunctions.at(i).get(); 71 } 72 CompiledFunctions& getCompiledFunctions() 73 { 74 RELEASE_ASSERT(!failed()); 75 return m_compiledFunctions; 78 76 } 79 77 80 78 private: 81 CompiledFunctions m_result; 82 std::unique_ptr<Memory> m_memory; 79 std::unique_ptr<ModuleInformation> m_moduleInformation; 80 CompiledFunctions m_compiledFunctions; 81 83 82 bool m_failed { true }; 84 83 String m_errorMessage; -
trunk/Source/JavaScriptCore/wasm/WasmSections.h
r207693 r208401 30 30 namespace JSC { namespace Wasm { 31 31 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 32 45 struct Sections { 33 46 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 38 50 Unknown 39 51 }; -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp
r207929 r208401 36 36 namespace JSC { 37 37 38 JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, Vector<std::unique_ptr<Wasm::FunctionCompilation>>* compiledFunctions, std::unique_ptr<Wasm::Memory>* memory)38 JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>& moduleInformation, Wasm::CompiledFunctions& compiledFunctions) 39 39 { 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); 41 41 instance->finishCreation(vm); 42 42 return instance; … … 48 48 } 49 49 50 JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, Vector<std::unique_ptr<Wasm::FunctionCompilation>>* compiledFunctions, std::unique_ptr<Wasm::Memory>* memory)50 JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>& moduleInformation, Wasm::CompiledFunctions& compiledFunctions) 51 51 : Base(vm, structure) 52 , m_ compiledFunctions(WTFMove(*compiledFunctions))53 , m_ memory(WTFMove(*memory))52 , m_moduleInformation(WTFMove(moduleInformation)) 53 , m_compiledFunctions(WTFMove(compiledFunctions)) 54 54 { 55 55 } -
trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h
r207929 r208401 30 30 #include "JSDestructibleObject.h" 31 31 #include "JSObject.h" 32 #include "WasmFormat.h" 32 33 33 34 namespace JSC { 34 35 namespace Wasm {36 struct FunctionCompilation;37 class Memory;38 }39 35 40 36 class JSWebAssemblyModule : public JSDestructibleObject { … … 42 38 typedef JSDestructibleObject Base; 43 39 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&); 45 41 static Structure* createStructure(VM&, JSGlobalObject*, JSValue); 46 42 47 43 DECLARE_INFO; 48 44 45 const Wasm::ModuleInformation* moduleInformation() const 46 { 47 return m_moduleInformation.get(); 48 } 49 49 50 protected: 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&); 51 52 void finishCreation(VM&); 52 53 static void destroy(JSCell*); 53 54 static void visitChildren(JSCell*, SlotVisitor&); 54 55 55 private: 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; 58 58 }; 59 59 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
r207929 r208401 65 65 return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("second argument to WebAssembly.Instance must be undefined or an Object"), defaultSourceAppender, runtimeTypeForValue(importArgument)))); 66 66 67 // FIXME use the importObject. https://bugs.webkit.org/show_bug.cgi?id=16403968 67 // 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)))); 69 70 70 71 // FIXME String things from https://bugs.webkit.org/show_bug.cgi?id=164023 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp
r207825 r208401 48 48 VM& vm = state->vm(); 49 49 auto scope = DECLARE_THROW_SCOPE(vm); 50 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164134 50 51 return JSValue::encode(throwException(state, scope, createError(state, ASCIILiteral("WebAssembly doesn't yet implement the Memory constructor property")))); 51 52 } -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp
r207929 r208401 74 74 return JSValue::encode(throwException(state, scope, createWebAssemblyCompileError(state, plan.errorMessage()))); 75 75 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=16402377 78 76 // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module. 79 77 auto* structure = InternalFunction::createSubclassStructure(state, state->newTarget(), asInternalFunction(state->callee())->globalObject()->WebAssemblyModuleStructure()); 80 78 RETURN_IF_EXCEPTION(scope, encodedJSValue()); 81 79 82 return JSValue::encode(JSWebAssemblyModule::create(vm, structure, plan.get Functions(), plan.getMemory()));80 return JSValue::encode(JSWebAssemblyModule::create(vm, structure, plan.getModuleInformation(), plan.getCompiledFunctions())); 83 81 } 84 82 -
trunk/Source/JavaScriptCore/wasm/js/WebAssemblyTableConstructor.cpp
r207825 r208401 48 48 VM& vm = state->vm(); 49 49 auto scope = DECLARE_THROW_SCOPE(vm); 50 // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135 50 51 return JSValue::encode(throwException(state, scope, createError(state, ASCIILiteral("WebAssembly doesn't yet implement the Table constructor property")))); 51 52 }
Note: See TracChangeset
for help on using the changeset viewer.