Changeset 208401 in webkit


Ignore:
Timestamp:
Nov 4, 2016 3:12:12 PM (7 years ago)
Author:
jfbastien@apple.com
Message:

WebAssembly JS API: implement more sections
https://bugs.webkit.org/show_bug.cgi?id=164023

Reviewed by Keith Miller.

On the JSC side:

  • Put in parser stubs for all WebAssembly sections.
  • Parse Import, Export sections.
  • 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.
  • Encapsulate all parsed module information into its own structure, making it easier to pass around (from parser to Plan to Module to Instance).
  • Create WasmFormat.cpp to hold parsed module information's dtor to avoid including WasmMemory.h needlessly.

JSTests:

  • parseCode: avoid overflow through function size.
  • Remove all remainders of polyfill-prototype-1, and update license.
  • Add missing WasmOps.h and WasmValidateInlines.h auto-generation for cmake build.

On the Builder.js testing side:

  • Implement Type, Import (function only), Export (function only) sections.
  • Check section order and uniqueness.
  • Optionally auto-generate the Type section from subsequent Export / Import / Code entries.
  • Allow re-exporting an import.
  • wasm/Builder.js: build type, import, and export sections

(const._normalizeFunctionSignature):

  • wasm/Builder_WebAssemblyBinary.js: Added. Forked from Builder.js

(const.emitters.Type):
(const.emitters.Import):
(const.emitters.Function):
(const.emitters.Table):
(const.emitters.Memory):
(const.emitters.Global):
(const.emitters.Export):
(const.emitters.Start):
(const.emitters.Element):
(const.emitters.Code):
(const.emitters.Data):
(export.const.Binary):

  • wasm/LowLevelBinary.js: Add a few useful outputs

(export.default.LowLevelBinary.prototype.varuint1):
(export.default.LowLevelBinary.prototype.varint7):

  • wasm/WASM.js: value type and external kind helpers
  • wasm/assert.js: array element-wise equality comparison

(const._eq):

  • wasm/js-api/test_Module.js:

(ModuleWithImports):

  • 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

(const.assertOpThrows):
(SectionsWithSameCustomName):
(TwoTypeSections):
(EmptyImportSection):
(ImportBeforeTypeSections):

  • wasm/self-test/test_BuilderWebAssembly.js: remove a test which wasn't helpful and is now obsolete

(CustomSection):

Source/JavaScriptCore:

  • Remove all remainders of polyfill-prototype-1, and update license.
  • Add missing WasmOps.h and WasmValidateInlines.h auto-generation for cmake build.

On the Builder.js testing side:

  • Implement Type, Import (function only), Export (function only) sections.
  • Check section order and uniqueness.
  • Optionally auto-generate the Type section from subsequent Export / Import / Code entries.
  • Allow re-exporting an import.
  • CMakeLists.txt: missing auto-genration
  • JavaScriptCore.xcodeproj/project.pbxproj: merge conflict
  • testWasm.cpp: update for API changes, no functional change

(checkPlan):
(runWasmTests):

  • wasm/WasmFormat.cpp: add a dtor which requires extra headers which I'd rather not include in WasmFormat.h

(JSC::Wasm::ModuleInformation::~ModuleInformation):

  • 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)

(JSC::Wasm::External::isValid):

  • wasm/WasmModuleParser.cpp: simplify some, make names consistent with the WebAssembly section names, check memory allocations so they can fail early

(JSC::Wasm::ModuleParser::parse):
(JSC::Wasm::ModuleParser::parseType):
(JSC::Wasm::ModuleParser::parseImport):
(JSC::Wasm::ModuleParser::parseFunction):
(JSC::Wasm::ModuleParser::parseTable):
(JSC::Wasm::ModuleParser::parseMemory):
(JSC::Wasm::ModuleParser::parseGlobal):
(JSC::Wasm::ModuleParser::parseExport):
(JSC::Wasm::ModuleParser::parseStart):
(JSC::Wasm::ModuleParser::parseElement):
(JSC::Wasm::ModuleParser::parseCode): avoid overflow through function size.
(JSC::Wasm::ModuleParser::parseData):

  • wasm/WasmModuleParser.h:

(JSC::Wasm::ModuleParser::moduleInformation):

  • wasm/WasmParser.h:

(JSC::Wasm::Parser::consumeUTF8String): add as required by spec
(JSC::Wasm::Parser::parseExternalKind): add as per spec

  • wasm/WasmPlan.cpp:

(JSC::Wasm::Plan::Plan): fix some ownership, improve some error messages

  • wasm/WasmPlan.h: fix some ownership

(JSC::Wasm::Plan::getModuleInformation):
(JSC::Wasm::Plan::getMemory):
(JSC::Wasm::Plan::compiledFunctionCount):
(JSC::Wasm::Plan::compiledFunction):
(JSC::Wasm::Plan::getCompiledFunctions):

  • wasm/WasmSections.h: macroize with description, so that error messages are super pretty. This could be auto-generated.
  • wasm/js/JSWebAssemblyModule.cpp:

(JSC::JSWebAssemblyModule::create): take module information
(JSC::JSWebAssemblyModule::JSWebAssemblyModule): ditto

  • wasm/js/JSWebAssemblyModule.h:

(JSC::JSWebAssemblyModule::moduleInformation):

  • wasm/js/WebAssemblyInstanceConstructor.cpp:

(JSC::constructJSWebAssemblyInstance): check that modules with imports are instantiated with an import object, as per spec. This needs to be tested.

  • wasm/js/WebAssemblyMemoryConstructor.cpp:

(JSC::constructJSWebAssemblyMemory):

  • wasm/js/WebAssemblyModuleConstructor.cpp:

(JSC::constructJSWebAssemblyModule):

  • wasm/js/WebAssemblyTableConstructor.cpp:

(JSC::constructJSWebAssemblyTable):

Location:
trunk
Files:
1 added
28 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r208377 r208401  
     12016-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
    1582016-11-03  Mark Lam  <mark.lam@apple.com>
    259
  • trunk/JSTests/wasm/Builder.js

    r207363 r208401  
    2424 */
    2525
    26 import LowLevelBinary from 'LowLevelBinary.js';
     26import * as assert from 'assert.js';
     27import * as BuildWebAssembly from 'Builder_WebAssemblyBinary.js';
    2728import * as WASM from 'WASM.js';
    2829
     
    4445const _unknownSectionId = 0;
    4546
    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
     47const _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
     58const _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
     92const _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
     105const _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;
    76145                }
    77                 funcBin.apply();
    78146            }
    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    };
    91155};
    92156
     
    99163        this.setPreamble(preamble);
    100164        this._sections = [];
     165        this._functionIndexSpace = {};
     166        this._functionIndexSpaceCount = 0;
    101167        this._registerSectionBuilders();
    102168    }
     
    109175        return this;
    110176    }
     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    }
    111190    _registerSectionBuilders() {
    112191        for (const section in WASM.description.section) {
    113192            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;
    114234            case "Code":
    115235                this[section] = function() {
     
    117237                    const builder = this;
    118238                    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 };
    124280                            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,
    127286                                code: []
    128287                            };
    129288                            s.data.push(func);
     289                            builder._registerFunctionToIndexSpace(functionName);
    130290                            let functionBuilder = {};
    131291                            for (const op in WASM.description.opcode) {
     
    175335                                } : () => {};
    176336                                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}`);
    178338                                    for (let idx = 0; idx !== imm.length; ++idx) {
    179339                                        const got = imms[idx];
     
    181341                                        switch (expect.name) {
    182342                                        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`);
    184344                                            // FIXME check function indices. https://bugs.webkit.org/show_bug.cgi?id=163421
    185345                                            break;
     
    187347                                        case "global_index": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`);
    188348                                        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;
    190352                                        case "flags": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`);
    191353                                        case "offset": throw new Error(`Unimplemented: "${expect.name}" on "${op}"`);
     
    227389            const unknownBuilder =  {
    228390                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                }
    230396            };
    231397            return unknownBuilder;
     
    235401        const name = typeof(nameOrNumber) === "string" ? nameOrNumber : "";
    236402        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        }
    237417        const s = Object.assign({ name: name, id: number, data: [] }, extraObject || {});
    238418        this._sections.push(s);
    239419        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        }
    240435    }
    241436    optimize() {
     
    255450        throw new Error("asm.js not implemented yet");
    256451    }
    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  
    2828
    2929export const varuintMin = 0;
     30export const varint7Min = -0b1000000;
     31export const varint7Max = 0b111111;
    3032export const varuint7Max = 0b1111111;
    3133export const varuintMax = ((((1 << 31) >>> 0) - 1) * 2) + 1;
     
    130132        } while (true);
    131133    }
     134    varuint1(v) {
     135        if (v !== 0 && v !== 1)
     136            throw new RangeError(`Invalid varuint1 ${v} range is [0, 1]`);
     137        this.varuint(v);
     138    }
     139    varint7(v) {
     140        if (v < varint7Min || varint7Max < v)
     141            throw new RangeError(`Invalid varint7 ${v} range is [${varint7Min}, ${varint7Max}]`);
     142        this.varint(v);
     143    }
    132144    varuint7(v) {
    133145        if (v < varuintMin || varuint7Max < v)
  • trunk/JSTests/wasm/WASM.js

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

    r207825 r208401  
    2424 */
    2525
    26 const _notUndef = (v) => {
    27     if (typeof v === "undefined")
    28         throw new Error("Shouldn't be undefined");
     26const _fail = (msg, extra) => {
     27    throw new Error(msg + (extra ? ": " + extra : ""));
    2928};
    3029
    31 const _isUndef = (v) => {
    32     if (typeof v !== "undefined")
    33         throw new Error("Should be undefined");
     30export const isNotA = (v, t, msg) => {
     31    if (typeof v === t)
     32        _fail(`Shouldn't be ${t}`, msg);
    3433};
    3534
    36 const _eq = (lhs, rhs) => {
    37     if (lhs !== rhs)
    38         throw new Error(`Not the same: "${lhs}" and "${rhs}"`);
     35export const isA = (v, t, msg) => {
     36    if (typeof v !== t)
     37        _fail(`Should be ${t}, got ${typeof(v)}`, msg);
    3938};
    4039
    41 const _ge = (lhs, rhs) => {
    42     _notUndef(lhs);
    43     _notUndef(rhs);
     40export const isNotUndef = (v, msg) => isNotA(v, "undefined", msg);
     41export const isUndef = (v, msg) => isA(v, "undefined", msg);
     42export const notObject = (v, msg) => isNotA(v, "object", msg);
     43export const isObject = (v, msg) => isA(v, "object", msg);
     44export const notString = (v, msg) => isNotA(v, "string", msg);
     45export const isString = (v, msg) => isA(v, "string", msg);
     46export const notNumber = (v, msg) => isNotA(v, "number", msg);
     47export const isNumber = (v, msg) => isA(v, "number", msg);
     48
     49export const hasObjectProperty = (o, p, msg) => {
     50    isObject(o, msg);
     51    isNotUndef(o[p], msg, `expected object to have property ${p}`);
     52};
     53
     54export const isArray = (v, msg) => {
     55    if (!Array.isArray(v))
     56        _fail(`Expected an array, got ${typeof(v)}`, msg);
     57};
     58
     59export const isNotArray = (v, msg) => {
     60    if (Array.isArray(v))
     61        _fail(`Expected to not be an array`, msg);
     62};
     63
     64export const truthy = (v, msg) => {
     65    if (!v)
     66        _fail(`Expected truthy`, msg);
     67};
     68
     69export const falsy = (v, msg) => {
     70    if (v)
     71        _fail(`Expected falsy`, msg);
     72};
     73
     74export 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
     82export const ge = (lhs, rhs, msg) => {
     83    isNotUndef(lhs);
     84    isNotUndef(rhs);
    4485    if (!(lhs >= rhs))
    45         throw new Error(`Expected: "${lhs}" < "${rhs}"`);
     86        _fail(`Expected: "${lhs}" < "${rhs}"`, msg);
     87};
     88
     89export const le = (lhs, rhs, msg) => {
     90    isNotUndef(lhs);
     91    isNotUndef(rhs);
     92    if (!(lhs <= rhs))
     93        _fail(`Expected: "${lhs}" > "${rhs}"`, msg);
    4694};
    4795
     
    52100        if (e instanceof type && e.message === message)
    53101            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}"`);
    55103    }
    56     throw new Error(`Expected to throw a ${type.name} with message "${message}"`);
     104    _fail(`Expected to throw a ${type.name} with message "${message}"`);
    57105};
    58106
    59 const _instanceof = (obj, type) => obj instanceof type;
     107const _instanceof = (obj, type, msg) => {
     108    if (!(obj instanceof type))
     109        _fail(`Expected a ${typeof(type)}, got ${typeof obj}`);
     110};
    60111
    61112// Use underscore names to avoid clashing with builtin names.
    62113export {
    63     _notUndef as notUndef,
    64     _isUndef as isUndef,
    65     _eq as eq,
    66     _ge as ge,
    67114    _throws as throws,
    68115    _instanceof as instanceof,
  • trunk/JSTests/wasm/js-api/test_Module.js

    r207846 r208401  
    88    assert.instanceof(module, WebAssembly.Module);
    99})();
     10
     11(function ModuleWithImports() {
     12    const builder = (new Builder())
     13        .Type().End()
     14        .Import()
     15            .Function("foo", "bar", { params: [] })
     16        .End();
     17    const bin = builder.WebAssembly().get();
     18    const module = new WebAssembly.Module(bin);
     19})();
  • trunk/JSTests/wasm/js-api/test_basic_api.js

    r207929 r208401  
    2929
    3030
    31 assert.notUndef(WebAssembly);
     31assert.isNotUndef(WebAssembly);
    3232checkOwnPropertyDescriptor(utilities.global, "WebAssembly", { typeofvalue: "object", writable: true, configurable: true, enumerable: false });
    3333assert.eq(String(WebAssembly), "[object WebAssembly]");
     
    3838
    3939for (const f in functionProperties) {
    40     assert.notUndef(WebAssembly[f]);
     40    assert.isNotUndef(WebAssembly[f]);
    4141    assert.eq(WebAssembly[f].name, f);
    4242    assert.eq(WebAssembly[f].length, functionProperties[f].length);
     
    4444
    4545for (const c in constructorProperties) {
    46     assert.notUndef(WebAssembly[c]);
     46    assert.isNotUndef(WebAssembly[c]);
    4747    assert.eq(WebAssembly[c].name, c);
    4848    assert.eq(WebAssembly[c].length, constructorProperties[c].length);
     
    6767        for (const invalid of invalidInstanceImports)
    6868            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);
    7070        checkOwnPropertyDescriptor(instance, "exports", { typeofvalue: "object", writable: true, configurable: true, enumerable: true });
    7171        assert.isUndef(instance.exports.__proto__);
  • trunk/JSTests/wasm/self-test/test_BuilderJSON.js

    r207572 r208401  
    33
    44const assertOpThrows = (opFn, message) => {
    5     let f = (new Builder()).Code().Function();
     5    let f = (new Builder()).Type().End().Code().Function();
    66    assert.throws(opFn, Error, message, f);
    77};
     
    1010    const b = new Builder();
    1111    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);
    1616    assert.eq(j.section.length, 0);
    1717})();
     
    2121    const j = JSON.parse(b.json());
    2222    assert.eq(j.preamble["magic number"], 1337);
    23     assert.notUndef(j.preamble.version);
     23    assert.isNotUndef(j.preamble.version);
    2424})();
    2525
     
    2828    const j = JSON.parse(b.json());
    2929    assert.eq(j.preamble["version"], 1337);
    30     assert.notUndef(j.preamble.version);
     30    assert.isNotUndef(j.preamble.version);
    3131})();
    3232
     
    5858
    5959(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"`);
    6962})();
    7063
     
    8780})();
    8881
     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
    89244(function EmptyCodeSection() {
    90245    const b = new Builder();
     
    98253(function CodeSectionWithEmptyFunction() {
    99254    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");
    105261    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);
    109271})();
    110272
    111273(function CodeSectionWithEmptyFunctionWithParameters() {
    112274    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);
    118280    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);
    125291})();
    126292
    127293(function InvalidFunctionParameters() {
    128     for (let invalid in ["", "void", "bool", "any", "struct"]) {
     294    for (let invalid of ["", "void", "bool", "any", "struct", 0, 3.14, undefined, [], {}]) {
    129295        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`);
    137297    }
    138298})();
     
    140300(function SimpleFunction() {
    141301    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()
    146364        .End();
    147365    const j = JSON.parse(b.json());
    148366    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"`);
    177387})();
    178388
    179389(function TwoBuildersAtTheSameTime() {
    180390    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());
    182392    f[0].Nop();
    183393    f[1].Return().End().End();
    184394    f[0].Nop().End().End();
    185395    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");
    193403})();
    194404
    195405(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`);
    197407})();
    198408
    199409(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.");
    201411})();
    202412
    203413(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`);
    205415})();
    206416
    207417(function UncheckedOpcodeArgumentsNotEnough() {
    208     (new Builder()).setChecked(false).Code().Function().I32Const();
     418    (new Builder()).setChecked(false).Type().End().Code().Function().I32Const();
    209419})();
    210420
    211421(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");
    220430})();
    221431
    222432(function CallInvalid() {
    223433    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`);
    225435})();
    226436
    227437(function I32ConstValid() {
    228438    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();
    230440        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);
    235445    }
    236446})();
     
    238448(function I32ConstInvalid() {
    239449    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`);
    241451})();
    242452
     
    245455(function F32ConstValid() {
    246456    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();
    248458        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);
    253463    }
    254464})();
     
    256466(function F32ConstInvalid() {
    257467    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`);
    259469})();
    260470
    261471(function F64ConstValid() {
    262472    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();
    264474        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);
    269479    }
    270480})();
     
    272482(function F64ConstInvalid() {
    273483    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`);
    275485})();
    276486
    277487(function CallOneFromStack() {
    278     const b = (new Builder()).Code()
    279         .Function(["i32"])
     488    const b = (new Builder()).Type().End().Code()
     489        .Function({ params: ["i32"] })
    280490            .I32Const(42)
    281491            .Call(0)
     
    283493    .End();
    284494    const j = JSON.parse(b.json());
    285     assert.eq(j.section[0].data[0].code.length, 3);
    286     assert.eq(j.section[0].data[0].code[0].name, "i32.const");
    287     assert.eq(j.section[0].data[0].code[0].immediates[0], 42);
    288     assert.eq(j.section[0].data[0].code[1].name, "call");
    289     // FIXME: assert.eq(j.section[0].data[0].code[1].arguments.length, 1); https://bugs.webkit.org/show_bug.cgi?id=163267
    290     assert.eq(j.section[0].data[0].code[1].immediates.length, 1);
    291     assert.eq(j.section[0].data[0].code[1].immediates[0], 0);
    292     assert.eq(j.section[0].data[0].code[2].name, "end");
     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");
    293503})();
    294504
     
    302512
    303513(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"] })
    306516              .I32Const(42).I32Const(1337).I32Const(0xBEEF).I32Const(0xFFFF)
    307517              .Call(0)
     
    309519    .End();
    310520    const j = JSON.parse(b.json());
    311     assert.eq(j.section[0].data[0].code.length, 6);
    312     assert.eq(j.section[0].data[0].code[4].name, "call");
    313     // FIXME: assert.eq(j.section[0].data[0].code[4].arguments.length, 4); https://bugs.webkit.org/show_bug.cgi?id=163267
    314     assert.eq(j.section[0].data[0].code[4].immediates.length, 1);
    315     assert.eq(j.section[0].data[0].code[4].immediates[0], 0);
     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);
    316526})();
    317527
    318528(function OpcodeAdd() {
    319     const b = (new Builder()).Code()
     529    const b = (new Builder()).Type().End().Code()
    320530          .Function()
    321531              .I32Const(42).I32Const(1337)
     
    325535    .End();
    326536    const j = JSON.parse(b.json());
    327     assert.eq(j.section[0].data[0].code.length, 5);
    328     assert.eq(j.section[0].data[0].code[2].name, "i32.add");
    329     // FIXME: assert.eq(j.section[0].data[0].code[2].arguments.length, 2); https://bugs.webkit.org/show_bug.cgi?id=163267
    330     assert.eq(j.section[0].data[0].code[3].name, "return");
     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");
    331541    // FIXME check return. https://bugs.webkit.org/show_bug.cgi?id=163267
    332542})();
    333543
    334544(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");
    339549})();
    340550
    341551(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();
    348558})();
    349559
    350560(function OpcodeSelect() {
    351     const b = (new Builder()).Code().Function()
     561    const b = (new Builder()).Type().End().Code().Function()
    352562        .I32Const(1).I32Const(2).I32Const(0)
    353563        .Select()
     
    356566    .End();
    357567    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");
    360570})();
    361571
  • trunk/JSTests/wasm/self-test/test_BuilderWebAssembly.js

    r207363 r208401  
    3131               "00000010 00 41 00 49 00 de ad c0 fe                       |·A·I·····       |"].join("\n"));
    3232})();
    33 
    34 (function Basic() {
    35     const bin = (new Builder())
    36         .Code()
    37             .Function()
    38                 .Nop()
    39                 .Nop()
    40             .End()
    41         .End()
    42         .WebAssembly();
    43     assert.eq(bin.hexdump().trim(),
    44               "00000000 00 61 73 6d 0c 00 00 00 0a 06 01 04 00 0a 0a 0f  |·asm············|");
    45 })();
  • trunk/JSTests/wasm/self-test/test_WASM.js

    r207363 r208401  
    22import * as WASM from '../WASM.js';
    33
    4 assert.notUndef(WASM.description);
    5 assert.notUndef(WASM.valueType);
     4assert.isNotUndef(WASM.description);
     5assert.isNotUndef(WASM.valueType);
    66assert.ge(WASM.valueType.length, 4);
    77
     
    1919];
    2020for (const e of expectedFields) {
    21     assert.notUndef(WASM.description[e]);
     21    assert.isNotUndef(WASM.description[e]);
    2222    if (typeof(WASM.description[e]) !== "object")
    2323        throw new Error(`Expected description to contain field "${e}"`);
     
    3333for (const op in WASM.description.opcode)
    3434    for (const e of expectedOpFields)
    35         assert.notUndef(WASM.description.opcode[op][e]);
     35        assert.isNotUndef(WASM.description.opcode[op][e]);
    3636
    3737// FIXME: test for field "b3op" when all arithmetic/ comparison ops have them. https://bugs.webkit.org/show_bug.cgi?id=146064
    3838
    39 assert.notUndef(WASM.sections);
    40 assert.notUndef(WASM.sectionEncodingType);
     39assert.isNotUndef(WASM.sections);
     40assert.isNotUndef(WASM.sectionEncodingType);
    4141for (const section of WASM.sections)
    4242    assert.eq(WASM.sectionEncodingType, WASM.description.section[section].type);
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r208373 r208401  
    11401140endif ()
    11411141
     1142# WebAssembly generator
     1143
     1144macro(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})
     1153endmacro()
     1154GENERATE_PYTHON(${CMAKE_CURRENT_SOURCE_DIR}/wasm/generateWasmOpsHeader.py ${CMAKE_CURRENT_SOURCE_DIR}/wasm/wasm.json ${DERIVED_SOURCES_JAVASCRIPTCORE_DIR}/WasmOps.h)
     1155GENERATE_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
    11421159set(HASH_LUT_GENERATOR ${CMAKE_CURRENT_SOURCE_DIR}/create_hash_table)
    11431160macro(GENERATE_HASH_LUT _input _output)
  • trunk/Source/JavaScriptCore/ChangeLog

    r208377 r208401  
     12016-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
    1752016-11-03  Mark Lam  <mark.lam@apple.com>
    276
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r208373 r208401  
    12961296                53FF7F991DBFCD9000A26CCC /* WasmValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FF7F981DBFCD9000A26CCC /* WasmValidate.h */; };
    12971297                53FF7F9B1DBFD2B900A26CCC /* WasmValidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */; };
    1298                 53FF7F9D1DC00DB100A26CCC /* WasmFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */; };
    12991298                5B70CFDE1DB69E6600EC23F9 /* JSAsyncFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */; };
    13001299                5B70CFDF1DB69E6600EC23F9 /* JSAsyncFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */; };
     
    19911990                AD2FCC301DB83D4900B3E736 /* JSWebAssembly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCC2E1DB839F700B3E736 /* JSWebAssembly.cpp */; };
    19921991                AD2FCC311DB83D4900B3E736 /* JSWebAssembly.h in Headers */ = {isa = PBXBuildFile; fileRef = AD2FCC2F1DB839F700B3E736 /* JSWebAssembly.h */; };
     1992                AD2FCC331DC4045400B3E736 /* WasmFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */; };
    19931993                AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
    19941994                ADDB1F6318D77DBE009B58A8 /* OpaqueRootSet.h in Headers */ = {isa = PBXBuildFile; fileRef = ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    36633663                53FF7F981DBFCD9000A26CCC /* WasmValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmValidate.h; sourceTree = "<group>"; };
    36643664                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>"; };
    36663665                5B70CFD81DB69E5C00EC23F9 /* JSAsyncFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAsyncFunction.h; sourceTree = "<group>"; };
    36673666                5B70CFD91DB69E5C00EC23F9 /* JSAsyncFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAsyncFunction.cpp; sourceTree = "<group>"; };
     
    44404439                AD2FCC2E1DB839F700B3E736 /* JSWebAssembly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebAssembly.cpp; sourceTree = "<group>"; };
    44414440                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>"; };
    44424442                AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCMapInlines.h; sourceTree = "<group>"; };
    44434443                ADDB1F6218D77DB7009B58A8 /* OpaqueRootSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OpaqueRootSet.h; sourceTree = "<group>"; };
     
    59565956                                53FD04D11D7AB187003287D3 /* WasmCallingConvention.cpp */,
    59575957                                53FD04D21D7AB187003287D3 /* WasmCallingConvention.h */,
    5958                                 53FF7F9C1DC00DB100A26CCC /* WasmFormat.cpp */,
     5958                                AD2FCC321DC4045300B3E736 /* WasmFormat.cpp */,
    59595959                                7BC547D21B69599B00959B58 /* WasmFormat.h */,
    59605960                                53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */,
     
    98759875                                0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */,
    98769876                                0FF8BDEA1AD4CF7100DFE884 /* InferredValue.cpp in Sources */,
     9877                                AD2FCC331DC4045400B3E736 /* WasmFormat.cpp in Sources */,
    98779878                                9E729407190F01A5001A91B5 /* InitializeThreading.cpp in Sources */,
    98789879                                A513E5B7185B8BD3007E95AD /* InjectedScript.cpp in Sources */,
  • trunk/Source/JavaScriptCore/testWasm.cpp

    r208341 r208401  
    277277    }
    278278
    279     if (plan.resultSize() != expectedNumberOfFunctions) {
     279    if (plan.compiledFunctionCount() != expectedNumberOfFunctions) {
    280280        dataLogLn("Incorrect number of functions");
    281281        CRASH();
     
    283283
    284284    for (unsigned i = 0; i < expectedNumberOfFunctions; ++i) {
    285         if (!plan.result(i)) {
     285        if (!plan.compiledFunction(i)) {
    286286            dataLogLn("Function at index, " , i, " failed to compile correctly");
    287287            CRASH();
     
    321321
    322322        // 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));
    325325    }
    326326
     
    348348
    349349        // 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));
    352352    }
    353353
     
    386386
    387387        // 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);
    396396    }
    397397
     
    416416
    417417        // 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));
    422422    }
    423423
     
    442442
    443443        // 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));
    448448    }
    449449
     
    473473
    474474        // 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);
    480480    }
    481481
     
    504504
    505505        // 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);
    510510    }
    511511
     
    527527
    528528        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)) {
    530530            dataLogLn("Module failed to compile correctly.");
    531531            CRASH();
     
    533533
    534534        // 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);
    541541    }
    542542
     
    561561
    562562        // 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);
    569569    }
    570570
     
    590590
    591591        // 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);
    595595    }
    596596
     
    617617
    618618        // 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);
    622622    }
    623623
     
    658658        unsigned offset = sizeof(uint32_t);
    659659        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) });
    661661        offset /= sizeof(uint32_t);
    662662        CHECK_EQ(memory[offset - 1], 0u);
     
    667667        length = 10;
    668668        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) });
    670670        offset /= sizeof(uint32_t);
    671671        CHECK_EQ(memory[offset - 1], 100u);
     
    710710        unsigned offset = 1;
    711711        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) });
    713713        CHECK_EQ(memory[offset - 1], 0u);
    714714        CHECK_EQ(memory[offset + length], 0u);
     
    718718        length = 10;
    719719        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) });
    721721        CHECK_EQ(memory[offset - 1], 100u);
    722722        CHECK_EQ(memory[offset + length], 0u);
     
    748748
    749749        // 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);
    753753    }
    754754
     
    775775
    776776        // 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);
    780780    }
    781781
     
    802802
    803803        // 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);
    808808    }
    809809
     
    830830
    831831        // 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);
    835835    }
    836836
     
    871871        unsigned offset = sizeof(uint32_t);
    872872        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) });
    874874        offset /= sizeof(uint32_t);
    875875        CHECK_EQ(memory[offset - 1], 0u);
     
    880880        length = 10;
    881881        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) });
    883883        offset /= sizeof(uint32_t);
    884884        CHECK_EQ(memory[offset - 1], 100u);
     
    923923        unsigned offset = 1;
    924924        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) });
    926926        CHECK_EQ(memory[offset - 1], 0u);
    927927        CHECK_EQ(memory[offset + length], 0u);
     
    931931        length = 10;
    932932        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) });
    934934        CHECK_EQ(memory[offset - 1], 100u);
    935935        CHECK_EQ(memory[offset + length], 0u);
     
    961961
    962962        // 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);
    966966    }
    967967
     
    988988
    989989        // 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);
    993993    }
    994994
     
    10151015
    10161016        // 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);
    10251025    }
    10261026
     
    10531053
    10541054        // 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);
    10631063    }
    10641064
     
    10771077
    10781078        // 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);
    10801080    }
    10811081
     
    10951095
    10961096        // 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);
    10981098    }
    10991099
     
    11121112
    11131113        // 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);
    11151115    }
    11161116
     
    11291129
    11301130        // 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);
    11321132    }
    11331133
     
    11451145
    11461146        // 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());
    11511151    }
    11521152
     
    11711171
    11721172        // 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);
    11751175    }
    11761176
     
    12041204
    12051205        // 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);
    12101210    }
    12111211
     
    12451245
    12461246        // 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);
    12551255    }
    12561256
     
    12951295
    12961296        // 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);
    13051305    }
    13061306
  • trunk/Source/JavaScriptCore/wasm/WasmFormat.cpp

    r208238 r208401  
    2525
    2626#include "config.h"
     27
    2728#include "WasmFormat.h"
    2829
    2930#if ENABLE(WEBASSEMBLY)
     31
     32#include "WasmMemory.h"
    3033
    3134namespace JSC { namespace Wasm {
     
    4750}
    4851
     52ModuleInformation::~ModuleInformation() { }
     53
    4954} } // namespace JSC::Wasm
    5055
    51 #endif // ENABLE(B3_JIT)
     56#endif // ENABLE(WEBASSEMBLY)
  • trunk/Source/JavaScriptCore/wasm/WasmFormat.h

    r208238 r208401  
    2222 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    2323 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    24  *
    25  * =========================================================================
    26  *
    27  * Copyright (c) 2015 by the repository authors of
    28  * WebAssembly/polyfill-prototype-1.
    29  *
    30  * Licensed under the Apache License, Version 2.0 (the "License");
    31  * you may not use this file except in compliance with the License.
    32  * You may obtain a copy of the License at
    33  *
    34  *     http://www.apache.org/licenses/LICENSE-2.0
    35  *
    36  * Unless required by applicable law or agreed to in writing, software
    37  * distributed under the License is distributed on an "AS IS" BASIS,
    38  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    39  * See the License for the specific language governing permissions and
    40  * limitations under the License.
    4124 */
    4225
     
    9982
    10083const char* toString(Type);
     84   
     85struct External {
     86    enum Kind : uint8_t {
     87        Function = 0,
     88        Table = 1,
     89        Memory = 2,
     90        Global = 3,
     91    };
     92    template<typename Int>
     93    static bool isValid(Int val)
     94    {
     95        switch (val) {
     96        case Function:
     97        case Table:
     98        case Memory:
     99        case Global:
     100            return true;
     101        default:
     102            return false;
     103        }
     104    }
     105   
     106    static_assert(Function == 0, "Wasm needs Function to have the value 0");
     107    static_assert(Table    == 1, "Wasm needs Table to have the value 1");
     108    static_assert(Memory   == 2, "Wasm needs Memory to have the value 2");
     109    static_assert(Global   == 3, "Wasm needs Global to have the value 3");
     110};
    101111
    102112struct Signature {
     
    104114    Vector<Type> arguments;
    105115};
    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   
     117struct Import {
     118    String module;
     119    String field;
     120    External::Kind kind;
     121    union {
     122        Signature* functionSignature;
     123        // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=164135
     124        // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=164134
     125        // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
     126    };
    124127};
    125128
     
    129132    size_t end;
    130133};
     134
     135class Memory;
     136
     137struct Export {
     138    String field;
     139    External::Kind kind;
     140    union {
     141        Signature* functionSignature;
     142        // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=164135
     143        // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=164134
     144        // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
     145    };
     146};
     147
     148struct 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
     158struct FunctionCompilation;
     159typedef Vector<std::unique_ptr<FunctionCompilation>> CompiledFunctions;
    131160
    132161struct UnlinkedCall {
  • trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp

    r207927 r208401  
    3030
    3131#include "WasmFormat.h"
     32#include "WasmMemory.h"
    3233#include "WasmOps.h"
    3334#include "WasmSections.h"
     
    4142bool ModuleParser::parse()
    4243{
     44    m_module = std::make_unique<ModuleInformation>();
     45
    4346    const size_t minSize = 8;
    4447    if (length() < minSize) {
     
    112115
    113116        switch (section) {
    114 
    115         case Sections::Memory: {
    116             if (verbose)
    117                 dataLogLn("Parsing Memory.");
    118             if (!parseMemory()) {
    119                 // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
    120                 m_errorMessage = "couldn't parse memory";
    121                 return false;
    122             }
    123             break;
    124         }
    125 
    126         case Sections::FunctionTypes: {
    127             if (verbose)
    128                 dataLogLn("Parsing types.");
    129             if (!parseFunctionTypes()) {
    130                 // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
    131                 m_errorMessage = "couldn't parse types";
    132                 return false;
    133             }
    134             break;
    135         }
    136 
    137         case Sections::Signatures: {
    138             if (verbose)
    139                 dataLogLn("Parsing function signatures.");
    140             if (!parseFunctionSignatures()) {
    141                 // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
    142                 m_errorMessage = "couldn't parse function signatures";
    143                 return false;
    144             }
    145             break;
    146         }
    147 
    148         case Sections::Definitions: {
    149             if (verbose)
    150                 dataLogLn("Parsing function definitions.");
    151             if (!parseFunctionDefinitions()) {
    152                 // FIXME improve error message https://bugs.webkit.org/show_bug.cgi?id=163919
    153                 m_errorMessage = "couldn't parse function definitions";
    154                 return false;
    155             }
    156             break;
    157         }
    158 
    159         case Sections::Unknown:
    160         // FIXME: Delete this when we support all the sections.
    161         default: {
     117        // FIXME improve error message in macro below https://bugs.webkit.org/show_bug.cgi?id=163919
     118#define WASM_SECTION_PARSE(NAME, ID, DESCRIPTION) \
     119        case Sections::NAME: { \
     120            if (verbose) \
     121                dataLogLn("Parsing " DESCRIPTION); \
     122            if (!parse ## NAME()) { \
     123                m_errorMessage = "couldn't parse section " #NAME ": " DESCRIPTION; \
     124                return false; \
     125            } \
     126        } break;
     127        FOR_EACH_WASM_SECTION(WASM_SECTION_PARSE)
     128#undef WASM_SECTION_PARSE
     129
     130        case Sections::Unknown: {
    162131            if (verbose)
    163132                dataLogLn("Unknown section, skipping.");
     
    185154}
    186155
     156bool 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
     215bool 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
     264bool ModuleParser::parseFunction()
     265{
     266    uint32_t count;
     267    if (!parseVarUInt32(count))
     268        return false;
     269    if (!m_module->functions.tryReserveCapacity(count))
     270        return false;
     271
     272    for (uint32_t i = 0; i != count; ++i) {
     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
     286bool ModuleParser::parseTable()
     287{
     288    // FIXME
     289    return true;
     290}
     291
    187292bool ModuleParser::parseMemory()
    188293{
     
    209314
    210315    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
     320bool ModuleParser::parseGlobal()
     321{
     322    // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
     323    return true;
     324}
     325
     326bool ModuleParser::parseExport()
     327{
     328    uint32_t exportCount;
     329    if (!parseVarUInt32(exportCount))
     330        return false;
     331    if (!m_module->exports.tryReserveCapacity(exportCount))
     332        return false;
     333
     334    for (uint32_t exportNumber = 0; exportNumber != exportCount; ++exportNumber) {
     335        Export e;
     336        uint32_t fieldLen;
     337        if (!parseVarUInt32(fieldLen))
     338            return false;
     339        if (!consumeUTF8String(e.field, fieldLen))
     340            return false;
     341        if (!parseExternalKind(e.kind))
     342            return false;
     343        switch (e.kind) {
     344        case External::Function: {
     345            uint32_t functionSignatureIndex;
     346            if (!parseVarUInt32(functionSignatureIndex))
     347                return false;
     348            if (functionSignatureIndex > m_module->signatures.size())
     349                return false;
     350            e.functionSignature = &m_module->signatures[functionSignatureIndex];
     351        } break;
     352        case External::Table:
     353            // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135
     354            break;
     355        case External::Memory:
     356            // FIXME https://bugs.webkit.org/show_bug.cgi?id=164134
     357            break;
     358        case External::Global:
     359            // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
     360            // In the MVP, only immutable global variables can be exported.
     361            break;
     362        }
     363
     364        m_module->exports.uncheckedAppend(e);
     365    }
     366
     367    return true;
     368}
     369
     370bool ModuleParser::parseStart()
     371{
     372    // FIXME https://bugs.webkit.org/show_bug.cgi?id=161709
     373    return true;
     374}
     375
     376bool ModuleParser::parseElement()
     377{
     378    // FIXME https://bugs.webkit.org/show_bug.cgi?id=161709
     379    return true;
     380}
     381
     382bool ModuleParser::parseCode()
    216383{
    217384    uint32_t count;
     
    219386        return false;
    220387
    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) {
    304392        uint32_t functionSize;
    305393        if (!parseVarUInt32(functionSize))
    306394            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];
    309399        info.start = m_offset;
    310400        info.end = m_offset + functionSize;
     
    315405}
    316406
     407bool ModuleParser::parseData()
     408{
     409    // FIXME https://bugs.webkit.org/show_bug.cgi?id=161709
     410    return true;
     411}
     412
    317413} } // namespace JSC::Wasm
    318414
  • trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h

    r207825 r208401  
    2828#if ENABLE(WEBASSEMBLY)
    2929
    30 #include "WasmMemory.h"
     30#include "WasmFormat.h"
    3131#include "WasmOps.h"
    3232#include "WasmParser.h"
     
    5757    }
    5858
    59     const Vector<FunctionInformation>& functionInformation() const
     59    std::unique_ptr<ModuleInformation>& moduleInformation()
    6060    {
    6161        RELEASE_ASSERT(!failed());
    62         return m_functions;
    63     }
    64     std::unique_ptr<Memory>& memory()
    65     {
    66         RELEASE_ASSERT(!failed());
    67         return m_memory;
     62        return m_module;
    6863    }
    6964
    7065private:
    71     bool WARN_UNUSED_RETURN parseMemory();
    72     bool WARN_UNUSED_RETURN parseFunctionTypes();
    73     bool WARN_UNUSED_RETURN parseFunctionSignatures();
    74     bool WARN_UNUSED_RETURN parseFunctionDefinitions();
    75     bool WARN_UNUSED_RETURN parseFunctionDefinition(uint32_t number);
     66#define WASM_SECTION_DECLARE_PARSER(NAME, ID, DESCRIPTION) bool WARN_UNUSED_RETURN parse ## NAME();
     67    FOR_EACH_WASM_SECTION(WASM_SECTION_DECLARE_PARSER)
     68#undef WASM_SECTION_DECLARE_PARSER
    7669
    77     Vector<FunctionInformation> m_functions;
    78     Vector<Signature> m_signatures;
    79     std::unique_ptr<Memory> m_memory;
     70    std::unique_ptr<ModuleInformation> m_module;
    8071    bool m_failed { true };
    8172    String m_errorMessage;
  • trunk/Source/JavaScriptCore/wasm/WasmParser.h

    r207825 r208401  
    3434#include "WasmSections.h"
    3535#include <wtf/LEBDecoder.h>
     36#include <wtf/StdLibExtras.h>
     37#include <wtf/text/WTFString.h>
    3638
    3739namespace JSC { namespace Wasm {
     
    4345    bool WARN_UNUSED_RETURN consumeCharacter(char);
    4446    bool WARN_UNUSED_RETURN consumeString(const char*);
     47    bool WARN_UNUSED_RETURN consumeUTF8String(String&, size_t);
    4548
    4649    bool WARN_UNUSED_RETURN parseVarUInt1(uint8_t& result);
     50    bool WARN_UNUSED_RETURN parseInt7(int8_t& result);
    4751    bool WARN_UNUSED_RETURN parseUInt7(uint8_t& result);
    4852    bool WARN_UNUSED_RETURN parseUInt32(uint32_t& result);
     
    5155
    5256    bool WARN_UNUSED_RETURN parseValueType(Type& result);
     57    bool WARN_UNUSED_RETURN parseExternalKind(External::Kind& result);
    5358
    5459    const uint8_t* source() const { return m_source; }
     
    9398}
    9499
     100ALWAYS_INLINE bool Parser::consumeUTF8String(String& result, size_t stringLength)
     101{
     102    if (stringLength == 0) {
     103        result = String();
     104        return true;
     105    }
     106    if (length() < stringLength || m_offset > length() - stringLength)
     107        return false;
     108    result = String::fromUTF8(static_cast<const LChar*>(&source()[m_offset]), stringLength);
     109    m_offset += stringLength;
     110    if (result.isEmpty())
     111        return false;
     112    return true;
     113}
     114
    95115ALWAYS_INLINE bool Parser::parseUInt32(uint32_t& result)
    96116{
     
    100120    m_offset += 4;
    101121    return true;
     122}
     123
     124ALWAYS_INLINE bool Parser::parseInt7(int8_t& result)
     125{
     126    if (m_offset >= length())
     127        return false;
     128    uint8_t v = source()[m_offset++];
     129    result = (v & 0x40) ? WTF::bitwise_cast<int8_t>(uint8_t(v | 0x80)) : v;
     130    return (v & 0x80) == 0;
    102131}
    103132
     
    129158    return true;
    130159}
     160   
     161ALWAYS_INLINE bool Parser::parseExternalKind(External::Kind& result)
     162{
     163    uint8_t value;
     164    if (!parseUInt7(value))
     165        return false;
     166    if (!External::isValid(value))
     167        return false;
     168    result = static_cast<External::Kind>(value);
     169    return true;
     170}
    131171
    132172} } // namespace JSC::Wasm
  • trunk/Source/JavaScriptCore/wasm/WasmPlan.cpp

    r208238 r208401  
    3232#include "WasmB3IRGenerator.h"
    3333#include "WasmCallingConvention.h"
     34#include "WasmMemory.h"
    3435#include "WasmModuleParser.h"
    3536#include "WasmValidate.h"
    3637#include <wtf/DataLog.h>
     38#include <wtf/text/StringBuilder.h>
    3739
    3840namespace JSC { namespace Wasm {
     
    4951    if (verbose)
    5052        dataLogLn("Starting plan.");
    51     ModuleParser moduleParser(source, sourceLength);
    52     if (!moduleParser.parse()) {
    53         dataLogLn("Parsing module failed: ", moduleParser.errorMessage());
    54         m_errorMessage = moduleParser.errorMessage();
     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();
    5571        return;
    5672    }
    5773
    58     if (verbose)
    59         dataLogLn("Parsed module.");
    60 
    61     for (const FunctionInformation& info : moduleParser.functionInformation()) {
     74    for (const FunctionInformation& info : m_moduleInformation->functions) {
    6275        if (verbose)
    63             dataLogLn("Processing funcion starting at: ", info.start, " and ending at: ", info.end);
     76            dataLogLn("Processing function starting at: ", info.start, " and ending at: ", info.end);
    6477        const uint8_t* functionStart = source + info.start;
    6578        size_t functionLength = info.end - info.start;
    6679        ASSERT(functionLength <= sourceLength);
    6780
    68         String error = validateFunction(functionStart, functionLength, info.signature, moduleParser.functionInformation());
     81        String error = validateFunction(functionStart, functionLength, info.signature, m_moduleInformation->functions);
    6982        if (!error.isNull()) {
    7083            m_errorMessage = error;
     
    7285        }
    7386
    74         m_result.append(parseAndCompile(vm, functionStart, functionLength, moduleParser.memory().get(), info.signature, moduleParser.functionInformation()));
     87        m_compiledFunctions.uncheckedAppend(parseAndCompile(vm, functionStart, functionLength, m_moduleInformation->memory.get(), info.signature, m_moduleInformation->functions));
    7588    }
    7689
    7790    // Patch the call sites for each function.
    78     for (std::unique_ptr<FunctionCompilation>& functionPtr : m_result) {
     91    for (std::unique_ptr<FunctionCompilation>& functionPtr : m_compiledFunctions) {
    7992        FunctionCompilation* function = functionPtr.get();
    8093        for (auto& call : function->unlinkedCalls)
    81             MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_result[call.functionIndex]->code->code()));
     94            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_compiledFunctions[call.functionIndex]->code->code()));
    8295    }
    8396
    84     m_memory = WTFMove(moduleParser.memory());
    8597    m_failed = false;
    8698}
  • trunk/Source/JavaScriptCore/wasm/WasmPlan.h

    r207929 r208401  
    3939class Plan {
    4040public:
    41     typedef Vector<std::unique_ptr<FunctionCompilation>> CompiledFunctions;
    42 
    4341    JS_EXPORT_PRIVATE Plan(VM&, Vector<uint8_t>);
    4442    JS_EXPORT_PRIVATE Plan(VM&, const uint8_t*, size_t);
     
    5149        return m_errorMessage;
    5250    }
    53     size_t resultSize() const
     51   
     52    std::unique_ptr<ModuleInformation>& getModuleInformation()
    5453    {
    5554        RELEASE_ASSERT(!failed());
    56         return m_result.size();
    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;
    6256    }
    6357    const Memory* memory() const
    6458    {
    6559        RELEASE_ASSERT(!failed());
    66         return m_memory.get();
     60        return m_moduleInformation->memory.get();
    6761    }
    68    
    69     CompiledFunctions* getFunctions()
     62    size_t compiledFunctionCount() const
    7063    {
    7164        RELEASE_ASSERT(!failed());
    72         return &m_result;
     65        return m_compiledFunctions.size();
    7366    }
    74     std::unique_ptr<Memory>* getMemory()
     67    const FunctionCompilation* compiledFunction(size_t i) const
    7568    {
    7669        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;
    7876    }
    7977
    8078private:
    81     CompiledFunctions m_result;
    82     std::unique_ptr<Memory> m_memory;
     79    std::unique_ptr<ModuleInformation> m_moduleInformation;
     80    CompiledFunctions m_compiledFunctions;
     81
    8382    bool m_failed { true };
    8483    String m_errorMessage;
  • trunk/Source/JavaScriptCore/wasm/WasmSections.h

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

    r207929 r208401  
    3636namespace JSC {
    3737
    38 JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, Vector<std::unique_ptr<Wasm::FunctionCompilation>>* compiledFunctions, std::unique_ptr<Wasm::Memory>* memory)
     38JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>& moduleInformation, Wasm::CompiledFunctions& compiledFunctions)
    3939{
    40     auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap)) JSWebAssemblyModule(vm, structure, compiledFunctions, memory);
     40    auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap)) JSWebAssemblyModule(vm, structure, moduleInformation, compiledFunctions);
    4141    instance->finishCreation(vm);
    4242    return instance;
     
    4848}
    4949
    50 JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, Vector<std::unique_ptr<Wasm::FunctionCompilation>>* compiledFunctions, std::unique_ptr<Wasm::Memory>* memory)
     50JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>& moduleInformation, Wasm::CompiledFunctions& compiledFunctions)
    5151    : Base(vm, structure)
    52     , m_compiledFunctions(WTFMove(*compiledFunctions))
    53     , m_memory(WTFMove(*memory))
     52    , m_moduleInformation(WTFMove(moduleInformation))
     53    , m_compiledFunctions(WTFMove(compiledFunctions))
    5454{
    5555}
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h

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

    r207929 r208401  
    6565        return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("second argument to WebAssembly.Instance must be undefined or an Object"), defaultSourceAppender, runtimeTypeForValue(importArgument))));
    6666
    67     // FIXME use the importObject. https://bugs.webkit.org/show_bug.cgi?id=164039
    6867    // If the list of module.imports is not empty and Type(importObject) is not Object, a TypeError is thrown.
     68    if (module->moduleInformation()->imports.size() && !importObject)
     69        return JSValue::encode(throwException(state, scope, createTypeError(state, ASCIILiteral("second argument to WebAssembly.Instance must be Object because the WebAssembly.Module has imports"), defaultSourceAppender, runtimeTypeForValue(importArgument))));
    6970
    7071    // FIXME String things from https://bugs.webkit.org/show_bug.cgi?id=164023
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyMemoryConstructor.cpp

    r207825 r208401  
    4848    VM& vm = state->vm();
    4949    auto scope = DECLARE_THROW_SCOPE(vm);
     50    // FIXME https://bugs.webkit.org/show_bug.cgi?id=164134
    5051    return JSValue::encode(throwException(state, scope, createError(state, ASCIILiteral("WebAssembly doesn't yet implement the Memory constructor property"))));
    5152}
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp

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

    r207825 r208401  
    4848    VM& vm = state->vm();
    4949    auto scope = DECLARE_THROW_SCOPE(vm);
     50    // FIXME https://bugs.webkit.org/show_bug.cgi?id=164135
    5051    return JSValue::encode(throwException(state, scope, createError(state, ASCIILiteral("WebAssembly doesn't yet implement the Table constructor property"))));
    5152}
Note: See TracChangeset for help on using the changeset viewer.