| Differences between
and this patch
- a/Source/JavaScriptCore/ChangeLog +76 lines
Lines 1-3 a/Source/JavaScriptCore/ChangeLog_sec1
1
2020-11-26  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
2
3
        [WASM-References] Add table.init
4
        https://bugs.webkit.org/show_bug.cgi?id=219297
5
6
        Reviewed by NOBODY (OOPS!).
7
        Spec is here: https://webassembly.github.io/reference-types/core/exec/instructions.html.
8
        Implemented in the same way as previously implemented table.* instructions.
9
10
        * bytecode/BytecodeList.rb:
11
        * llint/WebAssembly.asm:
12
        * wasm/WasmAirIRGenerator.cpp:
13
        (JSC::Wasm::AirIRGenerator::addTableInit):
14
        * wasm/WasmB3IRGenerator.cpp:
15
        (JSC::Wasm::B3IRGenerator::addTableInit):
16
        * wasm/WasmFormat.h:
17
        (JSC::Wasm::Element::Element):
18
        (JSC::Wasm::Element::length const):
19
        (JSC::Wasm::Element::passive const):
20
        * wasm/WasmFunctionParser.h:
21
        (JSC::Wasm::FunctionParser<Context>::parseExpression):
22
        * wasm/WasmInstance.cpp:
23
        (JSC::Wasm::Instance::Instance):
24
        (JSC::Wasm::Instance::elem const):
25
        (JSC::Wasm::Instance::initElementSegment):
26
        (JSC::Wasm::Instance::tableInit):
27
        * wasm/WasmInstance.h:
28
        (JSC::Wasm::Instance::isImportFunction const):
29
        * wasm/WasmLLIntGenerator.cpp:
30
        (JSC::Wasm::LLIntGenerator::addTableInit):
31
        * wasm/WasmModuleInformation.h:
32
        (JSC::Wasm::ModuleInformation::elementCount const):
33
        * wasm/WasmOperations.cpp:
34
        (JSC::Wasm::JSC_DEFINE_JIT_OPERATION):
35
        * wasm/WasmOperations.h:
36
        * wasm/WasmSectionParser.cpp:
37
        (JSC::Wasm::SectionParser::parseElement):
38
        * wasm/WasmSlowPaths.cpp:
39
        (JSC::LLInt::WASM_SLOW_PATH_DECL):
40
        * wasm/WasmSlowPaths.h:
41
        * wasm/js/WebAssemblyModuleRecord.cpp:
42
        (JSC::WebAssemblyModuleRecord::link):
43
        (JSC::WebAssemblyModuleRecord::evaluate):
44
        * wasm/wasm.json:
45
46
2020-11-19  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
47
48
        [WASM-References] Add support for active mods in element section
49
        https://bugs.webkit.org/show_bug.cgi?id=219192
50
51
        Reviewed by NOBODY (OOPS!).
52
        Adjust wasm parser to parse new form of element section.
53
        Don't need to worry about previous forms because they are compatible.
54
55
        Add support for vec(exp) in element section:
56
        https://webassembly.github.io/reference-types/core/binary/modules.html#element-section
57
        Just transformed (ref.func idx) -> idx and (ref.null func) -> null.
58
        For null values call table->clear to zero value.
59
60
        * wasm/WasmEntryPlan.cpp:
61
        (JSC::Wasm::EntryPlan::prepare):
62
        * wasm/WasmFormat.h:
63
        (JSC::Wasm::Element::Element):
64
        (JSC::Wasm::Element::active const):
65
        * wasm/WasmSectionParser.cpp:
66
        (JSC::Wasm::SectionParser::parseElement):
67
        (JSC::Wasm::SectionParser::validateElementTableIdx):
68
        (JSC::Wasm::SectionParser::parseI32InitExpr):
69
        (JSC::Wasm::SectionParser::parseElemKind):
70
        (JSC::Wasm::SectionParser::parseIndexCountForElemSection):
71
        (JSC::Wasm::SectionParser::parseFuncIdxFromRefExpForElemSection):
72
        (JSC::Wasm::SectionParser::parseFuncIdxForElemSection):
73
        * wasm/WasmSectionParser.h:
74
        * wasm/js/WebAssemblyModuleRecord.cpp:
75
        (JSC::WebAssemblyModuleRecord::evaluate):
76
1
2020-11-18  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
77
2020-11-18  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
2
78
3
        [WASM-References] Remove subtyping rule for externref and funcref
79
        [WASM-References] Remove subtyping rule for externref and funcref
- a/Source/JavaScriptCore/bytecode/BytecodeList.rb +9 lines
Lines 1587-1592 op :table_set, a/Source/JavaScriptCore/bytecode/BytecodeList.rb_sec1
1587
        tableIndex: unsigned,
1587
        tableIndex: unsigned,
1588
    }
1588
    }
1589
1589
1590
op :table_init,
1591
    args: {
1592
        dstOffset: VirtualRegister,
1593
        srcOffset: VirtualRegister,
1594
        length: VirtualRegister,
1595
        elementIndex: unsigned,
1596
        tableIndex: unsigned,
1597
    }
1598
1590
op :table_size,
1599
op :table_size,
1591
    args: {
1600
    args: {
1592
        dst: VirtualRegister,
1601
        dst: VirtualRegister,
- a/Source/JavaScriptCore/llint/WebAssembly.asm +1 lines
Lines 561-566 noWide(wasm_wide32) a/Source/JavaScriptCore/llint/WebAssembly.asm_sec1
561
slowWasmOp(ref_func)
561
slowWasmOp(ref_func)
562
slowWasmOp(table_get)
562
slowWasmOp(table_get)
563
slowWasmOp(table_set)
563
slowWasmOp(table_set)
564
slowWasmOp(table_init)
564
slowWasmOp(table_size)
565
slowWasmOp(table_size)
565
slowWasmOp(table_fill)
566
slowWasmOp(table_fill)
566
slowWasmOp(table_grow)
567
slowWasmOp(table_grow)
- a/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp +28 lines
Lines 259-264 public: a/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp_sec1
259
    // Tables
259
    // Tables
260
    PartialResult WARN_UNUSED_RETURN addTableGet(unsigned, ExpressionType index, ExpressionType& result);
260
    PartialResult WARN_UNUSED_RETURN addTableGet(unsigned, ExpressionType index, ExpressionType& result);
261
    PartialResult WARN_UNUSED_RETURN addTableSet(unsigned, ExpressionType index, ExpressionType value);
261
    PartialResult WARN_UNUSED_RETURN addTableSet(unsigned, ExpressionType index, ExpressionType value);
262
    PartialResult WARN_UNUSED_RETURN addTableInit(unsigned, unsigned, ExpressionType dstOffset, ExpressionType srcOffset, ExpressionType length);
262
    PartialResult WARN_UNUSED_RETURN addTableSize(unsigned, ExpressionType& result);
263
    PartialResult WARN_UNUSED_RETURN addTableSize(unsigned, ExpressionType& result);
263
    PartialResult WARN_UNUSED_RETURN addTableGrow(unsigned, ExpressionType fill, ExpressionType delta, ExpressionType& result);
264
    PartialResult WARN_UNUSED_RETURN addTableGrow(unsigned, ExpressionType fill, ExpressionType delta, ExpressionType& result);
264
    PartialResult WARN_UNUSED_RETURN addTableFill(unsigned, ExpressionType offset, ExpressionType fill, ExpressionType count);
265
    PartialResult WARN_UNUSED_RETURN addTableFill(unsigned, ExpressionType offset, ExpressionType fill, ExpressionType count);
Lines 1089-1094 auto AirIRGenerator::addTableSet(unsigned tableIndex, ExpressionType index, Expr a/Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp_sec2
1089
    return { };
1090
    return { };
1090
}
1091
}
1091
1092
1093
auto AirIRGenerator::addTableInit(unsigned elementIndex, unsigned tableIndex, ExpressionType dstOffset, ExpressionType srcOffset, ExpressionType length) -> PartialResult
1094
{
1095
    ASSERT(dstOffset.tmp());
1096
    ASSERT(dstOffset.type() == Type::I32);
1097
1098
    ASSERT(srcOffset.tmp());
1099
    ASSERT(srcOffset.type() == Type::I32);
1100
1101
    ASSERT(length.tmp());
1102
    ASSERT(length.type() == Type::I32);
1103
1104
    auto result = tmpForType(Type::I32);
1105
    emitCCall(
1106
        &operationWasmTableInit, result, instanceValue(),
1107
        addConstant(Type::I32, elementIndex),
1108
        addConstant(Type::I32, tableIndex),
1109
        dstOffset, srcOffset, length);
1110
1111
    emitCheck([&] {
1112
        return Inst(BranchTest32, nullptr, Arg::resCond(MacroAssembler::Zero), result, result);
1113
    }, [=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
1114
        this->emitThrowException(jit, ExceptionType::OutOfBoundsTableAccess);
1115
    });
1116
1117
    return { };
1118
}
1119
1092
auto AirIRGenerator::addTableSize(unsigned tableIndex, ExpressionType& result) -> PartialResult
1120
auto AirIRGenerator::addTableSize(unsigned tableIndex, ExpressionType& result) -> PartialResult
1093
{
1121
{
1094
    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
1122
    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
- a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp +23 lines
Lines 215-220 public: a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp_sec1
215
    // Tables
215
    // Tables
216
    PartialResult WARN_UNUSED_RETURN addTableGet(unsigned, ExpressionType index, ExpressionType& result);
216
    PartialResult WARN_UNUSED_RETURN addTableGet(unsigned, ExpressionType index, ExpressionType& result);
217
    PartialResult WARN_UNUSED_RETURN addTableSet(unsigned, ExpressionType index, ExpressionType value);
217
    PartialResult WARN_UNUSED_RETURN addTableSet(unsigned, ExpressionType index, ExpressionType value);
218
    PartialResult WARN_UNUSED_RETURN addTableInit(unsigned, unsigned, ExpressionType dstOffset, ExpressionType srcOffset, ExpressionType length);
218
    PartialResult WARN_UNUSED_RETURN addTableSize(unsigned, ExpressionType& result);
219
    PartialResult WARN_UNUSED_RETURN addTableSize(unsigned, ExpressionType& result);
219
    PartialResult WARN_UNUSED_RETURN addTableGrow(unsigned, ExpressionType fill, ExpressionType delta, ExpressionType& result);
220
    PartialResult WARN_UNUSED_RETURN addTableGrow(unsigned, ExpressionType fill, ExpressionType delta, ExpressionType& result);
220
    PartialResult WARN_UNUSED_RETURN addTableFill(unsigned, ExpressionType offset, ExpressionType fill, ExpressionType count);
221
    PartialResult WARN_UNUSED_RETURN addTableFill(unsigned, ExpressionType offset, ExpressionType fill, ExpressionType count);
Lines 725-730 auto B3IRGenerator::addRefFunc(uint32_t index, ExpressionType& result) -> Partia a/Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp_sec2
725
    return { };
726
    return { };
726
}
727
}
727
728
729
auto B3IRGenerator::addTableInit(unsigned elementIndex, unsigned tableIndex, ExpressionType dstOffset, ExpressionType srcOffset, ExpressionType length) -> PartialResult
730
{
731
    auto result = m_currentBlock->appendNew<CCallValue>(
732
        m_proc, toB3Type(I32), origin(),
733
        m_currentBlock->appendNew<ConstPtrValue>(m_proc, origin(), tagCFunction<OperationPtrTag>(operationWasmTableInit)),
734
        instanceValue(),
735
        m_currentBlock->appendNew<Const32Value>(m_proc, origin(), elementIndex),
736
        m_currentBlock->appendNew<Const32Value>(m_proc, origin(), tableIndex),
737
        dstOffset, srcOffset, length);
738
739
    {
740
        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
741
            m_currentBlock->appendNew<Value>(m_proc, Equal, origin(), result, m_currentBlock->appendNew<Const32Value>(m_proc, origin(), 0)));
742
743
        check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
744
            this->emitExceptionCheck(jit, ExceptionType::OutOfBoundsTableAccess);
745
        });
746
    }
747
748
    return { };
749
}
750
728
auto B3IRGenerator::addTableSize(unsigned tableIndex, ExpressionType& result) -> PartialResult
751
auto B3IRGenerator::addTableSize(unsigned tableIndex, ExpressionType& result) -> PartialResult
729
{
752
{
730
    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
753
    // FIXME: Emit this inline <https://bugs.webkit.org/show_bug.cgi?id=198506>.
- a/Source/JavaScriptCore/wasm/WasmEntryPlan.cpp -3 / +3 lines
Lines 143-151 void EntryPlan::prepare() a/Source/JavaScriptCore/wasm/WasmEntryPlan.cpp_sec1
143
    }
143
    }
144
144
145
    for (const auto& element : m_moduleInformation->elements) {
145
    for (const auto& element : m_moduleInformation->elements) {
146
        for (const uint32_t elementIndex : element.functionIndices) {
146
        for (const Optional<uint32_t>& elementIndex : element.functionIndices) {
147
            if (elementIndex >= importFunctionCount)
147
            if (elementIndex && *elementIndex >= importFunctionCount)
148
                m_exportedFunctionIndices.add(elementIndex - importFunctionCount);
148
                m_exportedFunctionIndices.add(*elementIndex - importFunctionCount);
149
        }
149
        }
150
    }
150
    }
151
151
- a/Source/JavaScriptCore/wasm/WasmFormat.h -6 / +27 lines
Lines 226-239 struct Segment { a/Source/JavaScriptCore/wasm/WasmFormat.h_sec1
226
226
227
struct Element {
227
struct Element {
228
    WTF_MAKE_STRUCT_FAST_ALLOCATED;
228
    WTF_MAKE_STRUCT_FAST_ALLOCATED;
229
    Element(uint32_t tableIndex, I32InitExpr offset)
229
    enum class Kind {
230
        : tableIndex(tableIndex)
230
        Active,
231
        , offset(offset)
231
        Passive,
232
        Declared,
233
    };
234
235
    Element(Element::Kind kind, TableElementType elemType, Optional<uint32_t> tableIndex, Optional<I32InitExpr> initExpr)
236
        : kind(kind)
237
        , elemType(elemType)
238
        , tableIndexIfActive(tableIndex)
239
        , offsetIfActive(initExpr)
232
    { }
240
    { }
233
241
234
    uint32_t tableIndex;
242
    Element(Element::Kind kind, TableElementType elemType)
235
    I32InitExpr offset;
243
        : Element(kind, elemType, Optional<uint32_t>(), Optional<I32InitExpr>())
236
    Vector<uint32_t> functionIndices;
244
    { }
245
246
    uint32_t length() const { return functionIndices.size(); }
247
248
    bool active() const { return kind == Kind::Active; }
249
    bool passive() const { return kind == Kind::Passive; }
250
251
    Kind kind;
252
    TableElementType elemType;
253
    Optional<uint32_t> tableIndexIfActive;
254
    Optional<I32InitExpr> offsetIfActive;
255
256
    // If there is no value then item represents ref.null.
257
    Vector<Optional<uint32_t>> functionIndices;
237
};
258
};
238
259
239
class TableInformation {
260
class TableInformation {
- a/Source/JavaScriptCore/wasm/WasmFunctionParser.h -3 / +35 lines
Lines 446-463 FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_CASE) a/Source/JavaScriptCore/wasm/WasmFunctionParser.h_sec1
446
        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
446
        WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
447
        uint8_t extOp;
447
        uint8_t extOp;
448
        WASM_PARSER_FAIL_IF(!parseUInt8(extOp), "can't parse table extended opcode");
448
        WASM_PARSER_FAIL_IF(!parseUInt8(extOp), "can't parse table extended opcode");
449
        unsigned tableIndex;
450
        WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't parse table index");
451
        WASM_VALIDATOR_FAIL_IF(tableIndex >= m_info.tableCount(), "table index ", tableIndex, " is invalid, limit is ", m_info.tableCount());
452
449
453
        switch (static_cast<ExtTableOpType>(extOp)) {
450
        switch (static_cast<ExtTableOpType>(extOp)) {
451
        case ExtTableOpType::TableInit: {
452
            unsigned elementIndex;
453
            WASM_PARSER_FAIL_IF(!parseVarUInt32(elementIndex), "can't parse element index");
454
            WASM_VALIDATOR_FAIL_IF(elementIndex >= m_info.elementCount(), "element index ", elementIndex, " is invalid, limit is ", m_info.elementCount());
455
456
            unsigned tableIndex;
457
            WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't parse element index");
458
            WASM_VALIDATOR_FAIL_IF(tableIndex >= m_info.tableCount(), "table index ", tableIndex, " is invalid, limit is ", m_info.tableCount());
459
460
            TypedExpression dstOffset;
461
            TypedExpression srcOffset;
462
            TypedExpression lenght;
463
            WASM_TRY_POP_EXPRESSION_STACK_INTO(lenght, "table.init");
464
            WASM_TRY_POP_EXPRESSION_STACK_INTO(srcOffset, "table.init");
465
            WASM_TRY_POP_EXPRESSION_STACK_INTO(dstOffset, "table.init");
466
467
            WASM_VALIDATOR_FAIL_IF(I32 != dstOffset.type(), "table.init dst_offset to type ", dstOffset.type(), " expected ", I32);
468
            WASM_VALIDATOR_FAIL_IF(I32 != srcOffset.type(), "table.init src_offset to type ", srcOffset.type(), " expected ", I32);
469
            WASM_VALIDATOR_FAIL_IF(I32 != lenght.type(), "table.init length to type ", lenght.type(), " expected ", I32);
470
471
            WASM_TRY_ADD_TO_CONTEXT(addTableInit(elementIndex, tableIndex, dstOffset, srcOffset, lenght));
472
            break;
473
        }
454
        case ExtTableOpType::TableSize: {
474
        case ExtTableOpType::TableSize: {
475
            unsigned tableIndex;
476
            WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't parse table index");
477
            WASM_VALIDATOR_FAIL_IF(tableIndex >= m_info.tableCount(), "table index ", tableIndex, " is invalid, limit is ", m_info.tableCount());
478
455
            ExpressionType result;
479
            ExpressionType result;
456
            WASM_TRY_ADD_TO_CONTEXT(addTableSize(tableIndex, result));
480
            WASM_TRY_ADD_TO_CONTEXT(addTableSize(tableIndex, result));
457
            m_expressionStack.constructAndAppend(I32, result);
481
            m_expressionStack.constructAndAppend(I32, result);
458
            break;
482
            break;
459
        }
483
        }
460
        case ExtTableOpType::TableGrow: {
484
        case ExtTableOpType::TableGrow: {
485
            unsigned tableIndex;
486
            WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't parse table index");
487
            WASM_VALIDATOR_FAIL_IF(tableIndex >= m_info.tableCount(), "table index ", tableIndex, " is invalid, limit is ", m_info.tableCount());
488
461
            TypedExpression fill;
489
            TypedExpression fill;
462
            TypedExpression delta;
490
            TypedExpression delta;
463
            WASM_TRY_POP_EXPRESSION_STACK_INTO(delta, "table.grow");
491
            WASM_TRY_POP_EXPRESSION_STACK_INTO(delta, "table.grow");
Lines 472-477 FOR_EACH_WASM_MEMORY_STORE_OP(CREATE_CASE) a/Source/JavaScriptCore/wasm/WasmFunctionParser.h_sec2
472
            break;
500
            break;
473
        }
501
        }
474
        case ExtTableOpType::TableFill: {
502
        case ExtTableOpType::TableFill: {
503
            unsigned tableIndex;
504
            WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't parse table index");
505
            WASM_VALIDATOR_FAIL_IF(tableIndex >= m_info.tableCount(), "table index ", tableIndex, " is invalid, limit is ", m_info.tableCount());
506
475
            TypedExpression offset, fill, count;
507
            TypedExpression offset, fill, count;
476
            WASM_TRY_POP_EXPRESSION_STACK_INTO(count, "table.fill");
508
            WASM_TRY_POP_EXPRESSION_STACK_INTO(count, "table.fill");
477
            WASM_TRY_POP_EXPRESSION_STACK_INTO(fill, "table.fill");
509
            WASM_TRY_POP_EXPRESSION_STACK_INTO(fill, "table.fill");
- a/Source/JavaScriptCore/wasm/WasmInstance.cpp +96 lines
Lines 29-34 a/Source/JavaScriptCore/wasm/WasmInstance.cpp_sec1
29
#if ENABLE(WEBASSEMBLY)
29
#if ENABLE(WEBASSEMBLY)
30
30
31
#include "JSCJSValueInlines.h"
31
#include "JSCJSValueInlines.h"
32
#include "JSWebAssemblyHelpers.h"
32
#include "JSWebAssemblyInstance.h"
33
#include "JSWebAssemblyInstance.h"
33
#include "Register.h"
34
#include "Register.h"
34
#include "WasmModuleInformation.h"
35
#include "WasmModuleInformation.h"
Lines 68-73 Instance::Instance(Context* context, Ref<Module>&& module, EntryFrame** pointerT a/Source/JavaScriptCore/wasm/WasmInstance.cpp_sec2
68
        }
69
        }
69
    }
70
    }
70
    memset(bitwise_cast<char*>(this) + offsetOfTablePtr(m_numImportFunctions, 0), 0, m_module->moduleInformation().tableCount() * sizeof(Table*));
71
    memset(bitwise_cast<char*>(this) + offsetOfTablePtr(m_numImportFunctions, 0), 0, m_module->moduleInformation().tableCount() * sizeof(Table*));
72
    m_passiveElements.resize(m_module->moduleInformation().elementCount());
73
    for (unsigned elementIdx = 0; elementIdx < m_passiveElements.size(); ++elementIdx) {
74
        const auto& element = m_module->moduleInformation().elements[elementIdx];
75
        if (element.passive())
76
            m_passiveElements[elementIdx] = element;
77
    }
71
}
78
}
72
79
73
Ref<Instance> Instance::create(Context* context, Ref<Module>&& module, EntryFrame** pointerToTopEntryFrame, void** pointerToActualStackLimit, StoreTopCallFrameCallback&& storeTopCallFrame)
80
Ref<Instance> Instance::create(Context* context, Ref<Module>&& module, EntryFrame** pointerToTopEntryFrame, void** pointerToActualStackLimit, StoreTopCallFrameCallback&& storeTopCallFrame)
Lines 120-125 Table* Instance::table(unsigned i) a/Source/JavaScriptCore/wasm/WasmInstance.cpp_sec3
120
    return *bitwise_cast<Table**>(bitwise_cast<char*>(this) + offsetOfTablePtr(m_numImportFunctions, i));
127
    return *bitwise_cast<Table**>(bitwise_cast<char*>(this) + offsetOfTablePtr(m_numImportFunctions, i));
121
}
128
}
122
129
130
const Element* Instance::elem(unsigned i) const
131
{
132
    RELEASE_ASSERT(i < m_passiveElements.size());
133
134
    if (m_passiveElements[i]) {
135
        const Element& elem = *m_passiveElements[i];
136
        return &elem;
137
    }
138
    return nullptr;
139
}
140
141
void Instance::initElementSegment(uint32_t tableIndex, const Element& segment, uint32_t dstOffset, uint32_t srcOffset, uint32_t length)
142
{
143
    RELEASE_ASSERT(length <= segment.functionIndices.size());
144
145
    for (uint32_t idx = 0; idx < length; ++idx) {
146
        const auto srcIndex = srcOffset + idx;
147
        const auto dstIndex = dstOffset + idx;
148
        JSWebAssemblyInstance* jsInstance = owner<JSWebAssemblyInstance>();
149
        JSWebAssemblyTable* jsTable = jsInstance->table(tableIndex);
150
151
        if (!segment.functionIndices[srcIndex].hasValue()) {
152
            jsTable->clear(dstIndex);
153
            continue;
154
        }
155
156
        // FIXME: This essentially means we're exporting an import.
157
        // We need a story here. We need to create a WebAssemblyFunction
158
        // for the import.
159
        // https://bugs.webkit.org/show_bug.cgi?id=165510
160
        JSGlobalObject* globalObject = jsInstance->globalObject();
161
        VM& vm = globalObject->vm();
162
        uint32_t functionIndex = *segment.functionIndices[srcIndex];
163
        SignatureIndex signatureIndex = m_module->signatureIndexFromFunctionIndexSpace(functionIndex);
164
        if (isImportFunction(functionIndex)) {
165
            JSObject* functionImport = importFunction<WriteBarrier<JSObject>>(functionIndex)->get();
166
            if (isWebAssemblyHostFunction(vm, functionImport)) {
167
                WebAssemblyFunction* wasmFunction = jsDynamicCast<WebAssemblyFunction*>(vm, functionImport);
168
                // If we ever import a WebAssemblyWrapperFunction, we set the import as the unwrapped value.
169
                // Because a WebAssemblyWrapperFunction can never wrap another WebAssemblyWrapperFunction,
170
                // the only type this could be is WebAssemblyFunction.
171
                RELEASE_ASSERT(wasmFunction);
172
                jsTable->set(dstIndex, wasmFunction);
173
                continue;
174
            }
175
            auto* wrapperFunction = WebAssemblyWrapperFunction::create(
176
                vm,
177
                globalObject,
178
                globalObject->webAssemblyWrapperFunctionStructure(),
179
                functionImport,
180
                functionIndex,
181
                jsInstance,
182
                signatureIndex);
183
            jsTable->set(dstIndex, wrapperFunction);
184
            continue;
185
        }
186
187
        Callee& embedderEntrypointCallee = codeBlock()->embedderEntrypointCalleeFromFunctionIndexSpace(functionIndex);
188
        WasmToWasmImportableFunction::LoadLocation entrypointLoadLocation = codeBlock()->entrypointLoadLocationFromFunctionIndexSpace(functionIndex);
189
        const Signature& signature = SignatureInformation::get(signatureIndex);
190
        // FIXME: Say we export local function "foo" at function index 0.
191
        // What if we also set it to the table an Element w/ index 0.
192
        // Does (new Instance(...)).exports.foo === table.get(0)?
193
        // https://bugs.webkit.org/show_bug.cgi?id=165825
194
        WebAssemblyFunction* function = WebAssemblyFunction::create(
195
            vm,
196
            globalObject,
197
            globalObject->webAssemblyFunctionStructure(),
198
            signature.argumentCount(),
199
            String(),
200
            jsInstance,
201
            embedderEntrypointCallee,
202
            entrypointLoadLocation,
203
            signatureIndex);
204
        jsTable->set(dstIndex, function);
205
    }
206
}
207
208
void Instance::tableInit(uint32_t dstOffset, uint32_t srcOffset, uint32_t len, uint32_t elementIndex, uint32_t tableIndex)
209
{
210
    RELEASE_ASSERT(elementIndex < m_module->moduleInformation().elementCount());
211
    RELEASE_ASSERT(tableIndex < m_module->moduleInformation().tableCount());
212
213
    const auto& elementSegment = m_passiveElements[elementIndex];
214
    RELEASE_ASSERT(elementSegment);
215
    RELEASE_ASSERT(elementSegment->passive());
216
    initElementSegment(tableIndex, *elementSegment, dstOffset, srcOffset, len);
217
}
218
123
void Instance::setTable(unsigned i, Ref<Table>&& table)
219
void Instance::setTable(unsigned i, Ref<Table>&& table)
124
{
220
{
125
    RELEASE_ASSERT(i < m_module->moduleInformation().tableCount());
221
    RELEASE_ASSERT(i < m_module->moduleInformation().tableCount());
- a/Source/JavaScriptCore/wasm/WasmInstance.h +11 lines
Lines 76-81 public: a/Source/JavaScriptCore/wasm/WasmInstance.h_sec1
76
    Memory* memory() { return m_memory.get(); }
76
    Memory* memory() { return m_memory.get(); }
77
    Table* table(unsigned);
77
    Table* table(unsigned);
78
    void setTable(unsigned, Ref<Table>&&);
78
    void setTable(unsigned, Ref<Table>&&);
79
    const Element* elem(unsigned) const;
80
81
    void initElementSegment(uint32_t tableIndex, const Element& segment, uint32_t dstOffset, uint32_t srcOffset, uint32_t length);
82
83
    bool isImportFunction(uint32_t functionIndex) const
84
    {
85
        return functionIndex < m_codeBlock->functionImportCount();
86
    }
87
88
    void tableInit(uint32_t dstOffset, uint32_t srcOffset, uint32_t len, uint32_t elementIndex, uint32_t tableIndex);
79
89
80
    void* cachedMemory() const { return m_cachedMemory.getMayBeNull(cachedBoundsCheckingSize()); }
90
    void* cachedMemory() const { return m_cachedMemory.getMayBeNull(cachedBoundsCheckingSize()); }
81
    size_t cachedBoundsCheckingSize() const { return m_cachedBoundsCheckingSize; }
91
    size_t cachedBoundsCheckingSize() const { return m_cachedBoundsCheckingSize; }
Lines 216-221 private: a/Source/JavaScriptCore/wasm/WasmInstance.h_sec2
216
    StoreTopCallFrameCallback m_storeTopCallFrame;
226
    StoreTopCallFrameCallback m_storeTopCallFrame;
217
    unsigned m_numImportFunctions { 0 };
227
    unsigned m_numImportFunctions { 0 };
218
    HashMap<uint32_t, Ref<Global>, IntHash<uint32_t>, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> m_linkedGlobals;
228
    HashMap<uint32_t, Ref<Global>, IntHash<uint32_t>, WTF::UnsignedWithZeroKeyHashTraits<uint32_t>> m_linkedGlobals;
229
    Vector<Optional<Element>> m_passiveElements;
219
};
230
};
220
231
221
} } // namespace JSC::Wasm
232
} } // namespace JSC::Wasm
- a/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp +8 lines
Lines 191-196 public: a/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp_sec1
191
    // Tables
191
    // Tables
192
    PartialResult WARN_UNUSED_RETURN addTableGet(unsigned, ExpressionType index, ExpressionType& result);
192
    PartialResult WARN_UNUSED_RETURN addTableGet(unsigned, ExpressionType index, ExpressionType& result);
193
    PartialResult WARN_UNUSED_RETURN addTableSet(unsigned, ExpressionType index, ExpressionType value);
193
    PartialResult WARN_UNUSED_RETURN addTableSet(unsigned, ExpressionType index, ExpressionType value);
194
    PartialResult WARN_UNUSED_RETURN addTableInit(unsigned, unsigned, ExpressionType dstOffset, ExpressionType srcOffset, ExpressionType length);
194
    PartialResult WARN_UNUSED_RETURN addTableSize(unsigned, ExpressionType& result);
195
    PartialResult WARN_UNUSED_RETURN addTableSize(unsigned, ExpressionType& result);
195
    PartialResult WARN_UNUSED_RETURN addTableGrow(unsigned, ExpressionType fill, ExpressionType delta, ExpressionType& result);
196
    PartialResult WARN_UNUSED_RETURN addTableGrow(unsigned, ExpressionType fill, ExpressionType delta, ExpressionType& result);
196
    PartialResult WARN_UNUSED_RETURN addTableFill(unsigned, ExpressionType offset, ExpressionType fill, ExpressionType count);
197
    PartialResult WARN_UNUSED_RETURN addTableFill(unsigned, ExpressionType offset, ExpressionType fill, ExpressionType count);
Lines 1109-1114 auto LLIntGenerator::addTableSet(unsigned tableIndex, ExpressionType index, Expr a/Source/JavaScriptCore/wasm/WasmLLIntGenerator.cpp_sec2
1109
    return { };
1110
    return { };
1110
}
1111
}
1111
1112
1113
auto LLIntGenerator::addTableInit(unsigned elementIndex, unsigned tableIndex, ExpressionType dstOffset, ExpressionType srcOffset, ExpressionType length) -> PartialResult
1114
{
1115
    WasmTableInit::emit(this, dstOffset, srcOffset, length, elementIndex, tableIndex);
1116
1117
    return { };
1118
}
1119
1112
auto LLIntGenerator::addTableSize(unsigned tableIndex, ExpressionType& result) -> PartialResult
1120
auto LLIntGenerator::addTableSize(unsigned tableIndex, ExpressionType& result) -> PartialResult
1113
{
1121
{
1114
    result = push();
1122
    result = push();
- a/Source/JavaScriptCore/wasm/WasmModuleInformation.h +1 lines
Lines 66-71 struct ModuleInformation : public ThreadSafeRefCounted<ModuleInformation> { a/Source/JavaScriptCore/wasm/WasmModuleInformation.h_sec1
66
    // If we need to remove this limitation, we would have MemoryInformation and TableInformation in the Vectors.
66
    // If we need to remove this limitation, we would have MemoryInformation and TableInformation in the Vectors.
67
    uint32_t memoryCount() const { return memory ? 1 : 0; }
67
    uint32_t memoryCount() const { return memory ? 1 : 0; }
68
    uint32_t tableCount() const { return tables.size(); }
68
    uint32_t tableCount() const { return tables.size(); }
69
    uint32_t elementCount() const { return elements.size(); }
69
70
70
    const BitVector& referencedFunctions() const { return m_referencedFunctions; }
71
    const BitVector& referencedFunctions() const { return m_referencedFunctions; }
71
    void addReferencedFunction(unsigned index) const { m_referencedFunctions.set(index); }
72
    void addReferencedFunction(unsigned index) const { m_referencedFunctions.set(index); }
- a/Source/JavaScriptCore/wasm/WasmOperations.cpp +20 lines
Lines 686-691 JSC_DEFINE_JIT_OPERATION(operationSetWasmTableElement, bool, (Instance* instance a/Source/JavaScriptCore/wasm/WasmOperations.cpp_sec1
686
    return setWasmTableElement(instance, tableIndex, signedIndex, encValue);
686
    return setWasmTableElement(instance, tableIndex, signedIndex, encValue);
687
}
687
}
688
688
689
JSC_DEFINE_JIT_OPERATION(operationWasmTableInit, bool, (Instance* instance, unsigned elementIndex, unsigned tableIndex, int32_t dstOffset, int32_t srcOffset, int32_t length))
690
{
691
    ASSERT(elementIndex < instance->module().moduleInformation().elementCount());
692
    ASSERT(tableIndex < instance->module().moduleInformation().tableCount());
693
694
    if ((srcOffset < 0) || (dstOffset < 0) || (length < 0))
695
        return false;
696
697
    const uint32_t lastSrcElementIdx = srcOffset + length;
698
    if (lastSrcElementIdx > instance->elem(elementIndex)->length())
699
        return false;
700
701
    const uint32_t lastDstElementIdx = dstOffset + length;
702
    if (lastDstElementIdx > instance->table(tableIndex)->length())
703
        return false;
704
705
    instance->tableInit(dstOffset, srcOffset, length, elementIndex, tableIndex);
706
    return true;
707
}
708
689
JSC_DEFINE_JIT_OPERATION(operationWasmTableGrow, int32_t, (Instance* instance, unsigned tableIndex, EncodedJSValue fill, int32_t delta))
709
JSC_DEFINE_JIT_OPERATION(operationWasmTableGrow, int32_t, (Instance* instance, unsigned tableIndex, EncodedJSValue fill, int32_t delta))
690
{
710
{
691
    ASSERT(tableIndex < instance->module().moduleInformation().tableCount());
711
    ASSERT(tableIndex < instance->module().moduleInformation().tableCount());
- a/Source/JavaScriptCore/wasm/WasmOperations.h +1 lines
Lines 65-70 JSC_DECLARE_JIT_OPERATION(operationGrowMemory, int32_t, (void*, Instance*, int32 a/Source/JavaScriptCore/wasm/WasmOperations.h_sec1
65
JSC_DECLARE_JIT_OPERATION(operationGetWasmTableElement, EncodedJSValue, (Instance*, unsigned, int32_t));
65
JSC_DECLARE_JIT_OPERATION(operationGetWasmTableElement, EncodedJSValue, (Instance*, unsigned, int32_t));
66
JSC_DECLARE_JIT_OPERATION(operationSetWasmTableElement, bool, (Instance*, unsigned, int32_t, EncodedJSValue encValue));
66
JSC_DECLARE_JIT_OPERATION(operationSetWasmTableElement, bool, (Instance*, unsigned, int32_t, EncodedJSValue encValue));
67
JSC_DECLARE_JIT_OPERATION(operationWasmRefFunc, EncodedJSValue, (Instance*, uint32_t));
67
JSC_DECLARE_JIT_OPERATION(operationWasmRefFunc, EncodedJSValue, (Instance*, uint32_t));
68
JSC_DECLARE_JIT_OPERATION(operationWasmTableInit, bool, (Instance*, unsigned elementIndex, unsigned tableIndex, int32_t dstOffset, int32_t srcOffset, int32_t length));
68
JSC_DECLARE_JIT_OPERATION(operationWasmTableGrow, int32_t, (Instance*, unsigned, EncodedJSValue fill, int32_t delta));
69
JSC_DECLARE_JIT_OPERATION(operationWasmTableGrow, int32_t, (Instance*, unsigned, EncodedJSValue fill, int32_t delta));
69
JSC_DECLARE_JIT_OPERATION(operationWasmTableFill, bool, (Instance*, unsigned, int32_t offset, EncodedJSValue fill, int32_t count));
70
JSC_DECLARE_JIT_OPERATION(operationWasmTableFill, bool, (Instance*, unsigned, int32_t offset, EncodedJSValue fill, int32_t count));
70
JSC_DECLARE_JIT_OPERATION(operationGetWasmTableSize, int32_t, (Instance*, unsigned));
71
JSC_DECLARE_JIT_OPERATION(operationGetWasmTableSize, int32_t, (Instance*, unsigned));
- a/Source/JavaScriptCore/wasm/WasmSectionParser.cpp -26 / +227 lines
Lines 378-418 auto SectionParser::parseElement() -> PartialResult a/Source/JavaScriptCore/wasm/WasmSectionParser.cpp_sec1
378
    WASM_PARSER_FAIL_IF(elementCount > maxTableEntries, "Element section's count is too big ", elementCount, " maximum ", maxTableEntries);
378
    WASM_PARSER_FAIL_IF(elementCount > maxTableEntries, "Element section's count is too big ", elementCount, " maximum ", maxTableEntries);
379
    WASM_PARSER_FAIL_IF(!m_info->elements.tryReserveCapacity(elementCount), "can't allocate memory for ", elementCount, " Elements");
379
    WASM_PARSER_FAIL_IF(!m_info->elements.tryReserveCapacity(elementCount), "can't allocate memory for ", elementCount, " Elements");
380
    for (unsigned elementNum = 0; elementNum < elementCount; ++elementNum) {
380
    for (unsigned elementNum = 0; elementNum < elementCount; ++elementNum) {
381
        uint32_t tableIndex;
381
        uint8_t elementFlags;
382
        uint64_t initExprBits;
382
        WASM_PARSER_FAIL_IF(!parseUInt8(elementFlags), "can't get ", elementNum, "th Element reserved byte, which should be element flags");
383
        uint8_t initOpcode;
383
384
        uint32_t indexCount;
384
        switch (elementFlags) {
385
        case 0x00: {
386
            const uint32_t tableIndex = 0;
387
            WASM_FAIL_IF_HELPER_FAILS(validateElementTableIdx(tableIndex));
388
389
            Optional<I32InitExpr> initExpr;
390
            WASM_FAIL_IF_HELPER_FAILS(parseI32InitExpr(initExpr));
391
392
            uint32_t indexCount;
393
            WASM_FAIL_IF_HELPER_FAILS(parseIndexCountForElemSection(indexCount, elementNum));
394
            ASSERT(!!m_info->tables[tableIndex]);
395
396
            Element element(Element::Kind::Active, TableElementType::Funcref, tableIndex, WTFMove(initExpr));
397
            WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
398
399
            for (uint32_t index = 0; index < indexCount; ++index) {
400
                Optional<uint32_t> funcIdx;
401
                WASM_FAIL_IF_HELPER_FAILS(parseFuncIdxForElemSection(funcIdx, elementNum, index));
402
                element.functionIndices.uncheckedAppend(WTFMove(funcIdx));
403
            }
404
405
            m_info->elements.uncheckedAppend(WTFMove(element));
406
            break;
407
        }
408
        case 0x01: {
409
            WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
410
            uint8_t elemKind;
411
            WASM_FAIL_IF_HELPER_FAILS(parseElemKind(elemKind));
412
413
            uint32_t indexCount;
414
            WASM_FAIL_IF_HELPER_FAILS(parseIndexCountForElemSection(indexCount, elementNum));
385
415
386
        uint8_t magic;
416
            Element element(Element::Kind::Passive, TableElementType::Funcref);
387
        WASM_PARSER_FAIL_IF(!parseUInt8(magic) || (magic && magic != 2), "can't get ", elementNum, "th Element reserved byte, which should be either 0x00 or 0x02 followed by a table index");
417
            WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
388
418
389
        if (magic == 2)
419
            for (uint32_t index = 0; index < indexCount; ++index) {
420
                Optional<uint32_t> funcIdx;
421
                WASM_FAIL_IF_HELPER_FAILS(parseFuncIdxForElemSection(funcIdx, elementNum, index));
422
                element.functionIndices.uncheckedAppend(WTFMove(funcIdx));
423
            }
424
425
            m_info->elements.uncheckedAppend(WTFMove(element));
426
            break;
427
        }
428
        case 0x02: {
429
            uint32_t tableIndex;
390
            WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't get ", elementNum, "th Element table index");
430
            WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't get ", elementNum, "th Element table index");
391
        else
431
            WASM_FAIL_IF_HELPER_FAILS(validateElementTableIdx(tableIndex));
392
            tableIndex = 0;
432
393
        
433
            Optional<I32InitExpr> initExpr;
394
        WASM_PARSER_FAIL_IF(tableIndex >= m_info->tableCount(), "Element section for Table ", tableIndex, " exceeds available Table ", m_info->tableCount());
434
            WASM_FAIL_IF_HELPER_FAILS(parseI32InitExpr(initExpr));
395
        WASM_PARSER_FAIL_IF(m_info->tables[tableIndex].type() != TableElementType::Funcref, "Table ", tableIndex, " must have type 'funcref' to have an element section");
435
396
        Type initExprType;
436
            uint8_t elemKind;
397
        WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
437
            WASM_FAIL_IF_HELPER_FAILS(parseElemKind(elemKind));
398
        WASM_PARSER_FAIL_IF(initExprType != I32, "Element init_expr must produce an i32");
399
        WASM_PARSER_FAIL_IF(!parseVarUInt32(indexCount), "can't get ", elementNum, "th index count for Element section");
400
        WASM_PARSER_FAIL_IF(indexCount == std::numeric_limits<uint32_t>::max(), "Element section's ", elementNum, "th index count is too big ", indexCount);
401
438
402
        ASSERT(!!m_info->tables[tableIndex]);
439
            uint32_t indexCount;
440
            WASM_FAIL_IF_HELPER_FAILS(parseIndexCountForElemSection(indexCount, elementNum));
441
            ASSERT(!!m_info->tables[tableIndex]);
403
442
404
        Element element(tableIndex, makeI32InitExpr(initOpcode, initExprBits));
443
            Element element(Element::Kind::Active, TableElementType::Funcref, tableIndex, WTFMove(initExpr));
405
        WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
444
            WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
406
445
407
        for (unsigned index = 0; index < indexCount; ++index) {
446
            for (unsigned index = 0; index < indexCount; ++index) {
408
            uint32_t functionIndex;
447
                Optional<uint32_t> funcIdx;
409
            WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), "can't get Element section's ", elementNum, "th element's ", index, "th index");
448
                WASM_FAIL_IF_HELPER_FAILS(parseFuncIdxForElemSection(funcIdx, elementNum, index));
410
            WASM_PARSER_FAIL_IF(functionIndex >= m_info->functionIndexSpaceSize(), "Element section's ", elementNum, "th element's ", index, "th index is ", functionIndex, " which exceeds the function index space size of ", m_info->functionIndexSpaceSize());
449
                element.functionIndices.uncheckedAppend(WTFMove(funcIdx));
450
            }
411
451
412
            element.functionIndices.uncheckedAppend(functionIndex);
452
            m_info->elements.uncheckedAppend(WTFMove(element));
453
            break;
413
        }
454
        }
455
        case 0x03: {
456
            WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
457
            WASM_PARSER_FAIL_IF(true, "unsupported ", elementNum, "th Element reserved byte");
458
            break;
459
        }
460
        case 0x04: {
461
            WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
462
463
            const uint32_t tableIndex = 0;
464
            WASM_FAIL_IF_HELPER_FAILS(validateElementTableIdx(tableIndex));
465
466
            Optional<I32InitExpr> initExpr;
467
            WASM_FAIL_IF_HELPER_FAILS(parseI32InitExpr(initExpr));
468
469
            uint32_t indexCount;
470
            WASM_FAIL_IF_HELPER_FAILS(parseIndexCountForElemSection(indexCount, elementNum));
471
            ASSERT(!!m_info->tables[tableIndex]);
472
473
            Element element(Element::Kind::Active, TableElementType::Funcref, tableIndex, WTFMove(initExpr));
474
            WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
475
476
            for (unsigned index = 0; index < indexCount; ++index) {
477
                Optional<uint32_t> funcIdx;
478
                WASM_FAIL_IF_HELPER_FAILS(parseFuncIdxFromRefExpForElemSection(funcIdx, elementNum, index));
479
                element.functionIndices.uncheckedAppend(WTFMove(funcIdx));
480
            }
481
482
            m_info->elements.uncheckedAppend(WTFMove(element));
483
            break;
484
        }
485
        case 0x05: {
486
            WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
487
            Type refType;
488
            WASM_PARSER_FAIL_IF(!parseRefType(refType), "can't parse reftype in elem section");
489
            WASM_PARSER_FAIL_IF(refType == Externref, "reftype in element section should be funcref");
490
491
            uint32_t indexCount;
492
            WASM_FAIL_IF_HELPER_FAILS(parseIndexCountForElemSection(indexCount, elementNum));
493
494
            Element element(Element::Kind::Passive, TableElementType::Funcref);
495
            WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
496
497
            for (unsigned index = 0; index < indexCount; ++index) {
498
                Optional<uint32_t> funcIdx;
499
                WASM_FAIL_IF_HELPER_FAILS(parseFuncIdxFromRefExpForElemSection(funcIdx, elementNum, index));
500
                element.functionIndices.uncheckedAppend(WTFMove(funcIdx));
501
            }
502
503
            m_info->elements.uncheckedAppend(WTFMove(element));
504
            break;
505
        }
506
        case 0x06: {
507
            WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
508
509
            uint32_t tableIndex;
510
            WASM_PARSER_FAIL_IF(!parseVarUInt32(tableIndex), "can't get ", elementNum, "th Element table index");
511
            WASM_FAIL_IF_HELPER_FAILS(validateElementTableIdx(tableIndex));
512
513
            Optional<I32InitExpr> initExpr;
514
            WASM_FAIL_IF_HELPER_FAILS(parseI32InitExpr(initExpr));
515
516
            Type refType;
517
            WASM_PARSER_FAIL_IF(!parseRefType(refType), "can't parse reftype in elem section");
518
            WASM_PARSER_FAIL_IF(refType == Externref, "reftype in element section should be funcref");
519
520
            uint32_t indexCount;
521
            WASM_FAIL_IF_HELPER_FAILS(parseIndexCountForElemSection(indexCount, elementNum));
522
            ASSERT(!!m_info->tables[tableIndex]);
414
523
415
        m_info->elements.uncheckedAppend(WTFMove(element));
524
            Element element(Element::Kind::Active, TableElementType::Funcref, tableIndex, WTFMove(initExpr));
525
            WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
526
527
            for (unsigned index = 0; index < indexCount; ++index) {
528
                Optional<uint32_t> funcIdx;
529
                WASM_FAIL_IF_HELPER_FAILS(parseFuncIdxFromRefExpForElemSection(funcIdx, elementNum, index));
530
                element.functionIndices.uncheckedAppend(WTFMove(funcIdx));
531
            }
532
533
            m_info->elements.uncheckedAppend(WTFMove(element));
534
            break;
535
        }
536
        case 0x07: {
537
            WASM_PARSER_FAIL_IF(!Options::useWebAssemblyReferences(), "references are not enabled");
538
            WASM_PARSER_FAIL_IF(true, "unsupported ", elementNum, "th Element reserved byte");
539
            break;
540
        }
541
        default:
542
            WASM_PARSER_FAIL_IF(true, "can't get ", elementNum, "th Element reserved byte");
543
        }
416
    }
544
    }
417
545
418
    return { };
546
    return { };
Lines 504-509 auto SectionParser::parseInitExpr(uint8_t& opcode, uint64_t& bitsOrImportNumber, a/Source/JavaScriptCore/wasm/WasmSectionParser.cpp_sec2
504
    return { };
632
    return { };
505
}
633
}
506
634
635
auto SectionParser::validateElementTableIdx(uint32_t tableIndex) -> PartialResult
636
{
637
    WASM_PARSER_FAIL_IF(tableIndex >= m_info->tableCount(), "Element section for Table ", tableIndex, " exceeds available Table ", m_info->tableCount());
638
    WASM_PARSER_FAIL_IF(m_info->tables[tableIndex].type() != TableElementType::Funcref, "Table ", tableIndex, " must have type 'funcref' to have an element section");
639
640
    return { };
641
}
642
643
auto SectionParser::parseI32InitExpr(Optional<I32InitExpr>& initExpr) -> PartialResult
644
{
645
    uint8_t initOpcode;
646
    uint64_t initExprBits;
647
    Type initExprType;
648
    WASM_FAIL_IF_HELPER_FAILS(parseInitExpr(initOpcode, initExprBits, initExprType));
649
    WASM_PARSER_FAIL_IF(initExprType != I32, "Element init_expr must produce an i32");
650
    initExpr = makeI32InitExpr(initOpcode, initExprBits);
651
652
    return { };
653
}
654
655
auto SectionParser::parseElemKind(uint8_t& resultElemKind) -> PartialResult
656
{
657
    uint8_t elemKind;
658
    WASM_PARSER_FAIL_IF(!parseUInt8(elemKind), "can't get elemkind");
659
    WASM_PARSER_FAIL_IF(!!elemKind, "elemkind must be zero");
660
    resultElemKind = elemKind;
661
662
    return { };
663
}
664
665
auto SectionParser::parseIndexCountForElemSection(uint32_t& resultIndexCount, const unsigned elementNum) -> PartialResult
666
{
667
    uint32_t indexCount;
668
    WASM_PARSER_FAIL_IF(!parseVarUInt32(indexCount), "can't get ", elementNum, "th index count for Element section");
669
    WASM_PARSER_FAIL_IF(indexCount == std::numeric_limits<uint32_t>::max(), "Element section's ", elementNum, "th index count is too big ", indexCount);
670
    resultIndexCount = indexCount;
671
672
    return { };
673
}
674
675
auto SectionParser::parseFuncIdxFromRefExpForElemSection(Optional<uint32_t>& funcIdx, const unsigned elementNum, const unsigned index) -> PartialResult
676
{
677
    uint8_t opcode;
678
    WASM_PARSER_FAIL_IF(!parseUInt8(opcode), "can't get opcode for exp in element section's ", elementNum, "th element's ", index, "th index");
679
    WASM_PARSER_FAIL_IF((opcode != RefFunc) && (opcode != RefNull), "opcode for exp in element section's should be either ref.func or ref.null ", elementNum, "th element's ", index, "th index");
680
681
    if (opcode == RefFunc) {
682
        uint32_t functionIndex;
683
        WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), "can't get Element section's ", elementNum, "th element's ", index, "th index");
684
        WASM_PARSER_FAIL_IF(functionIndex >= m_info->functionIndexSpaceSize(), "Element section's ", elementNum, "th element's ", index, "th index is ", functionIndex, " which exceeds the function index space size of ", m_info->functionIndexSpaceSize());
685
        funcIdx = functionIndex;
686
    } else {
687
        Type typeOfNull;
688
        WASM_PARSER_FAIL_IF(!parseRefType(typeOfNull), "ref.null type must be a func type in elem section");
689
        WASM_PARSER_FAIL_IF(typeOfNull != Funcref, "ref.null extern is forbidden in element section's, ", elementNum, "th element's ", index, "th index");
690
    }
691
692
    WASM_PARSER_FAIL_IF(!parseUInt8(opcode), "can't get opcode for exp end in element section's ", elementNum, "th element's ", index, "th index");
693
    WASM_PARSER_FAIL_IF(opcode != End, "malformed expr in element section's", elementNum, "th element's ", index, "th index");
694
695
    return { };
696
}
697
698
auto SectionParser::parseFuncIdxForElemSection(Optional<uint32_t>& funcIdx, const unsigned elementNum, const unsigned index) -> PartialResult
699
{
700
    uint32_t functionIndex;
701
    WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), "can't get Element section's ", elementNum, "th element's ", index, "th index");
702
    WASM_PARSER_FAIL_IF(functionIndex >= m_info->functionIndexSpaceSize(), "Element section's ", elementNum, "th element's ", index, "th index is ", functionIndex, " which exceeds the function index space size of ", m_info->functionIndexSpaceSize());
703
    funcIdx = functionIndex;
704
705
    return { };
706
}
707
507
auto SectionParser::parseGlobalType(GlobalInformation& global) -> PartialResult
708
auto SectionParser::parseGlobalType(GlobalInformation& global) -> PartialResult
508
{
709
{
509
    uint8_t mutability;
710
    uint8_t mutability;
- a/Source/JavaScriptCore/wasm/WasmSectionParser.h +7 lines
Lines 66-71 private: a/Source/JavaScriptCore/wasm/WasmSectionParser.h_sec1
66
    PartialResult WARN_UNUSED_RETURN parseResizableLimits(uint32_t& initial, Optional<uint32_t>& maximum);
66
    PartialResult WARN_UNUSED_RETURN parseResizableLimits(uint32_t& initial, Optional<uint32_t>& maximum);
67
    PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&, uint64_t&, Type& initExprType);
67
    PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&, uint64_t&, Type& initExprType);
68
68
69
    PartialResult WARN_UNUSED_RETURN validateElementTableIdx(uint32_t);
70
    PartialResult WARN_UNUSED_RETURN parseI32InitExpr(Optional<I32InitExpr>&);
71
    PartialResult WARN_UNUSED_RETURN parseElemKind(uint8_t& elemKind);
72
    PartialResult WARN_UNUSED_RETURN parseIndexCountForElemSection(uint32_t&, const unsigned);
73
    PartialResult WARN_UNUSED_RETURN parseFuncIdxFromRefExpForElemSection(Optional<uint32_t>&, const unsigned, const unsigned);
74
    PartialResult WARN_UNUSED_RETURN parseFuncIdxForElemSection(Optional<uint32_t>&, const unsigned, const unsigned);
75
69
    size_t m_offsetInSource;
76
    size_t m_offsetInSource;
70
    Ref<ModuleInformation> m_info;
77
    Ref<ModuleInformation> m_info;
71
};
78
};
- a/Source/JavaScriptCore/wasm/WasmSlowPaths.cpp +11 lines
Lines 316-321 WASM_SLOW_PATH_DECL(table_set) a/Source/JavaScriptCore/wasm/WasmSlowPaths.cpp_sec1
316
    WASM_END();
316
    WASM_END();
317
}
317
}
318
318
319
WASM_SLOW_PATH_DECL(table_init)
320
{
321
    auto instruction = pc->as<WasmTableInit, WasmOpcodeTraits>();
322
    int32_t dstOffset = READ(instruction.m_dstOffset).unboxedInt32();
323
    int32_t srcOffset = READ(instruction.m_srcOffset).unboxedInt32();
324
    int32_t length = READ(instruction.m_length).unboxedInt32();
325
    if (!Wasm::operationWasmTableInit(instance, instruction.m_elementIndex, instruction.m_tableIndex, dstOffset, srcOffset, length))
326
        WASM_THROW(Wasm::ExceptionType::OutOfBoundsTableAccess);
327
    WASM_END();
328
}
329
319
WASM_SLOW_PATH_DECL(table_size)
330
WASM_SLOW_PATH_DECL(table_size)
320
{
331
{
321
    auto instruction = pc->as<WasmTableSize, WasmOpcodeTraits>();
332
    auto instruction = pc->as<WasmTableSize, WasmOpcodeTraits>();
- a/Source/JavaScriptCore/wasm/WasmSlowPaths.h +1 lines
Lines 59-64 WASM_SLOW_PATH_HIDDEN_DECL(out_of_line_jump_target); a/Source/JavaScriptCore/wasm/WasmSlowPaths.h_sec1
59
WASM_SLOW_PATH_HIDDEN_DECL(ref_func);
59
WASM_SLOW_PATH_HIDDEN_DECL(ref_func);
60
WASM_SLOW_PATH_HIDDEN_DECL(table_get);
60
WASM_SLOW_PATH_HIDDEN_DECL(table_get);
61
WASM_SLOW_PATH_HIDDEN_DECL(table_set);
61
WASM_SLOW_PATH_HIDDEN_DECL(table_set);
62
WASM_SLOW_PATH_HIDDEN_DECL(table_init);
62
WASM_SLOW_PATH_HIDDEN_DECL(table_size);
63
WASM_SLOW_PATH_HIDDEN_DECL(table_size);
63
WASM_SLOW_PATH_HIDDEN_DECL(table_fill);
64
WASM_SLOW_PATH_HIDDEN_DECL(table_fill);
64
WASM_SLOW_PATH_HIDDEN_DECL(table_grow);
65
WASM_SLOW_PATH_HIDDEN_DECL(table_grow);
- a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp -15 / +19 lines
Lines 359-365 void WebAssemblyModuleRecord::link(JSGlobalObject* globalObject, JSValue, JSObje a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec1
359
        }
359
        }
360
    }
360
    }
361
361
362
    unsigned functionImportCount = codeBlock->functionImportCount();
363
    auto makeFunctionWrapper = [&] (const String& field, uint32_t index) -> JSValue {
362
    auto makeFunctionWrapper = [&] (const String& field, uint32_t index) -> JSValue {
364
        // If we already made a wrapper, do not make a new one.
363
        // If we already made a wrapper, do not make a new one.
365
        JSValue wrapper = m_instance->instance().getFunctionWrapper(index);
364
        JSValue wrapper = m_instance->instance().getFunctionWrapper(index);
Lines 370-376 void WebAssemblyModuleRecord::link(JSGlobalObject* globalObject, JSValue, JSObje a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec2
370
        // 1. If e is a closure c:
369
        // 1. If e is a closure c:
371
        //   i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func.
370
        //   i. If there is an Exported Function Exotic Object func in funcs whose func.[[Closure]] equals c, then return func.
372
        //   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.)
371
        //   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.)
373
        if (index < functionImportCount) {
372
        if (m_instance->instance().isImportFunction(index)) {
374
            JSObject* functionImport = m_instance->instance().importFunction<WriteBarrier<JSObject>>(index)->get();
373
            JSObject* functionImport = m_instance->instance().importFunction<WriteBarrier<JSObject>>(index)->get();
375
            if (isWebAssemblyHostFunction(vm, functionImport))
374
            if (isWebAssemblyHostFunction(vm, functionImport))
376
                wrapper = functionImport;
375
                wrapper = functionImport;
Lines 546-568 JSValue WebAssemblyModuleRecord::evaluate(JSGlobalObject* globalObject) a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec3
546
545
547
    auto forEachElement = [&] (auto fn) {
546
    auto forEachElement = [&] (auto fn) {
548
        for (const Wasm::Element& element : moduleInformation.elements) {
547
        for (const Wasm::Element& element : moduleInformation.elements) {
548
            if (!element.tableIndexIfActive)
549
                continue;
549
            // It should be a validation error to have any elements without a table.
550
            // It should be a validation error to have any elements without a table.
550
            // Also, it could be that a table wasn't imported, or that the table
551
            // Also, it could be that a table wasn't imported, or that the table
551
            // imported wasn't compatible. However, those should error out before
552
            // imported wasn't compatible. However, those should error out before
552
            // getting here.
553
            // getting here.
553
            ASSERT(!!m_instance->table(element.tableIndex));
554
            ASSERT(!!m_instance->table(*element.tableIndexIfActive));
554
555
555
            if (!element.functionIndices.size())
556
            if (!element.functionIndices.size())
556
                continue;
557
                continue;
557
558
558
            uint32_t elementIndex = element.offset.isGlobalImport()
559
            if (element.active()) {
559
                ? static_cast<uint32_t>(m_instance->instance().loadI32Global(element.offset.globalImportIndex()))
560
                uint32_t elementIndex = element.offsetIfActive->isGlobalImport()
560
                : element.offset.constValue();
561
                    ? static_cast<uint32_t>(m_instance->instance().loadI32Global(element.offsetIfActive->globalImportIndex()))
562
                    : element.offsetIfActive->constValue();
561
563
562
            fn(element, element.tableIndex, elementIndex);
564
                fn(element, *element.tableIndexIfActive, elementIndex);
563
565
564
            if (exception)
566
                if (exception)
565
                break;
567
                    break;
568
            }
566
        }
569
        }
567
    };
570
    };
568
571
Lines 605-616 JSValue WebAssemblyModuleRecord::evaluate(JSGlobalObject* globalObject) a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec4
605
        return exception.value();
608
        return exception.value();
606
609
607
    forEachElement([&] (const Wasm::Element& element, uint32_t tableIndex, uint32_t elementIndex) {
610
    forEachElement([&] (const Wasm::Element& element, uint32_t tableIndex, uint32_t elementIndex) {
608
        for (uint32_t i = 0; i < element.functionIndices.size(); ++i) {
611
        for (uint32_t i = 0; i < element.functionIndices.size(); ++i, ++elementIndex) {
612
            if (!element.functionIndices[i].hasValue()) {
613
                m_instance->table(tableIndex)->clear(elementIndex);
614
                continue;
615
            }
616
609
            // FIXME: This essentially means we're exporting an import.
617
            // FIXME: This essentially means we're exporting an import.
610
            // We need a story here. We need to create a WebAssemblyFunction
618
            // We need a story here. We need to create a WebAssemblyFunction
611
            // for the import.
619
            // for the import.
612
            // https://bugs.webkit.org/show_bug.cgi?id=165510
620
            // https://bugs.webkit.org/show_bug.cgi?id=165510
613
            uint32_t functionIndex = element.functionIndices[i];
621
            uint32_t functionIndex = *element.functionIndices[i];
614
            Wasm::SignatureIndex signatureIndex = module.signatureIndexFromFunctionIndexSpace(functionIndex);
622
            Wasm::SignatureIndex signatureIndex = module.signatureIndexFromFunctionIndexSpace(functionIndex);
615
            if (functionIndex < codeBlock->functionImportCount()) {
623
            if (functionIndex < codeBlock->functionImportCount()) {
616
                JSObject* functionImport = m_instance->instance().importFunction<WriteBarrier<JSObject>>(functionIndex)->get();
624
                JSObject* functionImport = m_instance->instance().importFunction<WriteBarrier<JSObject>>(functionIndex)->get();
Lines 621-633 JSValue WebAssemblyModuleRecord::evaluate(JSGlobalObject* globalObject) a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec5
621
                    // the only type this could be is WebAssemblyFunction.
629
                    // the only type this could be is WebAssemblyFunction.
622
                    RELEASE_ASSERT(wasmFunction);
630
                    RELEASE_ASSERT(wasmFunction);
623
                    m_instance->table(tableIndex)->set(elementIndex, wasmFunction);
631
                    m_instance->table(tableIndex)->set(elementIndex, wasmFunction);
624
                    ++elementIndex;
625
                    continue;
632
                    continue;
626
                }
633
                }
627
634
628
                m_instance->table(tableIndex)->set(elementIndex,
635
                m_instance->table(tableIndex)->set(elementIndex,
629
                    WebAssemblyWrapperFunction::create(vm, globalObject, globalObject->webAssemblyWrapperFunctionStructure(), functionImport, functionIndex, m_instance.get(), signatureIndex));
636
                    WebAssemblyWrapperFunction::create(vm, globalObject, globalObject->webAssemblyWrapperFunctionStructure(), functionImport, functionIndex, m_instance.get(), signatureIndex));
630
                ++elementIndex;
631
                continue;
637
                continue;
632
            }
638
            }
633
639
Lines 640-648 JSValue WebAssemblyModuleRecord::evaluate(JSGlobalObject* globalObject) a/Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp_sec6
640
            // https://bugs.webkit.org/show_bug.cgi?id=165825
646
            // https://bugs.webkit.org/show_bug.cgi?id=165825
641
            WebAssemblyFunction* function = WebAssemblyFunction::create(
647
            WebAssemblyFunction* function = WebAssemblyFunction::create(
642
                vm, globalObject, globalObject->webAssemblyFunctionStructure(), signature.argumentCount(), String(), m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex);
648
                vm, globalObject, globalObject->webAssemblyFunctionStructure(), signature.argumentCount(), String(), m_instance.get(), embedderEntrypointCallee, entrypointLoadLocation, signatureIndex);
643
644
            m_instance->table(tableIndex)->set(elementIndex, function);
649
            m_instance->table(tableIndex)->set(elementIndex, function);
645
            ++elementIndex;
646
        }
650
        }
647
    });
651
    });
648
652
- a/Source/JavaScriptCore/wasm/wasm.json -1 / +2 lines
Lines 69-77 a/Source/JavaScriptCore/wasm/wasm.json_sec1
69
        "set_global":          { "category": "special",    "value":  36, "return": [],                               "parameter": ["any"],                        "immediate": [{"name": "global_index",   "type": "varuint32"}],                                             "description": "write a global variable" },
69
        "set_global":          { "category": "special",    "value":  36, "return": [],                               "parameter": ["any"],                        "immediate": [{"name": "global_index",   "type": "varuint32"}],                                             "description": "write a global variable" },
70
        "table.get":           { "category": "special",    "value":  37, "return": ["externref"],                    "parameter": ["i32"],                        "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "get a table value" },
70
        "table.get":           { "category": "special",    "value":  37, "return": ["externref"],                    "parameter": ["i32"],                        "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "get a table value" },
71
        "table.set":           { "category": "special",    "value":  38, "return": [],                               "parameter": ["i32", "externref"],           "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "set a table value" },
71
        "table.set":           { "category": "special",    "value":  38, "return": [],                               "parameter": ["i32", "externref"],           "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "set a table value" },
72
        "table.init":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": ["i32", "i32", "i32"],          "immediate": [{"name": "element_index",  "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "initialize table from given element", "extendedOp": 12 },
72
        "table.grow":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": ["externref", "i32"],           "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "grow a table by the given delta and return the previous size, or -1 if enough space cannot be allocated", "extendedOp": 15 },
73
        "table.grow":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": ["externref", "i32"],           "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "grow a table by the given delta and return the previous size, or -1 if enough space cannot be allocated", "extendedOp": 15 },
73
        "table.size":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": [],                             "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "get the size of a table", "extendedOp": 16 },
74
        "table.size":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": [],                             "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "get the size of a table", "extendedOp": 16 },
74
        "table.fill":           { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": ["i32", "externref", "i32"],    "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "fill entries [i,i+n) with the given value", "extendedOp": 17 },
75
        "table.fill":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": ["i32", "externref", "i32"],    "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "fill entries [i,i+n) with the given value", "extendedOp": 17 },
75
        "call":                { "category": "call",       "value":  16, "return": ["call"],                         "parameter": ["call"],                       "immediate": [{"name": "function_index", "type": "varuint32"}],                                             "description": "call a function by its index" },
76
        "call":                { "category": "call",       "value":  16, "return": ["call"],                         "parameter": ["call"],                       "immediate": [{"name": "function_index", "type": "varuint32"}],                                             "description": "call a function by its index" },
76
        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],                         "parameter": ["call"],                       "immediate": [{"name": "type_index",     "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "call a function indirect with an expected signature" },
77
        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],                         "parameter": ["call"],                       "immediate": [{"name": "type_index",     "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "call a function indirect with an expected signature" },
77
        "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],                          "parameter": ["addr"],                       "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset",   "type": "varuint32"}], "description": "load from memory" },
78
        "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],                          "parameter": ["addr"],                       "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset",   "type": "varuint32"}], "description": "load from memory" },
- a/JSTests/ChangeLog +43 lines
Lines 1-3 a/JSTests/ChangeLog_sec1
1
2020-11-26  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
2
3
        [WASM-References] Add table.init
4
        https://bugs.webkit.org/show_bug.cgi?id=219297
5
6
        Reviewed by NOBODY (OOPS!).
7
        Added very basic tests for table.init.
8
        Once we have support for elem.drop and declarative elements we can replace them spec tests. 
9
10
        * wasm/references/element_parsing.js:
11
        * wasm/references/table_init.js: Added.
12
        (module):
13
        (basicTest):
14
        (elementIndexOutOfBounds):
15
        (invalidSourceOffset):
16
        (invalidLength):
17
        * wasm/wasm.json:
18
19
2020-11-19  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
20
21
        [WASM-References] Add support for active mods in element section
22
        https://bugs.webkit.org/show_bug.cgi?id=219192
23
24
        Reviewed by NOBODY (OOPS!).
25
        Fix builder dsl to produce the right element section.
26
        It produces correct wasm code for the previous spec and for the ref-types spec because the core spec is binary compatible with the ref-types.
27
        https://webassembly.github.io/reference-types/core/binary/modules.html#element-section.
28
        Added basic tests for the element section.
29
30
31
        * wasm/Builder.js:
32
        (export.default.Builder.prototype._registerSectionBuilders.const.section.in.WASM.description.section.switch.section.case.string_appeared_here.this.section):
33
        * wasm/Builder_WebAssemblyBinary.js:
34
        (const.emitters.Element):
35
        * wasm/references-spec-tests/ref_null.js:
36
        (module):
37
        * wasm/references/element_active_mod.js: Added.
38
        (module):
39
        (basicTest):
40
        (refNullExternInElemsSection):
41
        * wasm/references/element_parsing.js:
42
        * wasm/references/multitable.js:
43
1
2020-11-18  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
44
2020-11-18  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
2
45
3
        [WASM-References] Remove subtyping rule for externref and funcref
46
        [WASM-References] Remove subtyping rule for externref and funcref
- a/JSTests/wasm/Builder.js -2 / +2 lines
Lines 594-601 export default class Builder { a/JSTests/wasm/Builder.js_sec1
594
                    const s = this._addSection(section);
594
                    const s = this._addSection(section);
595
                    const elementBuilder = {
595
                    const elementBuilder = {
596
                        End: () => this,
596
                        End: () => this,
597
                        Element: ({tableIndex = 0, offset, functionIndices}) => {
597
                        Element: ({tableIndex = 0, offset, elemkind = 0, functionIndices}) => {
598
                            s.data.push({tableIndex, offset, functionIndices});
598
                            s.data.push({tableIndex, offset, elemkind, functionIndices});
599
                            return _errorHandlingProxyFor(elementBuilder);
599
                            return _errorHandlingProxyFor(elementBuilder);
600
                        }
600
                        }
601
                    };
601
                    };
- a/JSTests/wasm/Builder_WebAssemblyBinary.js -4 / +11 lines
Lines 193-202 const emitters = { a/JSTests/wasm/Builder_WebAssemblyBinary.js_sec1
193
    Element: (section, bin) => {
193
    Element: (section, bin) => {
194
        const data = section.data;
194
        const data = section.data;
195
        put(bin, "varuint32", data.length);
195
        put(bin, "varuint32", data.length);
196
        for (const {tableIndex, offset, functionIndices} of data) {
196
        for (const {tableIndex, offset, elemkind, functionIndices} of data) {
197
            if (tableIndex != 0)
197
            let flags = tableIndex == 0 ? 0 : 2;
198
                put(bin, "uint8", 2);
198
            put(bin, "uint8", flags);
199
            put(bin, "varuint32", tableIndex);
199
200
            if (flags == 2) {
201
              put(bin, "varuint32", tableIndex);
202
            }
200
203
201
            let initExpr;
204
            let initExpr;
202
            if (typeof offset === "number")
205
            if (typeof offset === "number")
Lines 205-210 const emitters = { a/JSTests/wasm/Builder_WebAssemblyBinary.js_sec2
205
                initExpr = offset;
208
                initExpr = offset;
206
            putInitExpr(bin, initExpr);
209
            putInitExpr(bin, initExpr);
207
210
211
            if (flags == 2) {
212
              put(bin, "uint8", elemkind);
213
            }
214
208
            put(bin, "varuint32", functionIndices.length);
215
            put(bin, "varuint32", functionIndices.length);
209
            for (const functionIndex of functionIndices)
216
            for (const functionIndex of functionIndices)
210
                put(bin, "varuint32", functionIndex);
217
                put(bin, "varuint32", functionIndex);
- a/JSTests/wasm/references-spec-tests/ref_null.js -1 / +1 lines
Lines 62-68 function module(bytes, valid = true) { a/JSTests/wasm/references-spec-tests/ref_null.js_sec1
62
    throw new Error("Wasm validate throws");
62
    throw new Error("Wasm validate throws");
63
  }
63
  }
64
  if (validated !== valid) {
64
  if (validated !== valid) {
65
    //throw new Error("Wasm validate failure" + (valid ? "" : " expected"));
65
    throw new Error("Wasm validate failure" + (valid ? "" : " expected"));
66
  }
66
  }
67
  return new WebAssembly.Module(buffer);
67
  return new WebAssembly.Module(buffer);
68
}
68
}
- a/JSTests/wasm/references/element_active_mod.js +59 lines
Line 0 a/JSTests/wasm/references/element_active_mod.js_sec1
1
//@ runWebAssemblySuite("--useWebAssemblyReferences=true")
2
import * as assert from '../assert.js';
3
4
function module(bytes, valid = true) {
5
  let buffer = new ArrayBuffer(bytes.length);
6
  let view = new Uint8Array(buffer);
7
  for (let i = 0; i < bytes.length; ++i) {
8
    view[i] = bytes.charCodeAt(i);
9
  }
10
  return new WebAssembly.Module(buffer);
11
}
12
13
function basicTest() {
14
  /*
15
  (module
16
    (func $f (result i32)
17
      (i32.const 37)
18
    )
19
    (func $g (result i32)
20
      (i32.const 42)
21
    )
22
    (table $t1 10 funcref)
23
    (table $t2 20 funcref)
24
    (elem (i32.const 3) funcref (ref.func $g) (ref.null func) (ref.func $f) (ref.null func))
25
    (elem (table $t2) (i32.const 7) funcref (ref.func $f) (ref.null func) (ref.func $g))
26
    (func (export "get_tbl1") (param $idx i32) (result funcref)
27
      (table.get $t1 (local.get $idx))
28
    )
29
    (func (export "get_tbl2") (param $idx i32) (result funcref)
30
      (table.get $t2 (local.get $idx))
31
    )
32
  )
33
  */
34
  let instance = new WebAssembly.Instance(module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x0a\x02\x60\x00\x01\x7f\x60\x01\x7f\x01\x70\x03\x05\x04\x00\x00\x01\x01\x04\x07\x02\x70\x00\x0a\x70\x00\x14\x07\x17\x02\x08\x67\x65\x74\x5f\x74\x62\x6c\x31\x00\x02\x08\x67\x65\x74\x5f\x74\x62\x6c\x32\x00\x03\x09\x22\x02\x04\x41\x03\x0b\x04\xd2\x01\x0b\xd0\x70\x0b\xd2\x00\x0b\xd0\x70\x0b\x06\x01\x41\x07\x0b\x70\x03\xd2\x00\x0b\xd0\x70\x0b\xd2\x01\x0b\x0a\x19\x04\x04\x00\x41\x25\x0b\x04\x00\x41\x2a\x0b\x06\x00\x20\x00\x25\x00\x0b\x06\x00\x20\x00\x25\x01\x0b"));
35
36
  assert.eq(instance.exports.get_tbl1(3)(), 42);
37
  assert.eq(instance.exports.get_tbl1(4), null);
38
  assert.eq(instance.exports.get_tbl1(5)(), 37);
39
  assert.eq(instance.exports.get_tbl1(6), null);
40
41
  assert.eq(instance.exports.get_tbl2(7)(), 37);
42
  assert.eq(instance.exports.get_tbl2(8), null);
43
  assert.eq(instance.exports.get_tbl2(9)(), 42);
44
}
45
46
function refNullExternInElemsSection() {
47
  /*
48
  (module
49
    (table $t 10 funcref)
50
    (elem (i32.const 3) funcref (ref.null extern))
51
  )
52
  */
53
  assert.throws(() => module("\x00\x61\x73\x6d\x01\x00\x00\x00\x04\x04\x01\x70\x00\x0a\x09\x09\x01\x04\x41\x03\x0b\x01\xd0\x6f\x0b"),
54
  WebAssembly.CompileError,
55
  "WebAssembly.Module doesn't parse at byte 24: ref.null extern is forbidden in element section's, 0th element's 0th index (evaluating 'new WebAssembly.Module(buffer)')");
56
}
57
58
basicTest();
59
refNullExternInElemsSection();
- a/JSTests/wasm/references/element_parsing.js -1 / +1 lines
Lines 23-26 assert.throws(() => module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x97\x80\x80\x80 a/JSTests/wasm/references/element_parsing.js_sec1
23
//  + "\x02"
23
//  + "\x02"
24
    + "\x01"
24
    + "\x01"
25
    + "\x41\x01\x0b\x01\x02\x0a\xd4\x80\x80\x80\x00\x07\x85\x80\x80\x80\x00\x00\x20\x00\xd1\x0b\x85\x80\x80\x80\x00\x00\x20\x00\xd1\x0b\x82\x80\x80\x80\x00\x00\x0b\x88\x80\x80\x80\x00\x00\x41\x01\x20\x00\x26\x00\x0b\x8c\x80\x80\x80\x00\x00\x41\x01\xd0\x26\x00\x41\x01\xd0\x26\x01\x0b\x88\x80\x80\x80\x00\x00\x20\x00\x25\x00\x10\x00\x0b\x88\x80\x80\x80\x00\x00\x20\x00\x25\x01\x10\x01\x0b"),
25
    + "\x41\x01\x0b\x01\x02\x0a\xd4\x80\x80\x80\x00\x07\x85\x80\x80\x80\x00\x00\x20\x00\xd1\x0b\x85\x80\x80\x80\x00\x00\x20\x00\xd1\x0b\x82\x80\x80\x80\x00\x00\x0b\x88\x80\x80\x80\x00\x00\x41\x01\x20\x00\x26\x00\x0b\x8c\x80\x80\x80\x00\x00\x41\x01\xd0\x26\x00\x41\x01\xd0\x26\x01\x0b\x88\x80\x80\x80\x00\x00\x20\x00\x25\x00\x10\x00\x0b\x88\x80\x80\x80\x00\x00\x20\x00\x25\x01\x10\x01\x0b"),
26
    Error, "WebAssembly.Module doesn't parse at byte 143: can't get 0th Element reserved byte, which should be either 0x00 or 0x02 followed by a table index (evaluating 'new WebAssembly.Module(buffer)')");
26
    Error, "WebAssembly.Module doesn't parse at byte 144: elemkind must be zero (evaluating 'new WebAssembly.Module(buffer)')");
- a/JSTests/wasm/references/multitable.js -1 / +1 lines
Lines 304-310 assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder a/JSTests/wasm/references/multitable.js_sec1
304
            .Function("ret42", { params: [], ret: "i32" })
304
            .Function("ret42", { params: [], ret: "i32" })
305
              .I32Const(42)
305
              .I32Const(42)
306
            .End()
306
            .End()
307
          .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't parse at byte 41: Table 0 must have type 'funcref' to have an element section (evaluating 'new WebAssembly.Module')")
307
          .End().WebAssembly().get())), Error, "WebAssembly.Module doesn't parse at byte 42: Table 0 must have type 'funcref' to have an element section (evaluating 'new WebAssembly.Module')")
308
308
309
assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
309
assert.throws(() => new WebAssembly.Instance(new WebAssembly.Module((new Builder())
310
          .Type().End()
310
          .Type().End()
- a/JSTests/wasm/references/table_init.js +159 lines
Line 0 a/JSTests/wasm/references/table_init.js_sec1
1
//@ runWebAssemblySuite("--useWebAssemblyReferences=true")
2
import * as assert from '../assert.js';
3
4
function module(bytes, valid = true) {
5
  let buffer = new ArrayBuffer(bytes.length);
6
  let view = new Uint8Array(buffer);
7
  for (let i = 0; i < bytes.length; ++i) {
8
    view[i] = bytes.charCodeAt(i);
9
  }
10
  return new WebAssembly.Module(buffer);
11
}
12
13
function basicTest() {
14
  /*
15
  (module
16
    (type $type0 (func (result i32)))
17
    (func $f (result i32) i32.const 37)
18
    (func $g (result i32) i32.const 42)
19
    (table $t0 10 funcref)
20
    (elem $e0 func $f $f $g $g)
21
    (elem $e1 funcref (ref.null func) (ref.null func) (ref.func $f))
22
    (func (export "init")
23
      (table.init $t0 $e0 (i32.const 0) (i32.const 0) (i32.const 4))
24
      (table.init $t0 $e1 (i32.const 4) (i32.const 1) (i32.const 2)))
25
    (func (export "get_func") (param $idx i32) (result funcref)
26
      (table.get $t0 (local.get $idx))))
27
  */
28
  let instance = new WebAssembly.Instance(module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x0d\x03\x60\x00\x01\x7f\x60\x00\x00\x60\x01\x7f\x01\x70\x03\x05\x04\x00\x00\x01\x02\x04\x04\x01\x70\x00\x0a\x07\x13\x02\x04\x69\x6e\x69\x74\x00\x02\x08\x67\x65\x74\x5f\x66\x75\x6e\x63\x00\x03\x09\x14\x02\x01\x00\x04\x00\x00\x01\x01\x05\x70\x03\xd0\x70\x0b\xd0\x70\x0b\xd2\x00\x0b\x0a\x29\x04\x04\x00\x41\x25\x0b\x04\x00\x41\x2a\x0b\x16\x00\x41\x00\x41\x00\x41\x04\xfc\x0c\x00\x00\x41\x04\x41\x01\x41\x02\xfc\x0c\x01\x00\x0b\x06\x00\x20\x00\x25\x00\x0b"));
29
30
  instance.exports.init();
31
  assert.eq(instance.exports.get_func(0)(), 37);
32
  assert.eq(instance.exports.get_func(1)(), 37);
33
  assert.eq(instance.exports.get_func(2)(), 42);
34
  assert.eq(instance.exports.get_func(3)(), 42);
35
  assert.eq(instance.exports.get_func(4), null);
36
  assert.eq(instance.exports.get_func(5)(), 37);
37
  assert.eq(instance.exports.get_func(6), null);
38
  assert.eq(instance.exports.get_func(7), null);
39
  assert.eq(instance.exports.get_func(8), null);
40
  assert.eq(instance.exports.get_func(9), null);
41
}
42
43
function elementIndexOutOfBounds() {
44
  /*
45
  (module
46
    (table $t0 10 funcref)
47
    (elem (i32.const 3) funcref (ref.null func))
48
    (func (export "run")
49
      (table.init $t0 1 (i32.const 1) (i32.const 2) (i32.const 3))
50
    )
51
  )
52
  */
53
  assert.throws(() => module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x04\x04\x01\x70\x00\x0a\x07\x07\x01\x03\x72\x75\x6e\x00\x00\x09\x09\x01\x04\x41\x03\x0b\x01\xd0\x70\x0b\x0a\x0e\x01\x0c\x00\x41\x01\x41\x02\x41\x03\xfc\x0c\x01\x00\x0b"),
54
  WebAssembly.CompileError,
55
  "WebAssembly.Module doesn't validate: element index 1 is invalid, limit is 1, in function at index 0 (evaluating 'new WebAssembly.Module(buffer)')");
56
}
57
58
function tableIndexOutOfBounds() {
59
  /*
60
  (module
61
    (table 10 funcref)
62
    (elem $e0 (i32.const 3) funcref (ref.null func))
63
    (func (export "run")
64
      (table.init 1 $e0 (i32.const 1) (i32.const 2) (i32.const 3))
65
    )
66
  )
67
  */
68
  assert.throws(() => module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x04\x04\x01\x70\x00\x0a\x07\x07\x01\x03\x72\x75\x6e\x00\x00\x09\x09\x01\x04\x41\x03\x0b\x01\xd0\x70\x0b\x0a\x0e\x01\x0c\x00\x41\x01\x41\x02\x41\x03\xfc\x0c\x00\x01\x0b"),
69
  WebAssembly.CompileError,
70
  "WebAssembly.Module doesn't validate: table index 1 is invalid, limit is 1, in function at index 0 (evaluating 'new WebAssembly.Module(buffer)')");
71
}
72
73
function invalidDestinationOffset() {
74
  /*
75
  (module
76
    (table $t0 10 funcref)
77
    (elem $e0 (i32.const 3) funcref (ref.null func))
78
    (func (export "run")
79
      (table.init $t0 $e0 (i64.const 1) (i32.const 2) (i32.const 3))
80
    )
81
  )
82
  */
83
  assert.throws(() => module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x04\x04\x01\x70\x00\x0a\x07\x07\x01\x03\x72\x75\x6e\x00\x00\x09\x09\x01\x04\x41\x03\x0b\x01\xd0\x70\x0b\x0a\x0e\x01\x0c\x00\x42\x01\x41\x02\x41\x03\xfc\x0c\x00\x00\x0b"),
84
  WebAssembly.CompileError,
85
  "WebAssembly.Module doesn't validate: table.init dst_offset to type I64 expected I32, in function at index 0 (evaluating 'new WebAssembly.Module(buffer)')");
86
87
  /*
88
  (module
89
    (table $t0 10 funcref)
90
    (elem $e0 funcref (ref.null func) (ref.null func) (ref.null func))
91
    (func (export "run")
92
      (table.init $t0 $e0 (i32.const 11) (i32.const 0) (i32.const 1))
93
    )
94
  )
95
  */
96
  const instance = new WebAssembly.Instance(module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x04\x04\x01\x70\x00\x0a\x07\x07\x01\x03\x72\x75\x6e\x00\x00\x09\x0d\x01\x05\x70\x03\xd0\x70\x0b\xd0\x70\x0b\xd0\x70\x0b\x0a\x0e\x01\x0c\x00\x41\x0b\x41\x00\x41\x01\xfc\x0c\x00\x00\x0b"));
97
  assert.throws(instance.exports.run, WebAssembly.RuntimeError, "Out of bounds table access (evaluating 'func(...args)')");
98
}
99
100
function invalidSourceOffset() {
101
  /*
102
  (module
103
    (table $t0 10 funcref)
104
    (elem $e0 (i32.const 3) funcref (ref.null func))
105
    (func (export "run")
106
      (table.init $t0 $e0 (i32.const 1) (i64.const 2) (i32.const 3))
107
    )
108
  )
109
  */
110
  assert.throws(() => module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x04\x04\x01\x70\x00\x0a\x07\x07\x01\x03\x72\x75\x6e\x00\x00\x09\x09\x01\x04\x41\x03\x0b\x01\xd0\x70\x0b\x0a\x0e\x01\x0c\x00\x41\x01\x42\x02\x41\x03\xfc\x0c\x00\x00\x0b"),
111
  WebAssembly.CompileError,
112
  "WebAssembly.Module doesn't validate: table.init src_offset to type I64 expected I32, in function at index 0 (evaluating 'new WebAssembly.Module(buffer)')");
113
114
  /*
115
  (module
116
    (table $t0 10 funcref)
117
    (elem $e0 funcref (ref.null func) (ref.null func) (ref.null func))
118
    (func (export "run")
119
      (table.init $t0 $e0 (i32.const 0) (i32.const 11) (i32.const 1))
120
    )
121
  )
122
  */
123
  const instance = new WebAssembly.Instance(module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x04\x04\x01\x70\x00\x0a\x07\x07\x01\x03\x72\x75\x6e\x00\x00\x09\x0d\x01\x05\x70\x03\xd0\x70\x0b\xd0\x70\x0b\xd0\x70\x0b\x0a\x0e\x01\x0c\x00\x41\x00\x41\x0b\x41\x01\xfc\x0c\x00\x00\x0b"));
124
  assert.throws(instance.exports.run, WebAssembly.RuntimeError, "Out of bounds table access (evaluating 'func(...args)')");
125
}
126
127
function invalidLength() {
128
  /*
129
  (module
130
    (table $t0 10 funcref)
131
    (elem $e0 (i32.const 3) funcref (ref.null func))
132
    (func (export "run")
133
      (table.init $t0 $e0 (i32.const 1) (i64.const 2) (i64.const 3))
134
    )
135
  )
136
  */
137
  assert.throws(() => module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x04\x04\x01\x70\x00\x0a\x07\x07\x01\x03\x72\x75\x6e\x00\x00\x09\x09\x01\x04\x41\x03\x0b\x01\xd0\x70\x0b\x0a\x0e\x01\x0c\x00\x41\x01\x41\x02\x42\x03\xfc\x0c\x00\x00\x0b"),
138
  WebAssembly.CompileError,
139
  "WebAssembly.Module doesn't validate: table.init length to type I64 expected I32, in function at index 0 (evaluating 'new WebAssembly.Module(buffer)')");
140
141
  /*
142
  (module
143
    (table $t0 10 funcref)
144
    (elem $e0 funcref (ref.null func) (ref.null func) (ref.null func))
145
    (func (export "run")
146
      (table.init $t0 $e0 (i32.const 0) (i32.const 0) (i32.const 11))
147
    )
148
  )
149
  */
150
  const instance = new WebAssembly.Instance(module("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x04\x01\x60\x00\x00\x03\x02\x01\x00\x04\x04\x01\x70\x00\x0a\x07\x07\x01\x03\x72\x75\x6e\x00\x00\x09\x0d\x01\x05\x70\x03\xd0\x70\x0b\xd0\x70\x0b\xd0\x70\x0b\x0a\x0e\x01\x0c\x00\x41\x00\x41\x00\x41\x0b\xfc\x0c\x00\x00\x0b"));
151
  assert.throws(instance.exports.run, WebAssembly.RuntimeError, "Out of bounds table access (evaluating 'func(...args)')");
152
}
153
154
elementIndexOutOfBounds();
155
tableIndexOutOfBounds();
156
invalidDestinationOffset();
157
invalidSourceOffset();
158
invalidLength();
159
basicTest();
- a/JSTests/wasm/wasm.json -1 / +2 lines
Lines 69-77 a/JSTests/wasm/wasm.json_sec1
69
        "set_global":          { "category": "special",    "value":  36, "return": [],                               "parameter": ["any"],                        "immediate": [{"name": "global_index",   "type": "varuint32"}],                                             "description": "write a global variable" },
69
        "set_global":          { "category": "special",    "value":  36, "return": [],                               "parameter": ["any"],                        "immediate": [{"name": "global_index",   "type": "varuint32"}],                                             "description": "write a global variable" },
70
        "table.get":           { "category": "special",    "value":  37, "return": ["externref"],                    "parameter": ["i32"],                        "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "get a table value" },
70
        "table.get":           { "category": "special",    "value":  37, "return": ["externref"],                    "parameter": ["i32"],                        "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "get a table value" },
71
        "table.set":           { "category": "special",    "value":  38, "return": [],                               "parameter": ["i32", "externref"],           "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "set a table value" },
71
        "table.set":           { "category": "special",    "value":  38, "return": [],                               "parameter": ["i32", "externref"],           "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "set a table value" },
72
        "table.init":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": ["i32", "i32", "i32"],          "immediate": [{"name": "element_index",  "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "initialize table from given element", "extendedOp": 12 },
72
        "table.grow":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": ["externref", "i32"],           "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "grow a table by the given delta and return the previous size, or -1 if enough space cannot be allocated", "extendedOp": 15 },
73
        "table.grow":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": ["externref", "i32"],           "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "grow a table by the given delta and return the previous size, or -1 if enough space cannot be allocated", "extendedOp": 15 },
73
        "table.size":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": [],                             "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "get the size of a table", "extendedOp": 16 },
74
        "table.size":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": [],                             "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "get the size of a table", "extendedOp": 16 },
74
        "table.fill":           { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": ["i32", "externref", "i32"],    "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "fill entries [i,i+n) with the given value", "extendedOp": 17 },
75
        "table.fill":          { "category": "exttable",   "value":  252, "return": ["i32"],                         "parameter": ["i32", "externref", "i32"],    "immediate": [{"name": "table_index",    "type": "varuint32"}],                                             "description": "fill entries [i,i+n) with the given value", "extendedOp": 17 },
75
        "call":                { "category": "call",       "value":  16, "return": ["call"],                         "parameter": ["call"],                       "immediate": [{"name": "function_index", "type": "varuint32"}],                                             "description": "call a function by its index" },
76
        "call":                { "category": "call",       "value":  16, "return": ["call"],                         "parameter": ["call"],                       "immediate": [{"name": "function_index", "type": "varuint32"}],                                             "description": "call a function by its index" },
76
        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],                         "parameter": ["call"],                       "immediate": [{"name": "type_index",     "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "call a function indirect with an expected signature" },
77
        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],                         "parameter": ["call"],                       "immediate": [{"name": "type_index",     "type": "varuint32"}, {"name": "table_index","type": "varuint32"}],"description": "call a function indirect with an expected signature" },
77
        "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],                          "parameter": ["addr"],                       "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset",   "type": "varuint32"}], "description": "load from memory" },
78
        "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],                          "parameter": ["addr"],                       "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset",   "type": "varuint32"}], "description": "load from memory" },

Return to Bug 219297