Changeset 246139 in webkit


Ignore:
Timestamp:
Jun 5, 2019 8:14:47 PM (5 years ago)
Author:
Justin Michaud
Message:

[WASM-References] Add support for Anyref tables, Table.get and Table.set (for Anyref only).
https://bugs.webkit.org/show_bug.cgi?id=198398

Reviewed by Saam Barati.

JSTests:

  • wasm/references/anyref_table.js: Added.

(string_appeared_here.doGCSet):
(doGCTest):
(doGCSet.doGCTest.let.count.0.doBarrierSet):

  • wasm/references/anyref_table_import.js: Added.

(makeImport):
(string_appeared_here.fullGC.assert.eq.1.exports.get_tbl.makeImport):
(string_appeared_here.fullGC.assert.eq.1.exports.get_tbl):

  • wasm/references/is_null_error.js: Removed.
  • wasm/references/validation.js: Added.

(assert.throws.new.WebAssembly.Module.bin):
(assert.throws):

  • wasm/wasm.json:

Source/JavaScriptCore:

Create a new table subtype called FuncRefTable (note: Anyfunc was renamed to Funcref in the references spec).
Table now write-barriers and visits its children's wrapper objects. FuncRefTable caches some extra data to
support calling from wasm. A JSWebAssemblyTable is required to set an anyref element, but this is only because
we need to write barrier it (so it should not restrict how we implement threads). This patch does, however,
restrict the implementation of function references to require every Ref.func to have an associated wrapper. This
can be done statically, so this too should not restrict our threads implementation.

  • wasm/WasmAirIRGenerator.cpp:

(JSC::Wasm::AirIRGenerator::addTableGet):
(JSC::Wasm::AirIRGenerator::addTableSet):
(JSC::Wasm::AirIRGenerator::addCallIndirect):

  • wasm/WasmB3IRGenerator.cpp:

(JSC::Wasm::B3IRGenerator::addLocal):
(JSC::Wasm::B3IRGenerator::addTableGet):
(JSC::Wasm::B3IRGenerator::addTableSet):
(JSC::Wasm::B3IRGenerator::addCallIndirect):

  • wasm/WasmFormat.h:

(JSC::Wasm::TableInformation::TableInformation):
(JSC::Wasm::TableInformation::type const):

  • wasm/WasmFunctionParser.h:

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

  • wasm/WasmSectionParser.cpp:

(JSC::Wasm::SectionParser::parseTableHelper):

  • wasm/WasmTable.cpp:

(JSC::Wasm::Table::Table):
(JSC::Wasm::Table::tryCreate):
(JSC::Wasm::Table::grow):
(JSC::Wasm::Table::clear):
(JSC::Wasm::Table::set):
(JSC::Wasm::Table::get):
(JSC::Wasm::Table::visitChildren):
(JSC::Wasm::FuncRefTable::FuncRefTable):
(JSC::Wasm::FuncRefTable::setFunction):
(JSC::Wasm::Table::~Table): Deleted.
(JSC::Wasm::Table::clearFunction): Deleted.
(JSC::Wasm::Table::setFunction): Deleted.

  • wasm/WasmTable.h:

(JSC::Wasm::Table::length const):
(JSC::Wasm::Table::type const):
(JSC::Wasm::Table::setOwner):
(JSC::Wasm::FuncRefTable::offsetOfFunctions):
(JSC::Wasm::FuncRefTable::offsetOfInstances):
(JSC::Wasm::Table::offsetOfFunctions): Deleted.
(JSC::Wasm::Table::offsetOfInstances): Deleted.

  • wasm/WasmValidate.cpp:

(JSC::Wasm::Validate::addTableGet):
(JSC::Wasm::Validate::addTableSet):
(JSC::Wasm::Validate::addCallIndirect):

  • wasm/js/JSWebAssemblyTable.cpp:

(JSC::JSWebAssemblyTable::JSWebAssemblyTable):
(JSC::JSWebAssemblyTable::finishCreation):
(JSC::JSWebAssemblyTable::visitChildren):
(JSC::JSWebAssemblyTable::grow):
(JSC::JSWebAssemblyTable::get):
(JSC::JSWebAssemblyTable::set):
(JSC::JSWebAssemblyTable::clear):
(JSC::JSWebAssemblyTable::getFunction): Deleted.
(JSC::JSWebAssemblyTable::clearFunction): Deleted.
(JSC::JSWebAssemblyTable::setFunction): Deleted.

  • wasm/js/JSWebAssemblyTable.h:
  • wasm/js/WebAssemblyModuleRecord.cpp:

(JSC::WebAssemblyModuleRecord::link):
(JSC::WebAssemblyModuleRecord::evaluate):

  • wasm/js/WebAssemblyTableConstructor.cpp:

(JSC::constructJSWebAssemblyTable):

  • wasm/js/WebAssemblyTablePrototype.cpp:

(JSC::webAssemblyTableProtoFuncGet):
(JSC::webAssemblyTableProtoFuncSet):

  • wasm/wasm.json:
Location:
trunk
Files:
3 added
1 deleted
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r246134 r246139  
     12019-06-05  Justin Michaud  <justin_michaud@apple.com>
     2
     3        [WASM-References] Add support for Anyref tables, Table.get and Table.set (for Anyref only).
     4        https://bugs.webkit.org/show_bug.cgi?id=198398
     5
     6        Reviewed by Saam Barati.
     7
     8        * wasm/references/anyref_table.js: Added.
     9        (string_appeared_here.doGCSet):
     10        (doGCTest):
     11        (doGCSet.doGCTest.let.count.0.doBarrierSet):
     12        * wasm/references/anyref_table_import.js: Added.
     13        (makeImport):
     14        (string_appeared_here.fullGC.assert.eq.1.exports.get_tbl.makeImport):
     15        (string_appeared_here.fullGC.assert.eq.1.exports.get_tbl):
     16        * wasm/references/is_null_error.js: Removed.
     17        * wasm/references/validation.js: Added.
     18        (assert.throws.new.WebAssembly.Module.bin):
     19        (assert.throws):
     20        * wasm/wasm.json:
     21
    1222019-06-05  Justin Michaud  <justin_michaud@apple.com>
    223
  • trunk/JSTests/wasm/js-api/table.js

    r235420 r246139  
    133133    let badDescriptions = [
    134134        [{initial: 10, element: "i32"},
    135          "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc, got -1 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
    136          "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc, got -1 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
     135         "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc or anyref, got -1 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
     136         "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc or anyref, got -1 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
    137137        [{initial: 10, element: "f32"},
    138          "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc, got -3 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
    139          "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc, got -3 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
     138         "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc or anyref, got -3 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
     139         "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc or anyref, got -3 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
    140140        [{initial: 10, element: "f64"},
    141          "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc, got -4 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
    142          "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc, got -4 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
     141         "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc or anyref, got -4 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
     142         "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc or anyref, got -4 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
    143143        [{initial: 10, element: "i64"},
    144          "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc, got -2 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
    145          "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc, got -2 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
     144         "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc or anyref, got -2 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
     145         "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc or anyref, got -2 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
    146146        [{initial: 10, maximum: 20, element: "i32"},
    147          "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc, got -1 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
    148          "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc, got -1 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
     147         "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc or anyref, got -1 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
     148         "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc or anyref, got -1 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
    149149        [{initial: 10, maximum: 20, element: "f32"},
    150          "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc, got -3 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
    151          "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc, got -3 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
     150         "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc or anyref, got -3 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
     151         "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc or anyref, got -3 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
    152152        [{initial: 10, maximum: 20, element: "f64"},
    153          "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc, got -4 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
    154          "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc, got -4 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
     153         "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc or anyref, got -4 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
     154         "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc or anyref, got -4 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
    155155        [{initial: 10, maximum: 20, element: "i64"},
    156          "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc, got -2 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
    157          "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc, got -2 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
     156         "WebAssembly.Module doesn't parse at byte 18: Table type should be anyfunc or anyref, got -2 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')",
     157         "WebAssembly.Module doesn't parse at byte 26: Table type should be anyfunc or anyref, got -2 (evaluating 'new WebAssembly.Module(builder.WebAssembly().get())')"],
    158158
    159159        [{initial: 10, maximum: 9, element: "anyfunc"},
  • trunk/JSTests/wasm/wasm.json

    r245496 r246139  
    1919    "value_type": ["i32", "i64", "f32", "f64", "anyref"],
    2020    "block_type": ["i32", "i64", "f32", "f64", "void", "anyref"],
    21     "elem_type": ["anyfunc"],
     21    "elem_type": ["anyfunc","anyref"],
    2222    "external_kind": {
    2323        "Function": { "type": "uint8", "value": 0 },
     
    6767        "get_global":          { "category": "special",    "value":  35, "return": ["any"],      "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                            "description": "read a global variable" },
    6868        "set_global":          { "category": "special",    "value":  36, "return": [],           "parameter": ["any"],                  "immediate": [{"name": "global_index",   "type": "varuint32"}],                                            "description": "write a global variable" },
     69        "table.get":           { "category": "special",    "value":  37, "return": ["anyref"],   "parameter": ["i32"],                  "immediate": [],                                                                                           "description": "get a table value" },
     70        "table.set":           { "category": "special",    "value":  38, "return": [],           "parameter": ["i32", "anyref"],        "immediate": [],                                                                                           "description": "set a table value" },
    6971        "call":                { "category": "call",       "value":  16, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                            "description": "call a function by its index" },
    7072        "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

    r246134 r246139  
     12019-06-05  Justin Michaud  <justin_michaud@apple.com>
     2
     3        [WASM-References] Add support for Anyref tables, Table.get and Table.set (for Anyref only).
     4        https://bugs.webkit.org/show_bug.cgi?id=198398
     5
     6        Reviewed by Saam Barati.
     7
     8        Create a new table subtype called FuncRefTable (note: Anyfunc was renamed to Funcref in the references spec).
     9        Table now write-barriers and visits its children's wrapper objects. FuncRefTable caches some extra data to
     10        support calling from wasm. A JSWebAssemblyTable is required to set an anyref element, but this is only because
     11        we need to write barrier it (so it should not restrict how we implement threads). This patch does, however,
     12        restrict the implementation of function references to require every Ref.func to have an associated wrapper. This
     13        can be done statically, so this too should not restrict our threads implementation.
     14
     15        * wasm/WasmAirIRGenerator.cpp:
     16        (JSC::Wasm::AirIRGenerator::addTableGet):
     17        (JSC::Wasm::AirIRGenerator::addTableSet):
     18        (JSC::Wasm::AirIRGenerator::addCallIndirect):
     19        * wasm/WasmB3IRGenerator.cpp:
     20        (JSC::Wasm::B3IRGenerator::addLocal):
     21        (JSC::Wasm::B3IRGenerator::addTableGet):
     22        (JSC::Wasm::B3IRGenerator::addTableSet):
     23        (JSC::Wasm::B3IRGenerator::addCallIndirect):
     24        * wasm/WasmFormat.h:
     25        (JSC::Wasm::TableInformation::TableInformation):
     26        (JSC::Wasm::TableInformation::type const):
     27        * wasm/WasmFunctionParser.h:
     28        (JSC::Wasm::FunctionParser<Context>::parseExpression):
     29        (JSC::Wasm::FunctionParser<Context>::parseUnreachableExpression):
     30        * wasm/WasmSectionParser.cpp:
     31        (JSC::Wasm::SectionParser::parseTableHelper):
     32        * wasm/WasmTable.cpp:
     33        (JSC::Wasm::Table::Table):
     34        (JSC::Wasm::Table::tryCreate):
     35        (JSC::Wasm::Table::grow):
     36        (JSC::Wasm::Table::clear):
     37        (JSC::Wasm::Table::set):
     38        (JSC::Wasm::Table::get):
     39        (JSC::Wasm::Table::visitChildren):
     40        (JSC::Wasm::FuncRefTable::FuncRefTable):
     41        (JSC::Wasm::FuncRefTable::setFunction):
     42        (JSC::Wasm::Table::~Table): Deleted.
     43        (JSC::Wasm::Table::clearFunction): Deleted.
     44        (JSC::Wasm::Table::setFunction): Deleted.
     45        * wasm/WasmTable.h:
     46        (JSC::Wasm::Table::length const):
     47        (JSC::Wasm::Table::type const):
     48        (JSC::Wasm::Table::setOwner):
     49        (JSC::Wasm::FuncRefTable::offsetOfFunctions):
     50        (JSC::Wasm::FuncRefTable::offsetOfInstances):
     51        (JSC::Wasm::Table::offsetOfFunctions): Deleted.
     52        (JSC::Wasm::Table::offsetOfInstances): Deleted.
     53        * wasm/WasmValidate.cpp:
     54        (JSC::Wasm::Validate::addTableGet):
     55        (JSC::Wasm::Validate::addTableSet):
     56        (JSC::Wasm::Validate::addCallIndirect):
     57        * wasm/js/JSWebAssemblyTable.cpp:
     58        (JSC::JSWebAssemblyTable::JSWebAssemblyTable):
     59        (JSC::JSWebAssemblyTable::finishCreation):
     60        (JSC::JSWebAssemblyTable::visitChildren):
     61        (JSC::JSWebAssemblyTable::grow):
     62        (JSC::JSWebAssemblyTable::get):
     63        (JSC::JSWebAssemblyTable::set):
     64        (JSC::JSWebAssemblyTable::clear):
     65        (JSC::JSWebAssemblyTable::getFunction): Deleted.
     66        (JSC::JSWebAssemblyTable::clearFunction): Deleted.
     67        (JSC::JSWebAssemblyTable::setFunction): Deleted.
     68        * wasm/js/JSWebAssemblyTable.h:
     69        * wasm/js/WebAssemblyModuleRecord.cpp:
     70        (JSC::WebAssemblyModuleRecord::link):
     71        (JSC::WebAssemblyModuleRecord::evaluate):
     72        * wasm/js/WebAssemblyTableConstructor.cpp:
     73        (JSC::constructJSWebAssemblyTable):
     74        * wasm/js/WebAssemblyTablePrototype.cpp:
     75        (JSC::webAssemblyTableProtoFuncGet):
     76        (JSC::webAssemblyTableProtoFuncSet):
     77        * wasm/wasm.json:
     78
    1792019-06-05  Justin Michaud  <justin_michaud@apple.com>
    280
  • trunk/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp

    r245895 r246139  
    233233    ExpressionType addConstant(BasicBlock*, Type, uint64_t);
    234234
     235    // References
    235236    PartialResult WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result);
     237
     238    // Tables
     239    PartialResult WARN_UNUSED_RETURN addTableGet(ExpressionType& idx, ExpressionType& result);
     240    PartialResult WARN_UNUSED_RETURN addTableSet(ExpressionType& idx, ExpressionType& value);
    236241
    237242    // Locals
     
    950955}
    951956
     957auto AirIRGenerator::addTableGet(ExpressionType& idx, ExpressionType& result) -> PartialResult
     958{
     959    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
     960    ASSERT(idx.tmp());
     961    ASSERT(idx.type() == Type::I32);
     962    result = tmpForType(Type::Anyref);
     963
     964    uint64_t (*doGet)(Instance*, int32_t) = [] (Instance* instance, int32_t idx) -> uint64_t {
     965        return JSValue::encode(instance->table()->get(idx));
     966    };
     967
     968    emitCCall(doGet, result, instanceValue(), idx);
     969
     970    return { };
     971}
     972
     973auto AirIRGenerator::addTableSet(ExpressionType& idx, ExpressionType& value) -> PartialResult
     974{
     975    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
     976    ASSERT(idx.tmp());
     977    ASSERT(idx.type() == Type::I32);
     978    ASSERT(value.tmp());
     979
     980    void (*doSet)(Instance*, int32_t, uint64_t value) = [] (Instance* instance, int32_t idx, uint64_t value) -> void {
     981        // FIXME: We need to box wasm Funcrefs once they are supported here.
     982        // <https://bugs.webkit.org/show_bug.cgi?id=198157>
     983        instance->table()->set(idx, JSValue::decode(value));
     984    };
     985
     986    emitCCall(doSet, TypedTmp(), instanceValue(), idx, value);
     987
     988    return { };
     989}
     990
    952991auto AirIRGenerator::getLocal(uint32_t index, ExpressionType& result) -> PartialResult
    953992{
     
    18421881    ExpressionType calleeIndex = args.takeLast();
    18431882    ASSERT(signature.argumentCount() == args.size());
     1883    ASSERT(m_info.tableInformation.type() == TableElementType::Funcref);
    18441884
    18451885    m_makesCalls = true;
     
    18571897    {
    18581898        RELEASE_ASSERT(Arg::isValidAddrForm(Instance::offsetOfTable(), B3::Width64));
    1859         RELEASE_ASSERT(Arg::isValidAddrForm(Table::offsetOfFunctions(), B3::Width64));
    1860         RELEASE_ASSERT(Arg::isValidAddrForm(Table::offsetOfInstances(), B3::Width64));
    1861         RELEASE_ASSERT(Arg::isValidAddrForm(Table::offsetOfLength(), B3::Width64));
     1899        RELEASE_ASSERT(Arg::isValidAddrForm(FuncRefTable::offsetOfFunctions(), B3::Width64));
     1900        RELEASE_ASSERT(Arg::isValidAddrForm(FuncRefTable::offsetOfInstances(), B3::Width64));
     1901        RELEASE_ASSERT(Arg::isValidAddrForm(FuncRefTable::offsetOfLength(), B3::Width64));
    18621902
    18631903        append(Move, Arg::addr(instanceValue(), Instance::offsetOfTable()), callableFunctionBufferLength);
    1864         append(Move, Arg::addr(callableFunctionBufferLength, Table::offsetOfFunctions()), callableFunctionBuffer);
    1865         append(Move, Arg::addr(callableFunctionBufferLength, Table::offsetOfInstances()), instancesBuffer);
     1904        append(Move, Arg::addr(callableFunctionBufferLength, FuncRefTable::offsetOfFunctions()), callableFunctionBuffer);
     1905        append(Move, Arg::addr(callableFunctionBufferLength, FuncRefTable::offsetOfInstances()), instancesBuffer);
    18661906        append(Move32, Arg::addr(callableFunctionBufferLength, Table::offsetOfLength()), callableFunctionBufferLength);
    18671907    }
  • trunk/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp

    r245895 r246139  
    186186    ExpressionType addConstant(Type, uint64_t);
    187187
     188    // References
    188189    PartialResult WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result);
     190
     191    // Tables
     192    PartialResult WARN_UNUSED_RETURN addTableGet(ExpressionType& idx, ExpressionType& result);
     193    PartialResult WARN_UNUSED_RETURN addTableSet(ExpressionType& idx, ExpressionType& value);
    189194
    190195    // Locals
     
    562567}
    563568
     569auto B3IRGenerator::addTableGet(ExpressionType& idx, ExpressionType& result) -> PartialResult
     570{
     571    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
     572    uint64_t (*doGet)(Instance*, int32_t) = [] (Instance* instance, int32_t idx) -> uint64_t {
     573        return JSValue::encode(instance->table()->get(idx));
     574    };
     575
     576    result = m_currentBlock->appendNew<CCallValue>(m_proc, toB3Type(Anyref), origin(),
     577        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunctionPtr<void*>(doGet, B3CCallPtrTag)),
     578        instanceValue(), idx);
     579
     580    return { };
     581}
     582
     583auto B3IRGenerator::addTableSet(ExpressionType& idx, ExpressionType& value) -> PartialResult
     584{
     585    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
     586    void (*doSet)(Instance*, int32_t, uint64_t value) = [] (Instance* instance, int32_t idx, uint64_t value) -> void {
     587        // FIXME: We need to box wasm Funcrefs once they are supported here.
     588        // <https://bugs.webkit.org/show_bug.cgi?id=198157>
     589        instance->table()->set(idx, JSValue::decode(value));
     590    };
     591
     592    m_currentBlock->appendNew<CCallValue>(m_proc, B3::Void, origin(),
     593        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunctionPtr<void*>(doSet, B3CCallPtrTag)),
     594        instanceValue(), idx, value);
     595
     596    return { };
     597}
     598
    564599auto B3IRGenerator::getLocal(uint32_t index, ExpressionType& result) -> PartialResult
    565600{
     
    12641299            instanceValue(), safeCast<int32_t>(Instance::offsetOfTable()));
    12651300        callableFunctionBuffer = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
    1266             table, safeCast<int32_t>(Table::offsetOfFunctions()));
     1301            table, safeCast<int32_t>(FuncRefTable::offsetOfFunctions()));
    12671302        instancesBuffer = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), origin(),
    1268             table, safeCast<int32_t>(Table::offsetOfInstances()));
     1303            table, safeCast<int32_t>(FuncRefTable::offsetOfInstances()));
    12691304        callableFunctionBufferLength = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, origin(),
    12701305            table, safeCast<int32_t>(Table::offsetOfLength()));
  • trunk/Source/JavaScriptCore/wasm/WasmFormat.h

    r245496 r246139  
    5555struct ModuleInformation;
    5656
     57enum class TableElementType : uint8_t {
     58    Anyref,
     59    Funcref
     60};
     61
    5762inline bool isValueType(Type type)
    5863{
     
    215220    }
    216221
    217     TableInformation(uint32_t initial, Optional<uint32_t> maximum, bool isImport)
     222    TableInformation(uint32_t initial, Optional<uint32_t> maximum, bool isImport, TableElementType type)
    218223        : m_initial(initial)
    219224        , m_maximum(maximum)
    220225        , m_isImport(isImport)
    221226        , m_isValid(true)
     227        , m_type(type)
    222228    {
    223229        ASSERT(*this);
     
    228234    uint32_t initial() const { return m_initial; }
    229235    Optional<uint32_t> maximum() const { return m_maximum; }
     236    TableElementType type() const { return m_type; }
    230237
    231238private:
     
    234241    bool m_isImport { false };
    235242    bool m_isValid { false };
     243    TableElementType m_type;
    236244};
    237245   
  • trunk/Source/JavaScriptCore/wasm/WasmFunctionParser.h

    r245496 r246139  
    282282    }
    283283
     284    case TableGet: {
     285        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
     286        ExpressionType result, idx;
     287        WASM_TRY_POP_EXPRESSION_STACK_INTO(idx, "table.get");
     288        WASM_TRY_ADD_TO_CONTEXT(addTableGet(idx, result));
     289        m_expressionStack.append(result);
     290        return { };
     291    }
     292
     293    case TableSet: {
     294        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
     295        ExpressionType val, idx;
     296        WASM_TRY_POP_EXPRESSION_STACK_INTO(val, "table.set");
     297        WASM_TRY_POP_EXPRESSION_STACK_INTO(idx, "table.set");
     298        WASM_TRY_ADD_TO_CONTEXT(addTableSet(idx, val));
     299        return { };
     300    }
     301
    284302    case RefNull: {
    285303        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
     
    374392        WASM_PARSER_FAIL_IF(reserved, "call_indirect's 'reserved' varuint1 must be 0x0");
    375393        WASM_PARSER_FAIL_IF(m_info.usedSignatures.size() <= signatureIndex, "call_indirect's signature index ", signatureIndex, " exceeds known signatures ", m_info.usedSignatures.size());
     394        WASM_PARSER_FAIL_IF(m_info.tableInformation.type() != TableElementType::Funcref, "call_indirect is only valid when a table has type anyfunc");
    376395
    377396        const Signature& calleeSignature = m_info.usedSignatures[signatureIndex].get();
     
    655674    }
    656675
     676    case TableGet:
     677    case TableSet:
     678    case RefIsNull:
    657679    case RefNull: {
    658         WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
    659         return { };
    660     }
    661 
    662     case RefIsNull: {
    663680        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
    664681        return { };
  • trunk/Source/JavaScriptCore/wasm/WasmSectionParser.cpp

    r245765 r246139  
    197197    int8_t type;
    198198    WASM_PARSER_FAIL_IF(!parseInt7(type), "can't parse Table type");
    199     WASM_PARSER_FAIL_IF(type != Wasm::Anyfunc, "Table type should be anyfunc, got ", type);
     199    WASM_PARSER_FAIL_IF(type != Wasm::Anyfunc && type != Wasm::Anyref, "Table type should be anyfunc or anyref, got ", type);
    200200
    201201    uint32_t initial;
     
    208208    ASSERT(!maximum || *maximum >= initial);
    209209
    210     m_info->tableInformation = TableInformation(initial, maximum, isImport);
     210    TableElementType tableType = type == Wasm::Anyfunc ? TableElementType::Funcref : TableElementType::Anyref;
     211    m_info->tableInformation = TableInformation(initial, maximum, isImport, tableType);
    211212
    212213    return { };
  • trunk/Source/JavaScriptCore/wasm/WasmTable.cpp

    r239427 r246139  
    4848}
    4949
    50 RefPtr<Table> Table::tryCreate(uint32_t initial, Optional<uint32_t> maximum)
    51 {
    52     if (!isValidLength(initial))
    53         return nullptr;
    54     return adoptRef(new (NotNull, fastMalloc(sizeof(Table))) Table(initial, maximum));
    55 }
    56 
    57 Table::~Table()
    58 {
    59 }
    60 
    61 Table::Table(uint32_t initial, Optional<uint32_t> maximum)
     50Table::Table(uint32_t initial, Optional<uint32_t> maximum, TableElementType type)
     51    : m_type(type)
     52    , m_maximum(maximum)
     53    , m_owner(nullptr)
    6254{
    6355    setLength(initial);
    64     m_maximum = maximum;
    6556    ASSERT(!m_maximum || *m_maximum >= m_length);
    6657
    6758    // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
    6859    // But for now, we're not doing that.
    69     m_importableFunctions = MallocPtr<WasmToWasmImportableFunction>::malloc((sizeof(WasmToWasmImportableFunction) * Checked<size_t>(allocatedLength(m_length))).unsafeGet());
    7060    // FIXME this over-allocates and could be smarter about not committing all of that memory https://bugs.webkit.org/show_bug.cgi?id=181425
    71     m_instances = MallocPtr<Instance*>::malloc((sizeof(Instance*) * Checked<size_t>(allocatedLength(m_length))).unsafeGet());
     61    m_jsValues = MallocPtr<WriteBarrier<Unknown>>::malloc((sizeof(WriteBarrier<Unknown>) * Checked<size_t>(allocatedLength(m_length))).unsafeGet());
    7262    for (uint32_t i = 0; i < allocatedLength(m_length); ++i) {
    73         new (&m_importableFunctions.get()[i]) WasmToWasmImportableFunction();
    74         ASSERT(m_importableFunctions.get()[i].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
    75         m_instances.get()[i] = nullptr;
     63        new (&m_jsValues.get()[i]) WriteBarrier<Unknown>();
     64        m_jsValues.get()[i].setStartingValue(jsNull());
     65    }
     66}
     67
     68RefPtr<Table> Table::tryCreate(uint32_t initial, Optional<uint32_t> maximum, TableElementType type)
     69{
     70    if (!isValidLength(initial))
     71        return nullptr;
     72    switch (type) {
     73    case TableElementType::Funcref:
     74        return adoptRef(new FuncRefTable(initial, maximum));
     75    case TableElementType::Anyref:
     76        return adoptRef(new Table(initial, maximum));
    7677    }
    7778}
     
    7980Optional<uint32_t> Table::grow(uint32_t delta)
    8081{
     82    RELEASE_ASSERT(m_owner);
    8183    if (delta == 0)
    8284        return length();
     85
     86    auto locker = holdLock(m_owner->cellLock());
    8387
    8488    using Checked = Checked<uint32_t, RecordOverflow>;
     
    109113    };
    110114
    111     if (!checkedGrow(m_importableFunctions))
    112         return WTF::nullopt;
    113     if (!checkedGrow(m_instances))
     115    if (auto* funcRefTable = asFuncrefTable()) {
     116        if (!checkedGrow(funcRefTable->m_importableFunctions))
     117            return WTF::nullopt;
     118        if (!checkedGrow(funcRefTable->m_instances))
     119            return WTF::nullopt;
     120    }
     121
     122    if (!checkedGrow(m_jsValues))
    114123        return WTF::nullopt;
    115124
    116125    setLength(newLength);
    117 
    118126    return newLength;
    119127}
    120128
    121 void Table::clearFunction(uint32_t index)
     129void Table::clear(uint32_t index)
    122130{
    123131    RELEASE_ASSERT(index < length());
    124     m_importableFunctions.get()[index & m_mask] = WasmToWasmImportableFunction();
    125     ASSERT(m_importableFunctions.get()[index & m_mask].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
    126     m_instances.get()[index & m_mask] = nullptr;
     132    RELEASE_ASSERT(m_owner);
     133    if (auto* funcRefTable = asFuncrefTable()) {
     134        funcRefTable->m_importableFunctions.get()[index & m_mask] = WasmToWasmImportableFunction();
     135        ASSERT(funcRefTable->m_importableFunctions.get()[index & m_mask].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
     136        funcRefTable->m_instances.get()[index & m_mask] = nullptr;
     137    }
     138    m_jsValues.get()[index & m_mask].setStartingValue(jsNull());
    127139}
    128140
    129 void Table::setFunction(uint32_t index, WasmToWasmImportableFunction function, Instance* instance)
     141void Table::set(uint32_t index, JSValue value)
    130142{
    131143    RELEASE_ASSERT(index < length());
     144    RELEASE_ASSERT(isAnyrefTable());
     145    RELEASE_ASSERT(m_owner);
     146    clear(index);
     147    m_jsValues.get()[index & m_mask].set(*m_owner->vm(), m_owner, value);
     148}
     149
     150JSValue Table::get(uint32_t index) const
     151{
     152    RELEASE_ASSERT(index < length());
     153    RELEASE_ASSERT(m_owner);
     154    return m_jsValues.get()[index & m_mask].get();
     155}
     156
     157void Table::visitChildren(SlotVisitor& visitor)
     158{
     159    RELEASE_ASSERT(m_owner);
     160    auto locker = holdLock(m_owner->cellLock());
     161    for (unsigned i = 0; i < m_length; ++i)
     162        visitor.append(m_jsValues.get()[i]);
     163}
     164
     165FuncRefTable* Table::asFuncrefTable()
     166{
     167    return m_type == TableElementType::Funcref ? static_cast<FuncRefTable*>(this) : nullptr;
     168}
     169
     170FuncRefTable::FuncRefTable(uint32_t initial, Optional<uint32_t> maximum)
     171    : Table(initial, maximum, TableElementType::Funcref)
     172{
     173    // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
     174    // But for now, we're not doing that.
     175    m_importableFunctions = MallocPtr<WasmToWasmImportableFunction>::malloc((sizeof(WasmToWasmImportableFunction) * Checked<size_t>(allocatedLength(m_length))).unsafeGet());
     176    // FIXME this over-allocates and could be smarter about not committing all of that memory https://bugs.webkit.org/show_bug.cgi?id=181425
     177    m_instances = MallocPtr<Instance*>::malloc((sizeof(Instance*) * Checked<size_t>(allocatedLength(m_length))).unsafeGet());
     178    for (uint32_t i = 0; i < allocatedLength(m_length); ++i) {
     179        new (&m_importableFunctions.get()[i]) WasmToWasmImportableFunction();
     180        ASSERT(m_importableFunctions.get()[i].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
     181        m_instances.get()[i] = nullptr;
     182    }
     183}
     184
     185void FuncRefTable::setFunction(uint32_t index, JSObject* optionalWrapper, WasmToWasmImportableFunction function, Instance* instance)
     186{
     187    RELEASE_ASSERT(index < length());
     188    RELEASE_ASSERT(m_owner);
     189    clear(index);
     190    if (optionalWrapper)
     191        m_jsValues.get()[index & m_mask].set(*m_owner->vm(), m_owner, optionalWrapper);
    132192    m_importableFunctions.get()[index & m_mask] = function;
    133193    m_instances.get()[index & m_mask] = instance;
  • trunk/Source/JavaScriptCore/wasm/WasmTable.h

    r239427 r246139  
    3030#include "WasmFormat.h"
    3131#include "WasmLimits.h"
     32#include "WriteBarrier.h"
    3233#include <wtf/MallocPtr.h>
    3334#include <wtf/Optional.h>
     
    3839
    3940class Instance;
     41class FuncRefTable;
    4042
    4143class Table : public ThreadSafeRefCounted<Table> {
     44    WTF_MAKE_NONCOPYABLE(Table);
     45    WTF_MAKE_FAST_ALLOCATED(Table);
    4246public:
    43     static RefPtr<Table> tryCreate(uint32_t initial, Optional<uint32_t> maximum);
     47    static RefPtr<Table> tryCreate(uint32_t initial, Optional<uint32_t> maximum, TableElementType);
    4448
    45     JS_EXPORT_PRIVATE ~Table();
     49    JS_EXPORT_PRIVATE ~Table() = default;
    4650
    4751    Optional<uint32_t> maximum() const { return m_maximum; }
    4852    uint32_t length() const { return m_length; }
    49     Optional<uint32_t> grow(uint32_t delta) WARN_UNUSED_RETURN;
    50     void clearFunction(uint32_t);
    51     void setFunction(uint32_t, WasmToWasmImportableFunction, Instance*);
    5253
    53     static ptrdiff_t offsetOfFunctions() { return OBJECT_OFFSETOF(Table, m_importableFunctions); }
    54     static ptrdiff_t offsetOfInstances() { return OBJECT_OFFSETOF(Table, m_instances); }
    5554    static ptrdiff_t offsetOfLength() { return OBJECT_OFFSETOF(Table, m_length); }
    5655    static ptrdiff_t offsetOfMask() { return OBJECT_OFFSETOF(Table, m_mask); }
     
    5857    static uint32_t allocatedLength(uint32_t length);
    5958    uint32_t mask() const { return m_mask; }
     59
     60    void setOwner(JSObject* owner)
     61    {
     62        ASSERT(!m_owner);
     63        ASSERT(owner);
     64        m_owner = owner;
     65    }
     66
     67    TableElementType type() const { return m_type; }
     68    bool isAnyrefTable() const { return m_type == TableElementType::Anyref; }
     69    FuncRefTable* asFuncrefTable();
     70
    6071    static bool isValidLength(uint32_t length) { return length < maxTableEntries; }
    6172
    62 private:
    63     Table(uint32_t initial, Optional<uint32_t> maximum);
     73    void clear(uint32_t);
     74    void set(uint32_t, JSValue);
     75    JSValue get(uint32_t) const;
     76
     77    Optional<uint32_t> grow(uint32_t delta);
     78
     79    void visitChildren(SlotVisitor&);
     80
     81protected:
     82    Table(uint32_t initial, Optional<uint32_t> maximum, TableElementType = TableElementType::Anyref);
    6483
    6584    void setLength(uint32_t);
     85
     86    uint32_t m_length;
     87    uint32_t m_mask;
     88    const TableElementType m_type;
     89    const Optional<uint32_t> m_maximum;
     90
     91    MallocPtr<WriteBarrier<Unknown>> m_jsValues;
     92    JSObject* m_owner;
     93};
     94
     95class FuncRefTable : public Table {
     96public:
     97    JS_EXPORT_PRIVATE ~FuncRefTable() = default;
     98
     99    void setFunction(uint32_t, JSObject*, WasmToWasmImportableFunction, Instance*);
     100
     101    static ptrdiff_t offsetOfFunctions() { return OBJECT_OFFSETOF(FuncRefTable, m_importableFunctions); }
     102    static ptrdiff_t offsetOfInstances() { return OBJECT_OFFSETOF(FuncRefTable, m_instances); }
     103
     104private:
     105    FuncRefTable(uint32_t initial, Optional<uint32_t> maximum);
    66106
    67107    MallocPtr<WasmToWasmImportableFunction> m_importableFunctions;
    68108    // call_indirect needs to do an Instance check to potentially context switch when calling a function to another instance. We can hold raw pointers to Instance here because the embedder ensures that Table keeps all the instances alive. We couldn't hold a Ref here because it would cause cycles.
    69109    MallocPtr<Instance*> m_instances;
    70     uint32_t m_length;
    71     uint32_t m_mask;
    72     Optional<uint32_t> m_maximum;
     110
     111    friend class Table;
    73112};
    74113
  • trunk/Source/JavaScriptCore/wasm/WasmValidate.cpp

    r245496 r246139  
    101101    ExpressionType addConstant(Type type, uint64_t) { return type; }
    102102
     103    // References
    103104    Result WARN_UNUSED_RETURN addRefIsNull(ExpressionType& value, ExpressionType& result);
     105
     106    // Tables
     107    Result WARN_UNUSED_RETURN addTableGet(ExpressionType& idx, ExpressionType& result);
     108    Result WARN_UNUSED_RETURN addTableSet(ExpressionType& idx, ExpressionType& value);
    104109
    105110    // Locals
     
    172177}
    173178
     179auto Validate::addTableGet(ExpressionType& idx, ExpressionType& result) -> Result
     180{
     181    result = Type::Anyref;
     182    WASM_VALIDATOR_FAIL_IF(Type::I32 != idx, "table.get index to type ", idx, " expected ", Type::I32);
     183    WASM_VALIDATOR_FAIL_IF(TableElementType::Anyref != m_module.tableInformation.type(), "table.get expects the table to have type ", Type::Anyref);
     184
     185    return { };
     186}
     187
     188auto Validate::addTableSet(ExpressionType& idx, ExpressionType& value) -> Result
     189{
     190    WASM_VALIDATOR_FAIL_IF(Type::I32 != idx, "table.set index to type ", idx, " expected ", Type::I32);
     191    WASM_VALIDATOR_FAIL_IF(Type::Anyref != value, "table.set value to type ", value, " expected ", Type::Anyref);
     192    WASM_VALIDATOR_FAIL_IF(TableElementType::Anyref != m_module.tableInformation.type(), "table.set expects the table to have type ", Type::Anyref);
     193
     194    return { };
     195}
     196
    174197auto Validate::addRefIsNull(ExpressionType& value, ExpressionType& result) -> Result
    175198{
     
    347370auto Validate::addCallIndirect(const Signature& signature, const Vector<ExpressionType>& args, ExpressionType& result) -> Result
    348371{
     372    WASM_VALIDATOR_FAIL_IF(m_module.tableInformation.type() != TableElementType::Funcref, "Table must have type Anyfunc to call");
    349373    const auto argumentCount = signature.argumentCount();
    350374    WASM_VALIDATOR_FAIL_IF(argumentCount != args.size() - 1, "arity mismatch in call_indirect, got ", args.size() - 1, " arguments, expected ", argumentCount);
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.cpp

    r242123 r246139  
    4848
    4949    auto* instance = new (NotNull, allocateCell<JSWebAssemblyTable>(vm.heap)) JSWebAssemblyTable(vm, structure, WTFMove(table));
     50    instance->table()->setOwner(instance);
    5051    instance->finishCreation(vm);
    5152    return instance;
     
    6162    , m_table(WTFMove(table))
    6263{
    63     // FIXME: It might be worth trying to pre-allocate maximum here. The spec recommends doing so.
    64     // But for now, we're not doing that.
    65     // FIXME this over-allocates and could be smarter about not committing all of that memory https://bugs.webkit.org/show_bug.cgi?id=181425
    66     m_jsFunctions = MallocPtr<WriteBarrier<JSObject>>::malloc((sizeof(WriteBarrier<JSObject>) * Checked<size_t>(allocatedLength())).unsafeGet());
    67     for (uint32_t i = 0; i < allocatedLength(); ++i)
    68         new(&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
    6964}
    7065
     
    8681
    8782    Base::visitChildren(thisObject, visitor);
    88 
    89     for (unsigned i = 0; i < thisObject->length(); ++i)
    90         visitor.append(thisObject->m_jsFunctions.get()[i]);
     83    thisObject->table()->visitChildren(visitor);
    9184}
    9285
     
    9588    if (delta == 0)
    9689        return true;
    97 
    98     size_t oldLength = length();
    99 
    100     auto grew = m_table->grow(delta);
    101     if (!grew)
    102         return false;
    103 
    104     size_t newLength = grew.value();
    105     if (newLength > m_table->allocatedLength(oldLength))
    106         // FIXME this over-allocates and could be smarter about not committing all of that memory https://bugs.webkit.org/show_bug.cgi?id=181425
    107         m_jsFunctions.realloc((sizeof(WriteBarrier<JSObject>) * Checked<size_t>(m_table->allocatedLength(newLength))).unsafeGet());
    108 
    109     for (size_t i = oldLength; i < m_table->allocatedLength(newLength); ++i)
    110         new (&m_jsFunctions.get()[i]) WriteBarrier<JSObject>();
    111 
    112     return true;
     90    return !!m_table->grow(delta);
    11391}
    11492
    115 JSObject* JSWebAssemblyTable::getFunction(uint32_t index)
     93JSValue JSWebAssemblyTable::get(uint32_t index)
    11694{
    11795    RELEASE_ASSERT(index < length());
    118     return m_jsFunctions.get()[index & m_table->mask()].get();
     96    return m_table->get(index);
    11997}
    12098
    121 void JSWebAssemblyTable::clearFunction(uint32_t index)
     99void JSWebAssemblyTable::set(uint32_t index, JSValue value)
    122100{
    123     m_table->clearFunction(index);
    124     m_jsFunctions.get()[index & m_table->mask()] = WriteBarrier<JSObject>();
     101    RELEASE_ASSERT(index < length());
     102    RELEASE_ASSERT(m_table->isAnyrefTable());
     103    m_table->set(index, value);
    125104}
    126105
    127 void JSWebAssemblyTable::setFunction(VM& vm, uint32_t index, WebAssemblyFunction* function)
     106void JSWebAssemblyTable::set(uint32_t index, WebAssemblyFunction* function)
    128107{
    129     m_table->setFunction(index, function->importableFunction(), &function->instance()->instance());
    130     m_jsFunctions.get()[index & m_table->mask()].set(vm, this, function);
     108    RELEASE_ASSERT(index < length());
     109    RELEASE_ASSERT(m_table->asFuncrefTable());
     110    auto& subThis = *static_cast<Wasm::FuncRefTable*>(&m_table.get());
     111    subThis.setFunction(index, function, function->importableFunction(), &function->instance()->instance());
    131112}
    132113
    133 void JSWebAssemblyTable::setFunction(VM& vm, uint32_t index, WebAssemblyWrapperFunction* function)
     114void JSWebAssemblyTable::set(uint32_t index, WebAssemblyWrapperFunction* function)
    134115{
    135     m_table->setFunction(index, function->importableFunction(), &function->instance()->instance());
    136     m_jsFunctions.get()[index & m_table->mask()].set(vm, this, function);
     116    RELEASE_ASSERT(index < length());
     117    RELEASE_ASSERT(m_table->asFuncrefTable());
     118    auto& subThis = *static_cast<Wasm::FuncRefTable*>(&m_table.get());
     119    subThis.setFunction(index, function, function->importableFunction(), &function->instance()->instance());
     120}
     121
     122void JSWebAssemblyTable::clear(uint32_t index)
     123{
     124    RELEASE_ASSERT(index < length());
     125    m_table->clear(index);
    137126}
    138127
  • trunk/Source/JavaScriptCore/wasm/js/JSWebAssemblyTable.h

    r242123 r246139  
    5353    uint32_t allocatedLength() const { return m_table->allocatedLength(length()); }
    5454    bool grow(uint32_t delta) WARN_UNUSED_RETURN;
    55     JSObject* getFunction(uint32_t);
    56     void clearFunction(uint32_t);
    57     void setFunction(VM&, uint32_t, WebAssemblyFunction*);
    58     void setFunction(VM&, uint32_t, WebAssemblyWrapperFunction*);
     55    JSValue get(uint32_t);
     56    void set(uint32_t, WebAssemblyFunction*);
     57    void set(uint32_t, WebAssemblyWrapperFunction*);
     58    void set(uint32_t, JSValue);
     59    void clear(uint32_t);
    5960
    6061    Wasm::Table* table() { return m_table.ptr(); }
     
    6768
    6869    Ref<Wasm::Table> m_table;
    69     MallocPtr<WriteBarrier<JSObject>> m_jsFunctions;
    7070};
    7171
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp

    r245765 r246139  
    281281            }
    282282
     283            auto expectedType = moduleInformation.tableInformation.type();
     284            auto actualType = table->table()->type();
     285            if (expectedType != actualType)
     286                return exception(createJSWebAssemblyLinkError(exec, vm, importFailMessage(import, "Table import", "provided a 'type' that is wrong")));
     287
    283288            // ii. Append v to tables.
    284289            // iii. Append v.[[Table]] to imports.
     
    302307            RELEASE_ASSERT(!moduleInformation.tableInformation.isImport());
    303308            // We create a Table when it's a Table definition.
    304             RefPtr<Wasm::Table> wasmTable = Wasm::Table::tryCreate(moduleInformation.tableInformation.initial(), moduleInformation.tableInformation.maximum());
     309            RefPtr<Wasm::Table> wasmTable = Wasm::Table::tryCreate(moduleInformation.tableInformation.initial(), moduleInformation.tableInformation.maximum(), moduleInformation.tableInformation.type());
    305310            if (!wasmTable)
    306311                return exception(createJSWebAssemblyLinkError(exec, vm, "couldn't create Table"));
     
    537542                    // the only type this could be is WebAssemblyFunction.
    538543                    RELEASE_ASSERT(wasmFunction);
    539                     table->setFunction(vm, tableIndex, wasmFunction);
     544                    table->set(tableIndex, wasmFunction);
    540545                    ++tableIndex;
    541546                    continue;
    542547                }
    543548
    544                 table->setFunction(vm, tableIndex,
     549                table->set(tableIndex,
    545550                    WebAssemblyWrapperFunction::create(vm, globalObject, globalObject->webAssemblyWrapperFunctionStructure(), functionImport, functionIndex, m_instance.get(), signatureIndex));
    546551                ++tableIndex;
     
    558563                vm, globalObject, globalObject->webAssemblyFunctionStructure(), signature.argumentCount(), String(), m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex);
    559564
    560             table->setFunction(vm, tableIndex, function);
     565            table->set(tableIndex, function);
    561566            ++tableIndex;
    562567        }
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyTableConstructor.cpp

    r243051 r246139  
    5959    }
    6060
     61    Wasm::TableElementType type;
    6162    {
    6263        Identifier elementIdent = Identifier::fromString(&vm, "element");
     
    6566        String elementString = elementValue.toWTFString(exec);
    6667        RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
    67         if (elementString != "anyfunc")
    68             return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, "WebAssembly.Table expects its 'element' field to be the string 'anyfunc'"_s)));
     68        if (elementString == "anyfunc")
     69            type = Wasm::TableElementType::Funcref;
     70        else if (elementString == "anyref")
     71            type = Wasm::TableElementType::Anyref;
     72        else
     73            return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, "WebAssembly.Table expects its 'element' field to be the string 'anyfunc' or 'anyref'"_s)));
    6974    }
    7075
     
    9196    }
    9297
    93     RefPtr<Wasm::Table> wasmTable = Wasm::Table::tryCreate(initial, maximum);
     98    RefPtr<Wasm::Table> wasmTable = Wasm::Table::tryCreate(initial, maximum, type);
    9499    if (!wasmTable) {
    95100        return JSValue::encode(throwException(exec, throwScope,
  • trunk/Source/JavaScriptCore/wasm/js/WebAssemblyTablePrototype.cpp

    r245082 r246139  
    110110        return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, "WebAssembly.Table.prototype.get expects an integer less than the length of the table"_s)));
    111111
    112     if (JSObject* result = table->getFunction(index))
    113         return JSValue::encode(result);
    114     return JSValue::encode(jsNull());
     112    return JSValue::encode(table->get(index));
    115113}
    116114
     
    124122
    125123    JSValue value = exec->argument(1);
    126     WebAssemblyFunction* wasmFunction;
    127     WebAssemblyWrapperFunction* wasmWrapperFunction;
    128     if (!value.isNull() && !isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction))
    129         return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, "WebAssembly.Table.prototype.set expects the second argument to be null or an instance of WebAssembly.Function"_s)));
    130124
    131125    uint32_t index = toNonWrappingUint32(exec, exec->argument(0));
     
    135129        return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, "WebAssembly.Table.prototype.set expects an integer less than the length of the table"_s)));
    136130
    137     if (value.isNull())
    138         table->clearFunction(index);
    139     else {
    140         ASSERT(value.isObject() && isWebAssemblyHostFunction(vm, jsCast<JSObject*>(value), wasmFunction, wasmWrapperFunction));
    141         ASSERT(!!wasmFunction || !!wasmWrapperFunction);
    142         if (wasmFunction)
    143             table->setFunction(vm, index, wasmFunction);
    144         else
    145             table->setFunction(vm, index, wasmWrapperFunction);
    146     }
     131    if (table->table()->asFuncrefTable()) {
     132        WebAssemblyFunction* wasmFunction;
     133        WebAssemblyWrapperFunction* wasmWrapperFunction;
     134        if (!value.isNull() && !isWebAssemblyHostFunction(vm, value, wasmFunction, wasmWrapperFunction))
     135            return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, "WebAssembly.Table.prototype.set expects the second argument to be null or an instance of WebAssembly.Function"_s)));
     136
     137        if (value.isNull())
     138            table->clear(index);
     139        else {
     140            ASSERT(value.isObject() && isWebAssemblyHostFunction(vm, jsCast<JSObject*>(value), wasmFunction, wasmWrapperFunction));
     141            ASSERT(!!wasmFunction || !!wasmWrapperFunction);
     142            if (wasmFunction)
     143                table->set(index, wasmFunction);
     144            else
     145                table->set(index, wasmWrapperFunction);
     146        }
     147    } else
     148        table->set(index, value);
    147149   
    148150    return JSValue::encode(jsUndefined());
  • trunk/Source/JavaScriptCore/wasm/wasm.json

    r245496 r246139  
    1919    "value_type": ["i32", "i64", "f32", "f64", "anyref"],
    2020    "block_type": ["i32", "i64", "f32", "f64", "void", "anyref"],
    21     "elem_type": ["anyfunc"],
     21    "elem_type": ["anyfunc","anyref"],
    2222    "external_kind": {
    2323        "Function": { "type": "uint8", "value": 0 },
     
    6767        "get_global":          { "category": "special",    "value":  35, "return": ["any"],      "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                            "description": "read a global variable" },
    6868        "set_global":          { "category": "special",    "value":  36, "return": [],           "parameter": ["any"],                  "immediate": [{"name": "global_index",   "type": "varuint32"}],                                            "description": "write a global variable" },
     69        "table.get":           { "category": "special",    "value":  37, "return": ["anyref"],   "parameter": ["i32"],                  "immediate": [],                                                                                           "description": "get a table value" },
     70        "table.set":           { "category": "special",    "value":  38, "return": [],           "parameter": ["i32", "anyref"],        "immediate": [],                                                                                           "description": "set a table value" },
    6971        "call":                { "category": "call",       "value":  16, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                            "description": "call a function by its index" },
    7072        "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" },
Note: See TracChangeset for help on using the changeset viewer.