Changeset 209830 in webkit


Ignore:
Timestamp:
Dec 14, 2016 1:29:14 PM (7 years ago)
Author:
keith_miller@apple.com
Message:

WebAssembly JS API: implement Global
https://bugs.webkit.org/show_bug.cgi?id=164133

Reviewed by Saam Barati.

JSTests:

  • wasm/Builder.js:

(export.default.Builder.prototype._registerSectionBuilders.switch.case.string_appeared_here.this.section):

  • wasm/Builder_WebAssemblyBinary.js:

(const.valueType.WASM.description.type.i32.type.const.putGlobalType):
(const.putOp):
(const.putInitExpr):
(const.emitters.Import):
(const.emitters.Global):
(const.emitters.Export):
(const.emitters.Code):

  • wasm/LowLevelBinary.js:

(export.default.LowLevelBinary.prototype.varuint32):
(export.default.LowLevelBinary.prototype.varint32):

  • wasm/js-api/global-error.js: Added.

(catch):
(assert.truthy):

  • wasm/js-api/global-external-init-from-import.js: Added.
  • wasm/js-api/global-internal-init-from-import.js: Added.
  • wasm/js-api/global-mutate.js: Added.

(createInternalGlobalModule):

  • wasm/js-api/globals-export.js: Added.
  • wasm/js-api/globals-import.js: Added.
  • wasm/wasm.json:

Source/JavaScriptCore:

This patch adds support for globals. It handles imports, exports
and internal globals. In the MVP only internal globals are allowed
to be mutable. This means we can store a C-array of 64-bit slots
off the instance holding them. When globals are exported to JS
they are done so as numbers. This means that i64 globals cannot be
imported or exported.

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::getGlobal):
(JSC::Wasm::B3IRGenerator::setGlobal):
(JSC::Wasm::B3IRGenerator::addCallIndirect):
(JSC::Wasm::parseAndCompile):

  • wasm/WasmFormat.h:
  • wasm/WasmFunctionParser.h:

(JSC::Wasm::FunctionParser<Context>::parseExpression):

  • wasm/WasmModuleParser.cpp:

(JSC::Wasm::ModuleParser::parseImport):
(JSC::Wasm::ModuleParser::parseGlobal):
(JSC::Wasm::ModuleParser::parseExport):
(JSC::Wasm::ModuleParser::parseElement):
(JSC::Wasm::ModuleParser::parseInitExpr):
(JSC::Wasm::ModuleParser::parseGlobalType):
(JSC::Wasm::ModuleParser::parseData):

  • wasm/WasmModuleParser.h:
  • wasm/WasmParser.h:

(JSC::Wasm::Parser::parseVarInt32):
(JSC::Wasm::Parser::parseVarInt64):
(JSC::Wasm::Parser::parseUInt64):

  • wasm/WasmValidate.cpp:

(JSC::Wasm::Validate::hasMemory):
(JSC::Wasm::Validate::Validate):
(JSC::Wasm::Validate::getGlobal):
(JSC::Wasm::Validate::setGlobal):
(JSC::Wasm::validateFunction):

  • wasm/generateWasmOpsHeader.py:
  • wasm/js/JSWebAssemblyInstance.cpp:

(JSC::JSWebAssemblyInstance::create):
(JSC::JSWebAssemblyInstance::finishCreation):
(JSC::JSWebAssemblyInstance::visitChildren):

  • wasm/js/JSWebAssemblyInstance.h:

(JSC::JSWebAssemblyInstance::loadI32Global):
(JSC::JSWebAssemblyInstance::loadI64Global):
(JSC::JSWebAssemblyInstance::loadF32Global):
(JSC::JSWebAssemblyInstance::loadF64Global):
(JSC::JSWebAssemblyInstance::setGlobal):
(JSC::JSWebAssemblyInstance::offsetOfGlobals):

  • wasm/js/WebAssemblyInstanceConstructor.cpp:

(JSC::constructJSWebAssemblyInstance):

  • wasm/js/WebAssemblyModuleRecord.cpp:

(JSC::WebAssemblyModuleRecord::finishCreation):
(JSC::WebAssemblyModuleRecord::link):

Location:
trunk
Files:
6 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r209785 r209830  
     12016-12-14  Keith Miller  <keith_miller@apple.com>
     2
     3        WebAssembly JS API: implement Global
     4        https://bugs.webkit.org/show_bug.cgi?id=164133
     5
     6        Reviewed by Saam Barati.
     7
     8        * wasm/Builder.js:
     9        (export.default.Builder.prototype._registerSectionBuilders.switch.case.string_appeared_here.this.section):
     10        * wasm/Builder_WebAssemblyBinary.js:
     11        (const.valueType.WASM.description.type.i32.type.const.putGlobalType):
     12        (const.putOp):
     13        (const.putInitExpr):
     14        (const.emitters.Import):
     15        (const.emitters.Global):
     16        (const.emitters.Export):
     17        (const.emitters.Code):
     18        * wasm/LowLevelBinary.js:
     19        (export.default.LowLevelBinary.prototype.varuint32):
     20        (export.default.LowLevelBinary.prototype.varint32):
     21        * wasm/js-api/global-error.js: Added.
     22        (catch):
     23        (assert.truthy):
     24        * wasm/js-api/global-external-init-from-import.js: Added.
     25        * wasm/js-api/global-internal-init-from-import.js: Added.
     26        * wasm/js-api/global-mutate.js: Added.
     27        (createInternalGlobalModule):
     28        * wasm/js-api/globals-export.js: Added.
     29        * wasm/js-api/globals-import.js: Added.
     30        * wasm/wasm.json:
     31
    1322016-12-13  Saam Barati  <sbarati@apple.com>
    233
  • trunk/JSTests/wasm/Builder.js

    r209785 r209830  
    175175};
    176176
     177const _normalizeMutability = (mutability) => {
     178    if (mutability === "mutable")
     179        return 1;
     180    else if (mutability === "immutable")
     181        return 0;
     182    else
     183        throw new Error(`mutability should be either "mutable" or "immutable", but got ${global.mutablity}`);
     184};
     185
     186const _exportGlobalContinuation = (builder, section, nextBuilder) => {
     187    return (field, index) => {
     188        assert.isNumber(index, `Global exports only support number indices right now`);
     189        section.data.push({ field, kind: "Global", index });
     190        return nextBuilder;
     191    }
     192};
     193
     194const _importGlobalContinuation = (builder, section, nextBuilder) => {
     195    return () => {
     196        const globalBuilder = {
     197            End: () => nextBuilder
     198        };
     199        for (let op of WASM.description.value_type) {
     200            globalBuilder[_toJavaScriptName(op)] = (module, field, mutability) => {
     201                assert.isString(module, `Import global module should be a string, got "${module}"`);
     202                assert.isString(field, `Import global field should be a string, got "${field}"`);
     203                assert.isString(mutability, `Import global mutability should be a string, got "${mutability}"`);
     204                section.data.push({ globalDescription: { type: op, mutability: _normalizeMutability(mutability) }, module, field, kind: "Global" });
     205                return globalBuilder;
     206            };
     207        }
     208        return globalBuilder;
     209    };
     210};
     211
    177212const _checkStackArgs = (op, param) => {
    178213    for (let expect of param) {
     
    203238            // Handle our own meta-types.
    204239            switch (expect) {
     240            case "any": break;
    205241            case "bool": break; // FIXME implement bool. https://bugs.webkit.org/show_bug.cgi?id=163421
    206242            case "call": break; // FIXME implement call stack return check based on function signature. https://bugs.webkit.org/show_bug.cgi?id=163421
     
    408444                    const importBuilder = {
    409445                        End: () => this,
    410                         Global: () => { throw new Error(`Unimplemented: import global`); },
    411                     };
     446                    };
     447                    importBuilder.Global = _importGlobalContinuation(this, s, importBuilder);
    412448                    importBuilder.Function = _importFunctionContinuation(this, s, importBuilder);
    413449                    importBuilder.Memory = _importMemoryContinuation(this, s, importBuilder);
     
    457493
    458494            case "Global":
    459                 // FIXME implement global https://bugs.webkit.org/show_bug.cgi?id=164133
    460                 this[section] = () => { throw new Error(`Unimplemented: section type "${section}"`); };
     495                this[section] = function() {
     496                    const s = this._addSection(section);
     497                    const globalBuilder = {
     498                        End: () => this,
     499                        GetGlobal: (type, initValue, mutability) => {
     500                            s.data.push({ type, op: "get_global", mutability: _normalizeMutability(mutability), initValue });
     501                            return globalBuilder;
     502                        }
     503                    };
     504                    for (let op of WASM.description.value_type) {
     505                        globalBuilder[_toJavaScriptName(op)] = (initValue, mutability) => {
     506                            s.data.push({ type: op, op: op + ".const", mutability: _normalizeMutability(mutability), initValue });
     507                            return globalBuilder;
     508                        };
     509                    }
     510                    return globalBuilder;
     511                };
    461512                break;
    462513
     
    468519                        Table: () => { throw new Error(`Unimplemented: export table`); },
    469520                        Memory: () => { throw new Error(`Unimplemented: export memory`); },
    470                         Global: () => { throw new Error(`Unimplemented: export global`); },
    471                     };
     521                    };
     522                    exportBuilder.Global = _exportGlobalContinuation(this, s, exportBuilder);
    472523                    exportBuilder.Function = _exportFunctionContinuation(this, s, exportBuilder);
    473524                    return exportBuilder;
     
    509560                    const codeBuilder =  {
    510561                        End: () => {
    511                             // We now have enough information to remap the export section's "type" and "index" according to the Code section we're currently ending.
     562                            // We now have enough information to remap the export section's "type" and "index" according to the Code section we are currently ending.
    512563                            const typeSection = builder._getSection("Type");
    513564                            const importSection = builder._getSection("Import");
     
    517568                            if (exportSection) {
    518569                                for (const e of exportSection.data) {
     570                                    if (e.kind !== "Function" || typeof(e.type) !== "undefined")
     571                                        continue;
    519572                                    switch (typeof(e.index)) {
    520573                                    default: throw new Error(`Unexpected export index "${e.index}"`);
  • trunk/JSTests/wasm/Builder_WebAssemblyBinary.js

    r209785 r209830  
    5252};
    5353
     54const valueType = WASM.description.type.i32.type
     55
     56const putGlobalType = (bin, global) => {
     57    put(bin, valueType, WASM.typeValue[global.type]);
     58    put(bin, "varuint1", global.mutability);
     59};
     60
     61const putOp = (bin, op) => {
     62    put(bin, "uint8", op.value);
     63    if (op.arguments.length !== 0)
     64        throw new Error(`Unimplemented: arguments`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
     65
     66    switch (op.name) {
     67    default:
     68        for (let i = 0; i < op.immediates.length; ++i) {
     69            const type = WASM.description.opcode[op.name].immediate[i].type
     70            if (!bin[type])
     71                throw new TypeError(`Unknown type: ${type} in op: ${op.name}`);
     72            put(bin, type, op.immediates[i]);
     73        }
     74        break;
     75    case "br_table":
     76        put(bin, "varuint32", op.immediates.length - 1);
     77        for (let imm of op.immediates)
     78            put(bin, "varuint32", imm);
     79        break;
     80    }
     81};
     82
     83const putInitExpr = (bin, expr) => {
     84    putOp(bin, { value: WASM.description.opcode[expr.op].value, name: expr.op, immediates: [expr.initValue], arguments: [] });
     85    putOp(bin, { value: WASM.description.opcode.end.value, name: "end", immediates: [], arguments: [] });
     86};
     87
    5488const emitters = {
    5589    Type: (section, bin) => {
     
    89123                break;
    90124            };
    91             case "Global": throw new Error(`Not yet implemented`);
     125            case "Global":
     126                putGlobalType(bin, entry.globalDescription);
     127                break;
    92128            }
    93129        }
     
    118154    },
    119155
    120     Global: (section, bin) => { throw new Error(`Not yet implemented`); },
     156    Global: (section, bin) => {
     157        put(bin, "varuint32", section.data.length);
     158        for (const global of section.data) {
     159            putGlobalType(bin, global);
     160            putInitExpr(bin, global)
     161        }
     162    },
     163
    121164    Export: (section, bin) => {
    122165        put(bin, "varuint32", section.data.length);
     
    126169            switch (entry.kind) {
    127170            default: throw new Error(`Implementation problem: unexpected kind ${entry.kind}`);
    128             case "Function": put(bin, "varuint32", entry.index); break;
     171            case "Global":
     172            case "Function":
     173                put(bin, "varuint32", entry.index);
     174                break;
    129175            case "Table": throw new Error(`Not yet implemented`);
    130176            case "Memory": throw new Error(`Not yet implemented`);
    131             case "Global": throw new Error(`Not yet implemented`);
     177
    132178            }
    133179        }
     
    165211            }
    166212
    167             for (const op of func.code) {
    168                 put(funcBin, "uint8", op.value);
    169                 if (op.arguments.length !== 0)
    170                     throw new Error(`Unimplemented: arguments`); // FIXME https://bugs.webkit.org/show_bug.cgi?id=162706
    171 
    172                 switch (op.name) {
    173                 default:
    174                     for (let i = 0; i < op.immediates.length; ++i) {
    175                         const type = WASM.description.opcode[op.name].immediate[i].type
    176                         if (!funcBin[type])
    177                             throw new TypeError(`Unknown type: ${type} in op: ${op.name}`);
    178                         put(funcBin, type, op.immediates[i]);
    179                     }
    180                     break;
    181                 case "br_table":
    182                     put(funcBin, "varuint32", op.immediates.length - 1);
    183                     for (let imm of op.immediates)
    184                         put(funcBin, "varuint32", imm);
    185                     break;
    186                 }
    187             }
     213            for (const op of func.code)
     214                putOp(funcBin, op);
     215
    188216            funcBin.apply();
    189217        }
  • trunk/JSTests/wasm/LowLevelBinary.js

    r209306 r209830  
    124124    }
    125125    varuint32(v) {
     126        assert.isNumber(v);
    126127        if (v < varuint32Min || varuint32Max < v)
    127128            throw new RangeError(`Invalid varuint32 ${v} range is [${varuint32Min}, ${varuint32Max}]`);
     
    133134    }
    134135    varint32(v) {
     136        assert.isNumber(v);
    135137        if (v < varint32Min || varint32Max < v)
    136138            throw new RangeError(`Invalid varint32 ${v} range is [${varint32Min}, ${varint32Max}]`);
  • trunk/JSTests/wasm/wasm.json

    r209652 r209830  
    5959        "f64.const":           { "category": "special",    "value":  68, "return": ["f64"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint64"}],                                             "description": "a constant value interpreted as f64" },
    6060        "f32.const":           { "category": "special",    "value":  67, "return": ["f32"],      "parameter": [],                       "immediate": [{"name": "value",          "type": "uint32"}],                                             "description": "a constant value interpreted as f32" },
    61         "get_local":           { "category": "special",    "value":  32, "return": ["local"],    "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "read a local variable or parameter" },
    62         "set_local":           { "category": "special",    "value":  33, "return": [],           "parameter": ["local"],                "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter" },
    63         "tee_local":           { "category": "special",    "value":  34, "return": ["prev"],     "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter and return the same value" },
    64         "get_global":          { "category": "special",    "value":  35, "return": ["global"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
    65         "set_global":          { "category": "special",    "value":  36, "return": [""],         "parameter": ["global"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
     61        "get_local":           { "category": "special",    "value":  32, "return": ["any"],    "parameter": [],                       "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "read a local variable or parameter" },
     62        "set_local":           { "category": "special",    "value":  33, "return": [],           "parameter": ["any"],                "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter" },
     63        "tee_local":           { "category": "special",    "value":  34, "return": ["any"],     "parameter": ["any"],                  "immediate": [{"name": "local_index",    "type": "varuint32"}],                                          "description": "write a local variable or parameter and return the same value" },
     64        "get_global":          { "category": "special",    "value":  35, "return": ["any"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
     65        "set_global":          { "category": "special",    "value":  36, "return": [],         "parameter": ["any"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
    6666        "call":                { "category": "call",       "value":  16, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                          "description": "call a function by its index" },
    6767        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}, {"name": "reserved",     "type": "varuint1"}], "description": "call a function indirect with an expected signature" },
  • trunk/Source/JavaScriptCore/ChangeLog

    r209827 r209830  
     12016-12-14  Keith Miller  <keith_miller@apple.com>
     2
     3        WebAssembly JS API: implement Global
     4        https://bugs.webkit.org/show_bug.cgi?id=164133
     5
     6        Reviewed by Saam Barati.
     7
     8        This patch adds support for globals. It handles imports, exports
     9        and internal globals. In the MVP only internal globals are allowed
     10        to be mutable. This means we can store a C-array of 64-bit slots
     11        off the instance holding them. When globals are exported to JS
     12        they are done so as numbers. This means that i64 globals cannot be
     13        imported or exported.
     14
     15        * wasm/WasmB3IRGenerator.cpp:
     16        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
     17        (JSC::Wasm::B3IRGenerator::getGlobal):
     18        (JSC::Wasm::B3IRGenerator::setGlobal):
     19        (JSC::Wasm::B3IRGenerator::addCallIndirect):
     20        (JSC::Wasm::parseAndCompile):
     21        * wasm/WasmFormat.h:
     22        * wasm/WasmFunctionParser.h:
     23        (JSC::Wasm::FunctionParser<Context>::parseExpression):
     24        * wasm/WasmModuleParser.cpp:
     25        (JSC::Wasm::ModuleParser::parseImport):
     26        (JSC::Wasm::ModuleParser::parseGlobal):
     27        (JSC::Wasm::ModuleParser::parseExport):
     28        (JSC::Wasm::ModuleParser::parseElement):
     29        (JSC::Wasm::ModuleParser::parseInitExpr):
     30        (JSC::Wasm::ModuleParser::parseGlobalType):
     31        (JSC::Wasm::ModuleParser::parseData):
     32        * wasm/WasmModuleParser.h:
     33        * wasm/WasmParser.h:
     34        (JSC::Wasm::Parser::parseVarInt32):
     35        (JSC::Wasm::Parser::parseVarInt64):
     36        (JSC::Wasm::Parser::parseUInt64):
     37        * wasm/WasmValidate.cpp:
     38        (JSC::Wasm::Validate::hasMemory):
     39        (JSC::Wasm::Validate::Validate):
     40        (JSC::Wasm::Validate::getGlobal):
     41        (JSC::Wasm::Validate::setGlobal):
     42        (JSC::Wasm::validateFunction):
     43        * wasm/generateWasmOpsHeader.py:
     44        * wasm/js/JSWebAssemblyInstance.cpp:
     45        (JSC::JSWebAssemblyInstance::create):
     46        (JSC::JSWebAssemblyInstance::finishCreation):
     47        (JSC::JSWebAssemblyInstance::visitChildren):
     48        * wasm/js/JSWebAssemblyInstance.h:
     49        (JSC::JSWebAssemblyInstance::loadI32Global):
     50        (JSC::JSWebAssemblyInstance::loadI64Global):
     51        (JSC::JSWebAssemblyInstance::loadF32Global):
     52        (JSC::JSWebAssemblyInstance::loadF64Global):
     53        (JSC::JSWebAssemblyInstance::setGlobal):
     54        (JSC::JSWebAssemblyInstance::offsetOfGlobals):
     55        * wasm/js/WebAssemblyInstanceConstructor.cpp:
     56        (JSC::constructJSWebAssemblyInstance):
     57        * wasm/js/WebAssemblyModuleRecord.cpp:
     58        (JSC::WebAssemblyModuleRecord::finishCreation):
     59        (JSC::WebAssemblyModuleRecord::link):
     60
    1612016-12-14  Filip Pizlo  <fpizlo@apple.com>
    262
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

    r209771 r209830  
    138138    static constexpr ExpressionType emptyExpression = nullptr;
    139139
    140     B3IRGenerator(VM&, const MemoryInformation&, Procedure&, WasmInternalFunction*, Vector<UnlinkedWasmToWasmCall>&, const ImmutableFunctionIndexSpace&);
     140    B3IRGenerator(VM&, const ModuleInformation&, Procedure&, WasmInternalFunction*, Vector<UnlinkedWasmToWasmCall>&, const ImmutableFunctionIndexSpace&);
    141141
    142142    bool WARN_UNUSED_RETURN addArguments(const Vector<Type>&);
     
    147147    bool WARN_UNUSED_RETURN getLocal(uint32_t index, ExpressionType& result);
    148148    bool WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value);
     149
     150    // Globals
     151    bool WARN_UNUSED_RETURN getGlobal(uint32_t index, ExpressionType& result);
     152    bool WARN_UNUSED_RETURN setGlobal(uint32_t index, ExpressionType value);
    149153
    150154    // Memory
     
    191195    VM& m_vm;
    192196    const ImmutableFunctionIndexSpace& m_functionIndexSpace;
     197    const ModuleInformation& m_info;
    193198    Procedure& m_proc;
    194199    BasicBlock* m_currentBlock;
     
    198203    GPRReg m_memorySizeGPR;
    199204    Value* m_zeroValues[numTypes];
    200     Value* m_functionIndexSpaceValue;
     205    Value* m_instanceValue;
     206
    201207};
    202208
    203 B3IRGenerator::B3IRGenerator(VM& vm, const MemoryInformation& memory, Procedure& procedure, WasmInternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace& functionIndexSpace)
     209B3IRGenerator::B3IRGenerator(VM& vm, const ModuleInformation& info, Procedure& procedure, WasmInternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace& functionIndexSpace)
    204210    : m_vm(vm)
    205211    , m_functionIndexSpace(functionIndexSpace)
     212    , m_info(info)
    206213    , m_proc(procedure)
    207214    , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls)
     
    223230    }
    224231
    225     if (!!memory) {
    226         m_memoryBaseGPR = memory.pinnedRegisters().baseMemoryPointer;
     232    if (!!info.memory) {
     233        m_memoryBaseGPR = info.memory.pinnedRegisters().baseMemoryPointer;
    227234        m_proc.pinRegister(m_memoryBaseGPR);
    228         ASSERT(!memory.pinnedRegisters().sizeRegisters[0].sizeOffset);
    229         m_memorySizeGPR = memory.pinnedRegisters().sizeRegisters[0].sizeRegister;
    230         for (const PinnedSizeRegisterInfo& info : memory.pinnedRegisters().sizeRegisters)
    231             m_proc.pinRegister(info.sizeRegister);
     235        ASSERT(!info.memory.pinnedRegisters().sizeRegisters[0].sizeOffset);
     236        m_memorySizeGPR = info.memory.pinnedRegisters().sizeRegisters[0].sizeRegister;
     237        for (const PinnedSizeRegisterInfo& regInfo : info.memory.pinnedRegisters().sizeRegisters)
     238            m_proc.pinRegister(regInfo.sizeRegister);
    232239
    233240        m_proc.setWasmBoundsCheckGenerator([=] (CCallHelpers& jit, GPRReg pinnedGPR, unsigned) {
     
    272279    wasmCallingConvention().setupFrameInPrologue(&compilation->wasmCalleeMoveLocation, m_proc, Origin(), m_currentBlock);
    273280
    274     m_functionIndexSpaceValue = m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), functionIndexSpace.buffer.get());
     281    m_instanceValue = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(),
     282        m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), &m_vm.topJSWebAssemblyInstance));
    275283}
    276284
     
    323331    ASSERT(m_locals[index]);
    324332    m_currentBlock->appendNew<VariableValue>(m_proc, B3::Set, Origin(), m_locals[index], value);
     333    return true;
     334}
     335
     336bool B3IRGenerator::getGlobal(uint32_t index, ExpressionType& result)
     337{
     338    Value* globalsArray = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfGlobals());
     339    result = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, toB3Type(m_info.globals[index].type), Origin(), globalsArray, index * sizeof(Register));
     340    return true;
     341}
     342
     343bool B3IRGenerator::setGlobal(uint32_t index, ExpressionType value)
     344{
     345    ASSERT(toB3Type(m_info.globals[index].type) == value->type());
     346    Value* globalsArray = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(), m_instanceValue, JSWebAssemblyInstance::offsetOfGlobals());
     347    m_currentBlock->appendNew<MemoryValue>(m_proc, Store, Origin(), value, globalsArray, index * sizeof(Register));
    325348    return true;
    326349}
     
    675698    ExpressionType callableFunctionBufferSize;
    676699    {
    677         ExpressionType topInstance = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(),
    678             m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), &m_vm.topJSWebAssemblyInstance));
    679700        ExpressionType table = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(),
    680             topInstance, JSWebAssemblyInstance::offsetOfTable());
     701            m_instanceValue, JSWebAssemblyInstance::offsetOfTable());
    681702        callableFunctionBuffer = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(),
    682703            table, JSWebAssemblyTable::offsetOfFunctions());
     
    873894
    874895    Procedure procedure;
    875     B3IRGenerator context(vm, info.memory, procedure, result.get(), unlinkedWasmToWasmCalls, functionIndexSpace);
     896    B3IRGenerator context(vm, info, procedure, result.get(), unlinkedWasmToWasmCalls, functionIndexSpace);
    876897    FunctionParser<B3IRGenerator> parser(context, functionStart, functionLength, signature, functionIndexSpace, info);
    877898    if (!parser.parse())
  • trunk/Source/JavaScriptCore/wasm/WasmFormat.h

    r209785 r209830  
    9494    Vector<Type> arguments;
    9595};
    96    
     96
    9797struct Import {
    9898    Identifier module;
     
    105105    Identifier field;
    106106    External::Kind kind;
    107     union {
    108         uint32_t functionIndex;
    109         // FIXME implement Table https://bugs.webkit.org/show_bug.cgi?id=165782
    110         // FIXME implement Memory https://bugs.webkit.org/show_bug.cgi?id=165671
    111         // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
     107    unsigned kindIndex; // Index in the vector of the corresponding kind.
     108};
     109
     110struct Global {
     111    enum Mutability : uint8_t {
     112        // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
     113        Mutable = 1,
     114        Immutable = 0
    112115    };
     116
     117    enum InitializationType {
     118        IsImport,
     119        FromGlobalImport,
     120        FromExpression
     121    };
     122
     123    Mutability mutability;
     124    Type type;
     125    InitializationType initializationType { IsImport };
     126    uint64_t initialBitsOrImportNumber { 0 };
    113127};
    114128
     
    185199    Vector<Import> imports;
    186200    Vector<Signature*> importFunctions;
    187     // FIXME implement import Global https://bugs.webkit.org/show_bug.cgi?id=164133
    188201    Vector<Signature*> internalFunctionSignatures;
    189202    MemoryInformation memory;
     
    193206    Vector<Element> elements;
    194207    TableInformation tableInformation;
     208    Vector<Global> globals;
     209    unsigned firstInternalGlobal { 0 };
    195210
    196211    ~ModuleInformation();
  • trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h

    r209771 r209830  
    352352    }
    353353
     354    case OpType::GetGlobal: {
     355        uint32_t index;
     356        if (!parseVarUInt32(index))
     357            return false;
     358        ExpressionType result;
     359        if (!m_context.getGlobal(index, result))
     360            return false;
     361
     362        m_expressionStack.append(result);
     363        return true;
     364    }
     365
     366    case OpType::SetGlobal: {
     367        uint32_t index;
     368        if (!parseVarUInt32(index))
     369            return false;
     370        ExpressionType value;
     371        if (!popExpressionStack(value))
     372            return false;
     373        return m_context.setGlobal(index, value);
     374    }
     375
    354376    case OpType::Call: {
    355377        uint32_t functionIndex;
     
    564586    case OpType::GrowMemory:
    565587    case OpType::CurrentMemory:
    566     case OpType::GetGlobal:
    567     case OpType::SetGlobal: {
    568588        // FIXME: Not yet implemented.
    569589        return false;
    570     }
    571590    }
    572591
  • trunk/Source/JavaScriptCore/wasm/WasmModuleParser.cpp

    r209785 r209830  
    218218    if (!parseVarUInt32(importCount)
    219219        || importCount == std::numeric_limits<uint32_t>::max()
     220        || !m_module->globals.tryReserveCapacity(importCount) // FIXME this over-allocates when we fix the FIXMEs below.
    220221        || !m_module->imports.tryReserveCapacity(importCount) // FIXME this over-allocates when we fix the FIXMEs below.
    221222        || !m_module->importFunctions.tryReserveCapacity(importCount) // FIXME this over-allocates when we fix the FIXMEs below.
     
    264265        }
    265266        case External::Global: {
    266             // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
    267             // In the MVP, only immutable global variables can be imported.
     267            Global global;
     268            if (!parseGlobalType(global))
     269                return false;
     270
     271            if (global.mutability == Global::Mutable)
     272                return false;
     273
     274            imp.kindIndex = m_module->globals.size();
     275            m_module->globals.uncheckedAppend(WTFMove(global));
    268276            break;
    269277        }
     
    273281    }
    274282
     283    m_module->firstInternalGlobal = m_module->globals.size();
    275284    return true;
    276285}
     
    424433bool ModuleParser::parseGlobal()
    425434{
    426     // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
    427     RELEASE_ASSERT_NOT_REACHED();
     435    uint32_t globalCount;
     436    if (!parseVarUInt32(globalCount))
     437        return false;
     438    if (!m_module->globals.tryReserveCapacity(globalCount + m_module->firstInternalGlobal))
     439        return false;
     440
     441    for (uint32_t globalIndex = 0; globalIndex < globalCount; ++globalIndex) {
     442        Global global;
     443        if (!parseGlobalType(global))
     444            return false;
     445
     446        uint8_t initOpcode;
     447        if (!parseInitExpr(initOpcode, global.initialBitsOrImportNumber))
     448            return false;
     449
     450        global.initializationType = Global::FromExpression;
     451        Type typeForInitOpcode;
     452        switch (initOpcode) {
     453        case I32Const:
     454            typeForInitOpcode = I32;
     455            break;
     456        case I64Const:
     457            typeForInitOpcode = I64;
     458            break;
     459        case F32Const:
     460            typeForInitOpcode = F32;
     461            break;
     462        case F64Const:
     463            typeForInitOpcode = F64;
     464            break;
     465        case GetGlobal:
     466            if (global.initialBitsOrImportNumber >= m_module->firstInternalGlobal)
     467                return false;
     468            typeForInitOpcode = m_module->globals[global.initialBitsOrImportNumber].type;
     469            global.initializationType = Global::FromGlobalImport;
     470            break;
     471        default:
     472            RELEASE_ASSERT_NOT_REACHED();
     473        }
     474
     475        if (typeForInitOpcode != global.type)
     476            return false;
     477
     478        m_module->globals.uncheckedAppend(WTFMove(global));
     479    }
     480
    428481    return true;
    429482}
     
    449502            return false;
    450503
     504        if (!parseVarUInt32(exp.kindIndex))
     505            return false;
     506
    451507        switch (exp.kind) {
    452508        case External::Function: {
    453             if (!parseVarUInt32(exp.functionIndex)
    454                 || exp.functionIndex >= m_functionIndexSpace.size())
     509            if (exp.kindIndex >= m_functionIndexSpace.size())
    455510                return false;
    456511            break;
     
    465520        }
    466521        case External::Global: {
    467             // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
    468             // In the MVP, only immutable global variables can be exported.
     522            if (exp.kindIndex >= m_module->globals.size())
     523                return false;
     524
     525            if (m_module->globals[exp.kindIndex].mutability != Global::Immutable)
     526                return false;
    469527            break;
    470528        }
     
    510568            return false;
    511569
    512         uint32_t offset;
    513         if (!parseInitExpr(offset))
     570        uint64_t offset;
     571        uint8_t initOpcode;
     572        if (!parseInitExpr(initOpcode, offset))
     573            return false;
     574
     575        if (initOpcode != OpType::I32Const)
    514576            return false;
    515577
     
    578640}
    579641
    580 bool ModuleParser::parseInitExpr(uint32_t& value)
    581 {
    582     // FIXME allow complex init_expr here. https://bugs.webkit.org/show_bug.cgi?id=165700
    583     // For now we only handle i32.const as offset.
    584 
    585     uint8_t opcode;
     642bool ModuleParser::parseInitExpr(uint8_t& opcode, uint64_t& bitsOrImportNumber)
     643{
     644    if (!parseUInt8(opcode))
     645        return false;
     646
     647    switch (opcode) {
     648    case I32Const: {
     649        int32_t constant;
     650        if (!parseVarInt32(constant))
     651            return false;
     652        bitsOrImportNumber = static_cast<uint64_t>(constant);
     653        break;
     654    }
     655
     656    case I64Const: {
     657        int64_t constant;
     658        if (!parseVarInt64(constant))
     659            return false;
     660        bitsOrImportNumber = constant;
     661        break;
     662    }
     663
     664    case F32Const: {
     665        uint32_t constant;
     666        if (!parseUInt32(constant))
     667            return false;
     668        bitsOrImportNumber = constant;
     669        break;
     670    }
     671
     672    case F64Const: {
     673        uint64_t constant;
     674        if (!parseUInt64(constant))
     675            return false;
     676        bitsOrImportNumber = constant;
     677        break;
     678    }
     679
     680    case GetGlobal: {
     681        uint32_t index;
     682        if (!parseVarUInt32(index))
     683            return false;
     684
     685        if (index >= m_module->imports.size())
     686            return false;
     687        const Import& import = m_module->imports[index];
     688        if (m_module->imports[index].kind != External::Global
     689            || import.kindIndex >= m_module->firstInternalGlobal)
     690            return false;
     691
     692        ASSERT(m_module->globals[import.kindIndex].mutability == Global::Immutable);
     693
     694        bitsOrImportNumber = index;
     695        break;
     696    }
     697
     698    default:
     699        return false;
     700    }
     701
    586702    uint8_t endOpcode;
    587     if (!parseUInt8(opcode)
    588         || opcode != Wasm::I32Const
    589         || !parseVarUInt32(value)
    590         || !parseUInt8(endOpcode)
    591         || endOpcode != Wasm::End)
    592         return false;
     703    if (!parseUInt8(endOpcode) || endOpcode != OpType::End)
     704        return false;
     705
     706    return true;
     707}
     708
     709bool ModuleParser::parseGlobalType(Global& global)
     710{
     711    uint8_t mutability;
     712    if (!parseValueType(global.type) || !parseVarUInt1(mutability))
     713        return false;
     714    global.mutability = static_cast<Global::Mutability>(mutability);
    593715    return true;
    594716}
     
    608730            dataLogLn("  segment #", segmentNumber);
    609731        uint32_t index;
    610         uint32_t offset;
     732        uint64_t offset;
     733        uint8_t initOpcode;
    611734        uint32_t dataByteLength;
    612735        if (!parseVarUInt32(index)
     
    614737            return false;
    615738
    616         if (!parseInitExpr(offset))
    617             return false;
     739        if (!parseInitExpr(initOpcode, offset))
     740            return false;
     741
     742        if (initOpcode != OpType::I32Const)
     743            return false;
     744
    618745        if (verbose)
    619746            dataLogLn("    offset: ", offset);
  • trunk/Source/JavaScriptCore/wasm/WasmModuleParser.h

    r209785 r209830  
    7575
    7676private:
     77    bool parseGlobalType(Global&);
     78
    7779#define WASM_SECTION_DECLARE_PARSER(NAME, ID, DESCRIPTION) bool WARN_UNUSED_RETURN parse ## NAME();
    7880    FOR_EACH_WASM_SECTION(WASM_SECTION_DECLARE_PARSER)
     
    8284    bool WARN_UNUSED_RETURN parseTableHelper(bool isImport);
    8385    bool WARN_UNUSED_RETURN parseResizableLimits(uint32_t& initial, std::optional<uint32_t>& maximum);
    84     bool WARN_UNUSED_RETURN parseInitExpr(uint32_t&);
     86    bool WARN_UNUSED_RETURN parseInitExpr(uint8_t&, uint64_t&);
    8587
    8688    VM* m_vm;
  • trunk/Source/JavaScriptCore/wasm/WasmParser.h

    r209560 r209830  
    5252    bool WARN_UNUSED_RETURN parseUInt8(uint8_t&);
    5353    bool WARN_UNUSED_RETURN parseUInt32(uint32_t&);
     54    bool WARN_UNUSED_RETURN parseUInt64(uint64_t&);
    5455    bool WARN_UNUSED_RETURN parseVarUInt32(uint32_t&);
    5556    bool WARN_UNUSED_RETURN parseVarUInt64(uint64_t&);
     57
     58    bool WARN_UNUSED_RETURN parseVarInt32(int32_t&);
     59    bool WARN_UNUSED_RETURN parseVarInt64(int64_t&);
    5660
    5761    bool WARN_UNUSED_RETURN parseResultType(Type&);
     
    125129}
    126130
     131ALWAYS_INLINE bool Parser::parseVarInt32(int32_t& result)
     132{
     133    return WTF::LEBDecoder::decodeInt32(m_source, m_sourceLength, m_offset, result);
     134}
     135
     136ALWAYS_INLINE bool Parser::parseVarInt64(int64_t& result)
     137{
     138    return WTF::LEBDecoder::decodeInt64(m_source, m_sourceLength, m_offset, result);
     139}
     140
    127141ALWAYS_INLINE bool Parser::parseUInt32(uint32_t& result)
    128142{
     
    131145    result = *reinterpret_cast<const uint32_t*>(source() + m_offset);
    132146    m_offset += 4;
     147    return true;
     148}
     149
     150ALWAYS_INLINE bool Parser::parseUInt64(uint64_t& result)
     151{
     152    if (length() < 8 || m_offset > length() - 8)
     153        return false;
     154    result = *reinterpret_cast<const uint64_t*>(source() + m_offset);
     155    m_offset += 8;
    133156    return true;
    134157}
  • trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp

    r209652 r209830  
    8787    bool WARN_UNUSED_RETURN setLocal(uint32_t index, ExpressionType value);
    8888
     89    // Globals
     90    bool WARN_UNUSED_RETURN getGlobal(uint32_t index, ExpressionType& result);
     91    bool WARN_UNUSED_RETURN setGlobal(uint32_t index, ExpressionType value);
     92
    8993    // Memory
    9094    bool WARN_UNUSED_RETURN load(LoadOpType, ExpressionType pointer, ExpressionType& result, uint32_t offset);
     
    117121    void dump(const Vector<ControlEntry>& controlStack, const ExpressionList& expressionStack);
    118122
    119     bool hasMemory() const { return !!m_memory; }
     123    bool hasMemory() const { return !!m_module.memory; }
    120124
    121125    void setErrorMessage(String&& message) { ASSERT(m_errorMessage.isNull()); m_errorMessage = WTFMove(message); }
    122126    String errorMessage() const { return m_errorMessage; }
    123     Validate(ExpressionType returnType, const MemoryInformation& memory)
     127    Validate(ExpressionType returnType, const ModuleInformation& module)
    124128        : m_returnType(returnType)
    125         , m_memory(memory)
     129        , m_module(module)
    126130    {
    127131    }
     
    136140    Vector<Type> m_locals;
    137141    String m_errorMessage;
    138     const MemoryInformation& m_memory;
     142    const ModuleInformation& m_module;
    139143};
    140144
     
    178182
    179183    m_errorMessage = makeString("Attempt to set local with type: ", toString(localType), " with a variable of type: ", toString(value));
     184    return false;
     185}
     186
     187bool Validate::getGlobal(uint32_t index, ExpressionType& result)
     188{
     189    if (index < m_module.globals.size()) {
     190        result = m_module.globals[index].type;
     191        ASSERT(isValueType(result));
     192        return true;
     193    }
     194    m_errorMessage = ASCIILiteral("Attempt to use unknown global.");
     195    return false;
     196}
     197
     198bool Validate::setGlobal(uint32_t index, ExpressionType value)
     199{
     200    if (index >= m_module.globals.size()) {
     201        m_errorMessage = ASCIILiteral("Attempt to use unknown global.");
     202        return false;
     203    }
     204
     205    if (m_module.globals[index].mutability == Global::Immutable) {
     206        m_errorMessage = ASCIILiteral("Attempt to store to immutable global.");
     207        return false;
     208    }
     209
     210    ExpressionType globalType = m_module.globals[index].type;
     211    ASSERT(isValueType(globalType));
     212    if (globalType == value)
     213        return true;
     214
     215    m_errorMessage = makeString("Attempt to set global with type: ", toString(globalType), " with a variable of type: ", toString(value));
    180216    return false;
    181217}
     
    402438}
    403439
    404 String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& info)
    405 {
    406     Validate context(signature->returnType, info.memory);
    407     FunctionParser<Validate> validator(context, source, length, signature, functionIndexSpace, info);
     440String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& module)
     441{
     442    Validate context(signature->returnType, module);
     443    FunctionParser<Validate> validator(context, source, length, signature, functionIndexSpace, module);
    408444
    409445    if (!validator.parse()) {
  • trunk/Source/JavaScriptCore/wasm/generateWasmOpsHeader.py

    r209503 r209830  
    151151#undef CREATE_CASE
    152152
    153 #define CREATE_CASE(name, id, b3type, inc) case name: return "name";
     153#define CREATE_CASE(name, id, b3type, inc) case name: return #name;
    154154inline const char* toString(Type type)
    155155{
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.cpp

    r209771 r209830  
    3939namespace JSC {
    4040
    41 JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject, unsigned numImportFunctions)
     41JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
    4242{
    43     auto* instance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap, allocationSize(numImportFunctions))) JSWebAssemblyInstance(vm, structure, numImportFunctions);
     43    // FIXME: These objects could be pretty big we should try to throw OOM here.
     44    auto* instance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap, allocationSize(module->moduleInformation().importFunctions.size()))) JSWebAssemblyInstance(vm, structure, module->moduleInformation().importFunctions.size());
    4445    instance->finishCreation(vm, module, moduleNamespaceObject);
    4546    return instance;
     
    6263    Base::finishCreation(vm);
    6364    ASSERT(inherits(info()));
     65
     66    const size_t extraMemorySize = module->moduleInformation().globals.size() * sizeof(Register);
     67    m_globals = MallocPtr<uint64_t>::malloc(extraMemorySize);
     68    heap()->reportExtraMemoryAllocated(extraMemorySize);
     69
    6470    m_module.set(vm, this, module);
    6571    m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
     
    8288    visitor.append(&thisObject->m_memory);
    8389    visitor.append(&thisObject->m_table);
     90    visitor.reportExtraMemoryVisited(thisObject->module()->moduleInformation().globals.size());
    8491    for (unsigned i = 0; i < thisObject->m_numImportFunctions; ++i)
    8592        visitor.append(thisObject->importFunction(i));
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyInstance.h

    r209771 r209830  
    4343
    4444
    45     static JSWebAssemblyInstance* create(VM&, Structure*, JSWebAssemblyModule*, JSModuleNamespaceObject*, unsigned);
     45    static JSWebAssemblyInstance* create(VM&, Structure*, JSWebAssemblyModule*, JSModuleNamespaceObject*);
    4646    static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
    4747
     
    7676    void setTable(VM& vm, JSWebAssemblyTable* table) { m_table.set(vm, this, table); }
    7777
     78    int32_t loadI32Global(unsigned i) const { return m_globals.get()[i]; }
     79    int64_t loadI64Global(unsigned i) const { return m_globals.get()[i]; }
     80    float loadF32Global(unsigned i) const { return bitwise_cast<float>(loadI32Global(i)); }
     81    double loadF64Global(unsigned i) const { return bitwise_cast<double>(loadI64Global(i)); }
     82    void setGlobal(unsigned i, int64_t bits) { m_globals.get()[i] = bits; }
     83
    7884    static size_t offsetOfImportFunction(unsigned idx)
    7985    {
     
    8288
    8389    static ptrdiff_t offsetOfTable() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_table); }
     90    static ptrdiff_t offsetOfGlobals() { return OBJECT_OFFSETOF(JSWebAssemblyInstance, m_globals); }
    8491
    8592protected:
    86     JSWebAssemblyInstance(VM&, Structure*, unsigned);
     93    JSWebAssemblyInstance(VM&, Structure*, unsigned numImportFunctions);
    8794    void finishCreation(VM&, JSWebAssemblyModule*, JSModuleNamespaceObject*);
    8895    static void destroy(JSCell*);
     
    104111    WriteBarrier<JSWebAssemblyMemory> m_memory;
    105112    WriteBarrier<JSWebAssemblyTable> m_table;
     113    MallocPtr<uint64_t> m_globals;
    106114    unsigned m_numImportFunctions;
    107115};
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp

    r209771 r209830  
    8282    RETURN_IF_EXCEPTION(throwScope, { });
    8383
    84     JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord->getModuleNamespace(exec), moduleInformation.imports.size());
     84    JSWebAssemblyInstance* instance = JSWebAssemblyInstance::create(vm, instanceStructure, jsModule, moduleRecord->getModuleNamespace(exec));
    8585    RETURN_IF_EXCEPTION(throwScope, { });
    8686
     
    8888    // Let imports be an initially-empty list of external values.
    8989    unsigned numImportFunctions = 0;
    90 
    91     // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
     90    unsigned numImportGlobals = 0;
    9291
    9392    bool hasMemoryImport = false;
     
    196195        case Wasm::External::Global: {
    197196            // 5. If i is a global import:
    198             // FIXME implement Global https://bugs.webkit.org/show_bug.cgi?id=164133
    199197            // i. If i is not an immutable global, throw a TypeError.
     198            ASSERT(moduleInformation.globals[import.kindIndex].mutability == Wasm::Global::Immutable);
    200199            // ii. If Type(v) is not Number, throw a TypeError.
     200            if (!value.isNumber())
     201                return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, ASCIILiteral("imported global must be a number"), defaultSourceAppender, runtimeTypeForValue(value))));
    201202            // iii. Append ToWebAssemblyValue(v) to imports.
    202             RELEASE_ASSERT_NOT_REACHED();
     203            switch (moduleInformation.globals[import.kindIndex].type) {
     204            case Wasm::I32:
     205                instance->setGlobal(numImportGlobals++, value.toInt32(exec));
     206                break;
     207            case Wasm::F32:
     208                instance->setGlobal(numImportGlobals++, bitwise_cast<uint32_t>(value.toFloat(exec)));
     209                break;
     210            case Wasm::F64:
     211                instance->setGlobal(numImportGlobals++, bitwise_cast<uint64_t>(value.asNumber()));
     212                break;
     213            default:
     214                RELEASE_ASSERT_NOT_REACHED();
     215            }
     216            ASSERT(!throwScope.exception());
    203217            break;
    204218        }
     
    242256    }
    243257
     258    // Globals
     259    {
     260        ASSERT(numImportGlobals == moduleInformation.firstInternalGlobal);
     261        for (size_t globalIndex = numImportGlobals; globalIndex < moduleInformation.globals.size(); ++globalIndex) {
     262            const auto& global = moduleInformation.globals[globalIndex];
     263            ASSERT(global.initializationType != Wasm::Global::IsImport);
     264            if (global.initializationType == Wasm::Global::FromGlobalImport) {
     265                ASSERT(global.initialBitsOrImportNumber < numImportGlobals);
     266                instance->setGlobal(globalIndex, instance->loadI64Global(global.initialBitsOrImportNumber));
     267            } else
     268                instance->setGlobal(globalIndex, global.initialBitsOrImportNumber);
     269        }
     270    }
     271
    244272    moduleRecord->link(exec, instance);
    245273    RETURN_IF_EXCEPTION(throwScope, { });
     274
    246275    if (verbose)
    247276        moduleRecord->dump();
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp

    r209785 r209830  
    8686        }
    8787        case Wasm::External::Global: {
    88             // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
    8988            // In the MVP, only immutable global variables can be exported.
     89            addExportEntry(ExportEntry::createLocal(exp.field, exp.field));
    9090            break;
    9191        }
     
    129129            //   i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func.
    130130            //   ii. (Note: At most one wrapper is created for any closure, so func is unique, even if there are multiple occurrances in the list. Moreover, if the item was an import that is already an Exported Function Exotic Object, then the original function object will be found. For imports that are regular JS functions, a new wrapper will be created.)
    131             if (exp.functionIndex < importCount) {
     131            if (exp.kindIndex < importCount) {
    132132                // FIXME Implement re-exporting an import. https://bugs.webkit.org/show_bug.cgi?id=165510
    133133                RELEASE_ASSERT_NOT_REACHED();
     
    137137            //     b. Append func to funcs.
    138138            //     c. Return func.
    139             JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(exp.functionIndex);
    140             JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(exp.functionIndex);
    141             Wasm::Signature* signature = module->signatureForFunctionIndexSpace(exp.functionIndex);
     139            JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
     140            JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
     141            Wasm::Signature* signature = module->signatureForFunctionIndexSpace(exp.kindIndex);
    142142            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->arguments.size(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signature);
    143143            exportedValue = function;
    144             if (hasStart && startFunctionIndexSpace == exp.functionIndex)
     144            if (hasStart && startFunctionIndexSpace == exp.kindIndex)
    145145                m_startFunction.set(vm, this, function);
    146146            break;
     
    154154            break;
    155155        }
     156
    156157        case Wasm::External::Global: {
    157             // FIXME https://bugs.webkit.org/show_bug.cgi?id=164133
    158             // In the MVP, only immutable global variables can be exported.
     158            // Assert: the global is immutable by MVP validation constraint.
     159            const Wasm::Global& global = moduleInformation.globals[exp.kindIndex];
     160            ASSERT(global.mutability == Wasm::Global::Immutable);
     161            // Return ToJSValue(v).
     162            switch (global.type) {
     163            case Wasm::I32:
     164                exportedValue = JSValue(instance->loadI32Global(exp.kindIndex));
     165                break;
     166
     167            case Wasm::F32:
     168                exportedValue = JSValue(instance->loadF32Global(exp.kindIndex));
     169                break;
     170
     171            case Wasm::F64:
     172                exportedValue = JSValue(instance->loadF64Global(exp.kindIndex));
     173                break;
     174
     175            default:
     176                RELEASE_ASSERT_NOT_REACHED();
     177            }
    159178            break;
    160179        }
Note: See TracChangeset for help on using the changeset viewer.