Title: [209652] trunk
Revision
209652
Author
keith_mil...@apple.com
Date
2016-12-09 23:12:53 -0800 (Fri, 09 Dec 2016)

Log Message

Wasm should support call_indirect
https://bugs.webkit.org/show_bug.cgi?id=165718

Reviewed by Filip Pizlo.

JSTests:

* wasm/Builder.js:
* wasm/function-tests/call-indirect-params.js: Added.
* wasm/function-tests/call-indirect.js: Added.
* wasm/js-api/call-indirect.js: Added.
(const.wasmModuleWhichImportJS):
(MonomorphicImport):
(Polyphic2Import):
(VirtualImport):
* wasm/wasm.json:

Source/_javascript_Core:

This patch adds support for call_indirect. The basic framework for
an indirect call is that the module holds a buffer containing a
stub for each function in the index space. Whenever a function
needs to do an indirect call it gets a index into that table. In
order to ensure call_indirect is calling a valid function the
functionIndexSpace also needs a pointer to a canonicalized
signature. When making an indirect call, we first check the index
is in range, then check the signature matches the value we were given.

This patch also differentiates between FunctionIndexSpaces and
ImmutableFunctionIndexSpaces. Since we don't know the size of the
FunctionIndexSpace when we start parsing we need to be able to
resize the IndexSpace. However, once we have finished parsing all
the sections we want to prevent an relocation of the function
index space pointer.

* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::B3IRGenerator::B3IRGenerator):
(JSC::Wasm::B3IRGenerator::addCall):
(JSC::Wasm::B3IRGenerator::addCallIndirect):
(JSC::Wasm::createJSToWasmWrapper):
(JSC::Wasm::parseAndCompile):
* wasm/WasmB3IRGenerator.h:
* wasm/WasmCallingConvention.h:
(JSC::Wasm::CallingConvention::setupCall):
* wasm/WasmFormat.h:
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser::setErrorMessage):
(JSC::Wasm::FunctionParser<Context>::FunctionParser):
(JSC::Wasm::FunctionParser<Context>::parseExpression):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::run):
* wasm/WasmPlan.h:
(JSC::Wasm::Plan::takeFunctionIndexSpace):
* wasm/WasmValidate.cpp:
(JSC::Wasm::Validate::addCallIndirect):
(JSC::Wasm::validateFunction):
* wasm/WasmValidate.h:
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::create):
(JSC::JSWebAssemblyModule::JSWebAssemblyModule):
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::signatureForFunctionIndexSpace):
(JSC::JSWebAssemblyModule::offsetOfFunctionIndexSpace):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (209651 => 209652)


--- trunk/JSTests/ChangeLog	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/JSTests/ChangeLog	2016-12-10 07:12:53 UTC (rev 209652)
@@ -1,3 +1,20 @@
+2016-12-09  Keith Miller  <keith_mil...@apple.com>
+
+        Wasm should support call_indirect
+        https://bugs.webkit.org/show_bug.cgi?id=165718
+
+        Reviewed by Filip Pizlo.
+
+        * wasm/Builder.js:
+        * wasm/function-tests/call-indirect-params.js: Added.
+        * wasm/function-tests/call-indirect.js: Added.
+        * wasm/js-api/call-indirect.js: Added.
+        (const.wasmModuleWhichImportJS):
+        (MonomorphicImport):
+        (Polyphic2Import):
+        (VirtualImport):
+        * wasm/wasm.json:
+
 2016-12-09  JF Bastien  <jfbast...@apple.com>
 
         WebAssembly: implement data section

Modified: trunk/JSTests/wasm/Builder.js (209651 => 209652)


--- trunk/JSTests/wasm/Builder.js	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/JSTests/wasm/Builder.js	2016-12-10 07:12:53 UTC (rev 209652)
@@ -236,6 +236,7 @@
             break;
         case "target_count": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
         case "target_table": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
+        case "reserved": break; // improve checking https://bugs.webkit.org/show_bug.cgi?id=163421
         default: throw new Error(`Implementation problem: unhandled immediate "${expect.name}" on "${op}"`);
         }
     }

Added: trunk/JSTests/wasm/function-tests/call-indirect-params.js (0 => 209652)


--- trunk/JSTests/wasm/function-tests/call-indirect-params.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/call-indirect-params.js	2016-12-10 07:12:53 UTC (rev 209652)
@@ -0,0 +1,28 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+    .Function().End()
+    .Code()
+
+    .Function({ params: ["i32"], ret: "i32" })
+    .I32Const(1)
+    .End()
+
+    .Function({ params: ["i32"], ret: "i32" })
+    .GetLocal(0)
+    .End()
+
+    .Function({ params: ["i32", "i32"], ret: "i32" })
+    .GetLocal(1)
+    .GetLocal(0)
+    .CallIndirect(0, 0)
+    .End()
+
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 3, [], [],
+                        [[{ type: "i32", value: 1 }, [{ type: "i32", value: 0 }, { type: "i32", value: 4 }]],
+                         [{ type: "i32", value: 4 }, [{ type: "i32", value: 1 }, { type: "i32", value: 4 }]],
+                        ]);

Added: trunk/JSTests/wasm/function-tests/call-indirect.js (0 => 209652)


--- trunk/JSTests/wasm/function-tests/call-indirect.js	                        (rev 0)
+++ trunk/JSTests/wasm/function-tests/call-indirect.js	2016-12-10 07:12:53 UTC (rev 209652)
@@ -0,0 +1,27 @@
+import Builder from '../Builder.js'
+
+const b = new Builder();
+b.Type().End()
+    .Function().End()
+    .Code()
+
+    .Function({ params: [], ret: "i32" })
+    .I32Const(1)
+    .End()
+
+    .Function({ params: [], ret: "i32" })
+    .I32Const(2)
+    .End()
+
+    .Function({ params: ["i32"], ret: "i32" })
+    .GetLocal(0)
+    .CallIndirect(0, 0)
+    .End()
+
+
+const bin = b.WebAssembly()
+bin.trim();
+testWasmModuleFunctions(bin.get(), 3, [], [],
+                        [[{ type: "i32", value: 1 }, [{ type: "i32", value: 0 }]],
+                         [{ type: "i32", value: 1 }, [{ type: "i32", value: 0 }]],
+                        ]);

Added: trunk/JSTests/wasm/js-api/call-indirect.js (0 => 209652)


--- trunk/JSTests/wasm/js-api/call-indirect.js	                        (rev 0)
+++ trunk/JSTests/wasm/js-api/call-indirect.js	2016-12-10 07:12:53 UTC (rev 209652)
@@ -0,0 +1,87 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+const wasmModuleWhichImportJS = () => {
+    const builder = (new Builder())
+        .Type().End()
+        .Import()
+            .Function("imp", "func", { params: ["i32"] })
+        .End()
+        .Function().End()
+        .Export()
+            .Function("changeCounter")
+        .End()
+        .Code()
+            .Function("changeCounter", { params: ["i32", "i32"] })
+                .I32Const(42)
+                .GetLocal(0)
+                .I32Add()
+                .GetLocal(1)
+                .CallIndirect(0, 0) // Calls func(param[0] + 42).
+            .End()
+        .End();
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    return module;
+};
+
+
+(function MonomorphicImport() {
+    let counter = 0;
+    const counterSetter = v => counter = v;
+    const module = wasmModuleWhichImportJS();
+    const instance = new WebAssembly.Instance(module, { imp: { func: counterSetter } });
+    for (let i = 0; i < 4096; ++i) {
+        // Invoke this a bunch of times to make sure the IC in the wasm -> JS stub works correctly.
+        instance.exports.changeCounter(i, 0);
+        assert.eq(counter, i + 42);
+    }
+})();
+
+(function Polyphic2Import() {
+    let counterA = 0;
+    let counterB = undefined;
+    const counterASetter = v => counterA = v;
+    const counterBSetter = v => counterB = { valueB: v };
+    const module = wasmModuleWhichImportJS();
+    const instanceA = new WebAssembly.Instance(module, { imp: { func: counterASetter } });
+    const instanceB = new WebAssembly.Instance(module, { imp: { func: counterBSetter } });
+    for (let i = 0; i < 2048; ++i) {
+        instanceA.exports.changeCounter(i, 0);
+        assert.isA(counterA, "number");
+        assert.eq(counterA, i + 42);
+        instanceB.exports.changeCounter(i, 0);
+        assert.isA(counterB, "object");
+        assert.eq(counterB.valueB, i + 42);
+    }
+})();
+
+(function VirtualImport() {
+    const num = 10; // It's definitely going virtual at 10!
+    let counters = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+    const counterSetters = [
+        v => counters[0] = v,
+        v => counters[1] = v + 1,
+        v => counters[2] = v + 2,
+        v => counters[3] = v + 3,
+        v => counters[4] = v + 4,
+        v => counters[5] = v + 5,
+        v => counters[6] = v + 6,
+        v => counters[7] = v + 7,
+        v => counters[8] = v + 8,
+        v => counters[9] = v + 9,
+    ];
+    assert.eq(counters.length, num);
+    assert.eq(counterSetters.length, num);
+    const module = wasmModuleWhichImportJS();
+    let instances = [];
+    for (let i = 0; i < num; ++i)
+        instances[i] = new WebAssembly.Instance(module, { imp: { func: counterSetters[i] } });
+    for (let i = 0; i < 2048; ++i) {
+        for (let j = 0; j < num; ++j) {
+            instances[j].exports.changeCounter(i, 0);
+            assert.isA(counters[j], "number");
+            assert.eq(counters[j], i + 42 + j);
+        }
+    }
+})();

Modified: trunk/JSTests/wasm/wasm.json (209651 => 209652)


--- trunk/JSTests/wasm/wasm.json	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/JSTests/wasm/wasm.json	2016-12-10 07:12:53 UTC (rev 209652)
@@ -64,7 +64,7 @@
         "get_global":          { "category": "special",    "value":  35, "return": ["global"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
         "set_global":          { "category": "special",    "value":  36, "return": [""],         "parameter": ["global"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
         "call":                { "category": "call",       "value":  16, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                          "description": "call a function by its index" },
-        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}],                                          "description": "call a function indirect with an expected signature" },
+        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}, {"name": "reserved",     "type": "varuint1"}], "description": "call a function indirect with an expected signature" },
         "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
         "i32.load8_u":         { "category": "memory",     "value":  45, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
         "i32.load16_s":        { "category": "memory",     "value":  46, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },

Modified: trunk/Source/_javascript_Core/ChangeLog (209651 => 209652)


--- trunk/Source/_javascript_Core/ChangeLog	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-12-10 07:12:53 UTC (rev 209652)
@@ -1,3 +1,55 @@
+2016-12-09  Keith Miller  <keith_mil...@apple.com>
+
+        Wasm should support call_indirect
+        https://bugs.webkit.org/show_bug.cgi?id=165718
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds support for call_indirect. The basic framework for
+        an indirect call is that the module holds a buffer containing a
+        stub for each function in the index space. Whenever a function
+        needs to do an indirect call it gets a index into that table. In
+        order to ensure call_indirect is calling a valid function the
+        functionIndexSpace also needs a pointer to a canonicalized
+        signature. When making an indirect call, we first check the index
+        is in range, then check the signature matches the value we were given.
+
+        This patch also differentiates between FunctionIndexSpaces and
+        ImmutableFunctionIndexSpaces. Since we don't know the size of the
+        FunctionIndexSpace when we start parsing we need to be able to
+        resize the IndexSpace. However, once we have finished parsing all
+        the sections we want to prevent an relocation of the function
+        index space pointer.
+
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+        (JSC::Wasm::B3IRGenerator::addCall):
+        (JSC::Wasm::B3IRGenerator::addCallIndirect):
+        (JSC::Wasm::createJSToWasmWrapper):
+        (JSC::Wasm::parseAndCompile):
+        * wasm/WasmB3IRGenerator.h:
+        * wasm/WasmCallingConvention.h:
+        (JSC::Wasm::CallingConvention::setupCall):
+        * wasm/WasmFormat.h:
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser::setErrorMessage):
+        (JSC::Wasm::FunctionParser<Context>::FunctionParser):
+        (JSC::Wasm::FunctionParser<Context>::parseExpression):
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::run):
+        * wasm/WasmPlan.h:
+        (JSC::Wasm::Plan::takeFunctionIndexSpace):
+        * wasm/WasmValidate.cpp:
+        (JSC::Wasm::Validate::addCallIndirect):
+        (JSC::Wasm::validateFunction):
+        * wasm/WasmValidate.h:
+        * wasm/js/JSWebAssemblyModule.cpp:
+        (JSC::JSWebAssemblyModule::create):
+        (JSC::JSWebAssemblyModule::JSWebAssemblyModule):
+        * wasm/js/JSWebAssemblyModule.h:
+        (JSC::JSWebAssemblyModule::signatureForFunctionIndexSpace):
+        (JSC::JSWebAssemblyModule::offsetOfFunctionIndexSpace):
+
 2016-12-09  JF Bastien  <jfbast...@apple.com>
 
         WebAssembly: implement data section

Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2016-12-10 07:12:53 UTC (rev 209652)
@@ -40,6 +40,8 @@
 #include "B3VariableValue.h"
 #include "B3WasmAddressValue.h"
 #include "B3WasmBoundsCheckValue.h"
+#include "JSWebAssemblyInstance.h"
+#include "JSWebAssemblyModule.h"
 #include "VirtualRegister.h"
 #include "WasmCallingConvention.h"
 #include "WasmFunctionParser.h"
@@ -130,7 +132,7 @@
 
     static constexpr ExpressionType emptyExpression = nullptr;
 
-    B3IRGenerator(MemoryInformation&, Procedure&, WasmInternalFunction*, Vector<UnlinkedWasmToWasmCall>&);
+    B3IRGenerator(const MemoryInformation&, Procedure&, WasmInternalFunction*, Vector<UnlinkedWasmToWasmCall>&, const ImmutableFunctionIndexSpace&);
 
     bool WARN_UNUSED_RETURN addArguments(const Vector<Type>&);
     bool WARN_UNUSED_RETURN addLocal(Type, uint32_t);
@@ -164,7 +166,9 @@
     bool WARN_UNUSED_RETURN endBlock(ControlEntry&, ExpressionList& expressionStack);
     bool WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&);
 
-    bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const Signature*, Vector<ExpressionType>& args, ExpressionType& result);
+    // Calls
+    bool WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature*, Vector<ExpressionType>& args, ExpressionType& result);
+    bool WARN_UNUSED_RETURN addCallIndirect(const Signature*, Vector<ExpressionType>& args, ExpressionType& result);
 
     void dump(const Vector<ControlEntry>& controlStack, const ExpressionList& expressionStack);
 
@@ -179,6 +183,7 @@
     void unifyValuesWithBlock(const ExpressionList& resultStack, ResultList& stack);
     Value* zeroForType(Type);
 
+    const ImmutableFunctionIndexSpace& m_functionIndexSpace;
     Procedure& m_proc;
     BasicBlock* m_currentBlock;
     Vector<Variable*> m_locals;
@@ -186,10 +191,12 @@
     GPRReg m_memoryBaseGPR;
     GPRReg m_memorySizeGPR;
     Value* m_zeroValues[numTypes];
+    Value* m_functionIndexSpaceValue;
 };
 
-B3IRGenerator::B3IRGenerator(MemoryInformation& memory, Procedure& procedure, WasmInternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls)
-    : m_proc(procedure)
+B3IRGenerator::B3IRGenerator(const MemoryInformation& memory, Procedure& procedure, WasmInternalFunction* compilation, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace& functionIndexSpace)
+    : m_functionIndexSpace(functionIndexSpace)
+    , m_proc(procedure)
     , m_unlinkedWasmToWasmCalls(unlinkedWasmToWasmCalls)
 {
     m_currentBlock = m_proc.addBlock();
@@ -224,6 +231,8 @@
     }
 
     wasmCallingConvention().setupFrameInPrologue(compilation, m_proc, Origin(), m_currentBlock);
+
+    m_functionIndexSpaceValue = m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), functionIndexSpace.buffer.get());
 }
 
 Value* B3IRGenerator::zeroForType(Type type)
@@ -592,7 +601,7 @@
     return true;
 }
 
-bool B3IRGenerator::addCall(unsigned functionIndex, const Signature* signature, Vector<ExpressionType>& args, ExpressionType& result)
+bool B3IRGenerator::addCall(uint32_t functionIndex, const Signature* signature, Vector<ExpressionType>& args, ExpressionType& result)
 {
     ASSERT(signature->arguments.size() == args.size());
 
@@ -618,6 +627,57 @@
     return true;
 }
 
+bool B3IRGenerator::addCallIndirect(const Signature* signature, Vector<ExpressionType>& args, ExpressionType& result)
+{
+    ExpressionType calleeIndex = args.takeLast();
+    ASSERT(signature->arguments.size() == args.size());
+
+    // Check the index we are looking for is valid.
+    {
+        ExpressionType maxValidIndex = m_currentBlock->appendIntConstant(m_proc, Origin(), Int32, m_functionIndexSpace.size);
+        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(),
+            m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(), m_zeroValues[linearizeType(I32)],
+                m_currentBlock->appendNew<Value>(m_proc, LessThan, Origin(), calleeIndex, maxValidIndex)));
+
+        check->setGenerator([] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+            jit.breakpoint();
+        });
+    }
+
+    // Compute the offset in the function index space we are looking for.
+    ExpressionType offset = m_currentBlock->appendNew<Value>(m_proc, Mul, Origin(),
+        m_currentBlock->appendNew<Value>(m_proc, ZExt32, Origin(), calleeIndex),
+        m_currentBlock->appendIntConstant(m_proc, Origin(), pointerType(), sizeof(CallableFunction)));
+    ExpressionType callableFunction = m_currentBlock->appendNew<Value>(m_proc, Add, Origin(), m_functionIndexSpaceValue, offset);
+
+    // Check the signature matches the value we expect.
+    {
+        ExpressionType calleeSignature = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(), callableFunction, OBJECT_OFFSETOF(CallableFunction, signature));
+        ExpressionType expectedSignature = m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), signature);
+        CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(),
+            m_currentBlock->appendNew<Value>(m_proc, NotEqual, Origin(), calleeSignature, expectedSignature));
+
+        check->setGenerator([] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+            jit.breakpoint();
+        });
+    }
+
+    ExpressionType calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(), callableFunction, OBJECT_OFFSETOF(CallableFunction, code));
+
+    result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(signature->returnType),
+        [&] (PatchpointValue* patchpoint) {
+            patchpoint->effects.writesPinned = true;
+            patchpoint->effects.readsPinned = true;
+
+            patchpoint->append(calleeCode, ValueRep::SomeRegister);
+
+            patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
+                jit.call(params[0].gpr());
+            });
+        });
+    return true;
+}
+
 void B3IRGenerator::unify(Variable* variable, ExpressionType source)
 {
     m_currentBlock->appendNew<VariableValue>(m_proc, Set, Origin(), variable, source);
@@ -657,7 +717,7 @@
     dataLogLn("\n");
 }
 
-static std::unique_ptr<Compilation> createJSToWasmWrapper(VM& vm, const Signature* signature, MacroAssemblerCodePtr mainFunction, MemoryInformation& memory)
+static std::unique_ptr<Compilation> createJSToWasmWrapper(VM& vm, const Signature* signature, MacroAssemblerCodePtr mainFunction, const MemoryInformation& memory)
 {
     Procedure proc;
     BasicBlock* block = proc.addBlock();
@@ -737,13 +797,13 @@
     return std::make_unique<Compilation>(vm, proc);
 }
 
-std::unique_ptr<WasmInternalFunction> parseAndCompile(VM& vm, const uint8_t* functionStart, size_t functionLength, MemoryInformation& memory, const Signature* signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const FunctionIndexSpace& functionIndexSpace, unsigned optLevel)
+std::unique_ptr<WasmInternalFunction> parseAndCompile(VM& vm, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& info, unsigned optLevel)
 {
     auto result = std::make_unique<WasmInternalFunction>();
 
     Procedure procedure;
-    B3IRGenerator context(memory, procedure, result.get(), unlinkedWasmToWasmCalls);
-    FunctionParser<B3IRGenerator> parser(context, functionStart, functionLength, signature, functionIndexSpace);
+    B3IRGenerator context(info.memory, procedure, result.get(), unlinkedWasmToWasmCalls, functionIndexSpace);
+    FunctionParser<B3IRGenerator> parser(context, functionStart, functionLength, signature, functionIndexSpace, info);
     if (!parser.parse())
         RELEASE_ASSERT_NOT_REACHED();
 
@@ -757,7 +817,7 @@
         dataLog("Post SSA: ", procedure);
 
     result->code = std::make_unique<Compilation>(vm, procedure, optLevel);
-    result->jsToWasmEntryPoint = createJSToWasmWrapper(vm, signature, result->code->code(), memory);
+    result->jsToWasmEntryPoint = createJSToWasmWrapper(vm, signature, result->code->code(), info.memory);
     return result;
 }
 

Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.h (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.h	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.h	2016-12-10 07:12:53 UTC (rev 209652)
@@ -37,7 +37,7 @@
 
 class MemoryInformation;
 
-std::unique_ptr<WasmInternalFunction> parseAndCompile(VM&, const uint8_t*, size_t, MemoryInformation&, const Signature*, Vector<UnlinkedWasmToWasmCall>&, const FunctionIndexSpace&, unsigned optLevel = 1);
+std::unique_ptr<WasmInternalFunction> parseAndCompile(VM&, const uint8_t*, size_t, const Signature*, Vector<UnlinkedWasmToWasmCall>&, const ImmutableFunctionIndexSpace&, const ModuleInformation&, unsigned optLevel = 1);
 
 } } // namespace JSC::Wasm
 

Modified: trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h	2016-12-10 07:12:53 UTC (rev 209652)
@@ -163,8 +163,8 @@
         B3::PatchpointValue* patchpoint = block->appendNew<B3::PatchpointValue>(proc, returnType, origin);
         patchpoint->clobberEarly(RegisterSet::macroScratchRegisters());
         patchpoint->clobberLate(RegisterSet::volatileRegistersForJSCall());
+        patchpointFunctor(patchpoint);
         patchpoint->appendVector(constrainedArguments);
-        patchpointFunctor(patchpoint);
 
         switch (returnType) {
         case B3::Void:

Modified: trunk/Source/_javascript_Core/wasm/WasmFormat.h (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/WasmFormat.h	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/WasmFormat.h	2016-12-10 07:12:53 UTC (rev 209652)
@@ -187,6 +187,12 @@
 };
 typedef Vector<CallableFunction> FunctionIndexSpace;
 
+
+struct ImmutableFunctionIndexSpace {
+    MallocPtr<CallableFunction> buffer;
+    size_t size;
+};
+
 } } // namespace JSC::Wasm
 
 #endif // ENABLE(WEBASSEMBLY)

Modified: trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/WasmFunctionParser.h	2016-12-10 07:12:53 UTC (rev 209652)
@@ -45,7 +45,7 @@
     typedef typename Context::ControlType ControlType;
     typedef typename Context::ExpressionList ExpressionList;
 
-    FunctionParser(Context&, const uint8_t* functionStart, size_t functionLength, const Signature*, const FunctionIndexSpace&);
+    FunctionParser(Context&, const uint8_t* functionStart, size_t functionLength, const Signature*, const ImmutableFunctionIndexSpace&, const ModuleInformation&);
 
     bool WARN_UNUSED_RETURN parse();
 
@@ -71,22 +71,28 @@
     template<OpType>
     bool WARN_UNUSED_RETURN binaryCase();
 
-    void setErrorMessage(String&& message) { m_context.setErrorMessage(WTFMove(message)); }
+    bool setErrorMessage(String&& message)
+    {
+        m_context.setErrorMessage(WTFMove(message));
+        return false;
+    }
 
     Context& m_context;
     ExpressionList m_expressionStack;
     Vector<ControlEntry> m_controlStack;
     const Signature* m_signature;
-    const FunctionIndexSpace& m_functionIndexSpace;
+    const ImmutableFunctionIndexSpace& m_functionIndexSpace;
+    const ModuleInformation& m_info;
     unsigned m_unreachableBlocks { 0 };
 };
 
 template<typename Context>
-FunctionParser<Context>::FunctionParser(Context& context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const FunctionIndexSpace& functionIndexSpace)
+FunctionParser<Context>::FunctionParser(Context& context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& info)
     : Parser(functionStart, functionLength)
     , m_context(context)
     , m_signature(signature)
     , m_functionIndexSpace(functionIndexSpace)
+    , m_info(info)
 {
     if (verbose)
         dataLogLn("Parsing function starting at: ", (uintptr_t)functionStart, " of length: ", functionLength);
@@ -350,10 +356,10 @@
         if (!parseVarUInt32(functionIndex))
             return false;
 
-        if (functionIndex >= m_functionIndexSpace.size())
+        if (functionIndex >= m_functionIndexSpace.size)
             return false;
 
-        const Signature* calleeSignature = m_functionIndexSpace[functionIndex].signature;
+        const Signature* calleeSignature = m_functionIndexSpace.buffer.get()[functionIndex].signature;
 
         if (calleeSignature->arguments.size() > m_expressionStack.size())
             return false;
@@ -375,6 +381,42 @@
         return true;
     }
 
+    case OpType::CallIndirect: {
+        uint32_t signatureIndex;
+        if (!parseVarUInt32(signatureIndex))
+            return false;
+
+        uint8_t reserved;
+        if (!parseVarUInt1(reserved))
+            return false;
+
+        if (m_info.signatures.size() <= signatureIndex)
+            return setErrorMessage("Tried to use a signature outside the range of valid signatures");
+
+        const Signature* calleeSignature = &m_info.signatures[signatureIndex];
+        size_t argumentCount = calleeSignature->arguments.size() + 1; // Add the callee's index.
+        if (argumentCount > m_expressionStack.size())
+            return setErrorMessage("Not enough values on the stack for call_indirect");
+
+        Vector<ExpressionType> args;
+        if (!args.tryReserveCapacity(argumentCount))
+            return setErrorMessage("Out of memory");
+
+        size_t firstArgumentIndex = m_expressionStack.size() - argumentCount;
+        for (unsigned i = firstArgumentIndex; i < m_expressionStack.size(); ++i)
+            args.uncheckedAppend(m_expressionStack[i]);
+        m_expressionStack.shrink(firstArgumentIndex);
+
+        ExpressionType result = Context::emptyExpression;
+        if (!m_context.addCallIndirect(calleeSignature, args, result))
+            return false;
+
+        if (result != Context::emptyExpression)
+            m_expressionStack.append(result);
+
+        return true;
+    }
+
     case OpType::Block: {
         Type inlineSignature;
         if (!parseResultType(inlineSignature))
@@ -517,8 +559,7 @@
     case OpType::GrowMemory:
     case OpType::CurrentMemory:
     case OpType::GetGlobal:
-    case OpType::SetGlobal:
-    case OpType::CallIndirect: {
+    case OpType::SetGlobal: {
         // FIXME: Not yet implemented.
         return false;
     }

Modified: trunk/Source/_javascript_Core/wasm/WasmPlan.cpp (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/WasmPlan.cpp	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/WasmPlan.cpp	2016-12-10 07:12:53 UTC (rev 209652)
@@ -72,7 +72,8 @@
         }
         m_moduleInformation = WTFMove(moduleParser.moduleInformation());
         m_functionLocationInBinary = WTFMove(moduleParser.functionLocationInBinary());
-        m_functionIndexSpace = WTFMove(moduleParser.functionIndexSpace());
+        m_functionIndexSpace.size = moduleParser.functionIndexSpace().size();
+        m_functionIndexSpace.buffer = moduleParser.functionIndexSpace().releaseBuffer();
     }
     if (verbose)
         dataLogLn("Parsed module.");
@@ -103,7 +104,7 @@
             dataLogLn("Processing import function number ", importFunctionIndex, ": ", import->module, ": ", import->field);
         Signature* signature = m_moduleInformation->importFunctions.at(import->kindIndex);
         m_wasmToJSStubs.uncheckedAppend(importStubGenerator(m_vm, m_callLinkInfos, signature, importFunctionIndex));
-        m_functionIndexSpace[importFunctionIndex].code = m_wasmToJSStubs[importFunctionIndex].code().executableAddress();
+        m_functionIndexSpace.buffer.get()[importFunctionIndex].code = m_wasmToJSStubs[importFunctionIndex].code().executableAddress();
     }
 
     for (unsigned functionIndex = 0; functionIndex < m_functionLocationInBinary.size(); ++functionIndex) {
@@ -114,9 +115,9 @@
         ASSERT(functionLength <= m_sourceLength);
         Signature* signature = m_moduleInformation->internalFunctionSignatures[functionIndex];
         unsigned functionIndexSpace = m_wasmToJSStubs.size() + functionIndex;
-        ASSERT(m_functionIndexSpace[functionIndexSpace].signature == signature);
+        ASSERT(m_functionIndexSpace.buffer.get()[functionIndexSpace].signature == signature);
 
-        String error = validateFunction(functionStart, functionLength, signature, m_functionIndexSpace, m_moduleInformation->memory);
+        String error = validateFunction(functionStart, functionLength, signature, m_functionIndexSpace, *m_moduleInformation);
         if (!error.isNull()) {
             if (verbose) {
                 for (unsigned i = 0; i < functionLength; ++i)
@@ -128,14 +129,14 @@
         }
 
         unlinkedWasmToWasmCalls.uncheckedAppend(Vector<UnlinkedWasmToWasmCall>());
-        m_wasmInternalFunctions.uncheckedAppend(parseAndCompile(*m_vm, functionStart, functionLength, m_moduleInformation->memory, signature, unlinkedWasmToWasmCalls.at(functionIndex), m_functionIndexSpace));
-        m_functionIndexSpace[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]->code->code().executableAddress();
+        m_wasmInternalFunctions.uncheckedAppend(parseAndCompile(*m_vm, functionStart, functionLength, signature, unlinkedWasmToWasmCalls.at(functionIndex), m_functionIndexSpace, *m_moduleInformation));
+        m_functionIndexSpace.buffer.get()[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]->code->code().executableAddress();
     }
 
     // Patch the call sites for each WebAssembly function.
     for (auto& unlinked : unlinkedWasmToWasmCalls) {
         for (auto& call : unlinked)
-            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_functionIndexSpace[call.functionIndex].code));
+            MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_functionIndexSpace.buffer.get()[call.functionIndex].code));
     }
 
     m_failed = false;

Modified: trunk/Source/_javascript_Core/wasm/WasmPlan.h (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/WasmPlan.h	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/WasmPlan.h	2016-12-10 07:12:53 UTC (rev 209652)
@@ -95,7 +95,7 @@
         return WTFMove(m_wasmToJSStubs);
     }
 
-    FunctionIndexSpace&& takeFunctionIndexSpace()
+    ImmutableFunctionIndexSpace&& takeFunctionIndexSpace()
     {
         RELEASE_ASSERT(!failed());
         return WTFMove(m_functionIndexSpace);
@@ -107,7 +107,7 @@
     Bag<CallLinkInfo> m_callLinkInfos;
     Vector<WasmToJSStub> m_wasmToJSStubs;
     Vector<std::unique_ptr<WasmInternalFunction>> m_wasmInternalFunctions;
-    FunctionIndexSpace m_functionIndexSpace;
+    ImmutableFunctionIndexSpace m_functionIndexSpace;
 
     VM* m_vm;
     const uint8_t* m_source;

Modified: trunk/Source/_javascript_Core/wasm/WasmValidate.cpp (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/WasmValidate.cpp	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/WasmValidate.cpp	2016-12-10 07:12:53 UTC (rev 209652)
@@ -110,8 +110,9 @@
     bool WARN_UNUSED_RETURN endBlock(ControlEntry&, ExpressionList& expressionStack);
     bool WARN_UNUSED_RETURN addEndToUnreachable(ControlEntry&);
 
-
+    // Calls
     bool WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const Signature*, const Vector<ExpressionType>& args, ExpressionType& result);
+    bool WARN_UNUSED_RETURN addCallIndirect(const Signature*, const Vector<ExpressionType>& args, ExpressionType& result);
 
     void dump(const Vector<ControlEntry>& controlStack, const ExpressionList& expressionStack);
 
@@ -347,6 +348,35 @@
     return true;
 }
 
+bool Validate::addCallIndirect(const Signature* signature, const Vector<ExpressionType>& args, ExpressionType& result)
+{
+    const auto argumentCount = signature->arguments.size();
+    if (argumentCount != args.size() - 1) {
+        StringBuilder builder;
+        builder.append("Arity mismatch in call_indirect, expected: ");
+        builder.appendNumber(signature->arguments.size());
+        builder.append(" but got: ");
+        builder.appendNumber(args.size());
+        m_errorMessage = builder.toString();
+        return false;
+    }
+
+    for (unsigned i = 0; i < argumentCount; ++i) {
+        if (args[i] != signature->arguments[i]) {
+            m_errorMessage = makeString("Expected argument type: ", toString(signature->arguments[i]), " does not match passed argument type: ", toString(args[i]));
+            return false;
+        }
+    }
+
+    if (args.last() != I32) {
+        m_errorMessage = makeString("Expected call_indirect target index to have type: i32 but got type: ", toString(args.last()));
+        return false;
+    }
+    
+    result = signature->returnType;
+    return true;
+}
+
 bool Validate::unify(const ExpressionList& values, const ControlType& block)
 {
     ASSERT(values.size() <= 1);
@@ -371,10 +401,11 @@
     // Think of this as penance for the sin of bad error messages.
 }
 
-String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const FunctionIndexSpace& functionIndexSpace, const MemoryInformation& memory)
+String validateFunction(const uint8_t* source, size_t length, const Signature* signature, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& info)
 {
-    Validate context(signature->returnType, memory);
-    FunctionParser<Validate> validator(context, source, length, signature, functionIndexSpace);
+    Validate context(signature->returnType, info.memory);
+    FunctionParser<Validate> validator(context, source, length, signature, functionIndexSpace, info);
+
     if (!validator.parse()) {
         // FIXME: add better location information here. see: https://bugs.webkit.org/show_bug.cgi?id=164288
         // FIXME: We should never not have an error message if we return false.

Modified: trunk/Source/_javascript_Core/wasm/WasmValidate.h (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/WasmValidate.h	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/WasmValidate.h	2016-12-10 07:12:53 UTC (rev 209652)
@@ -31,7 +31,7 @@
 
 namespace JSC { namespace Wasm {
 
-String validateFunction(const uint8_t*, size_t, const Signature*, const FunctionIndexSpace&, const MemoryInformation&);
+String validateFunction(const uint8_t*, size_t, const Signature*, const ImmutableFunctionIndexSpace&, const ModuleInformation&);
 
 } } // namespace JSC::Wasm
 

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.cpp	2016-12-10 07:12:53 UTC (rev 209652)
@@ -38,9 +38,9 @@
 
 const ClassInfo JSWebAssemblyModule::s_info = { "WebAssembly.Module", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
 
-JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>&& moduleInformation, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmToJSStub>&& wasmToJSStubs, Wasm::FunctionIndexSpace&& functionIndexSpace, SymbolTable* exportSymbolTable, unsigned calleeCount)
+JSWebAssemblyModule* JSWebAssemblyModule::create(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>&& moduleInformation, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmToJSStub>&& wasmToJSStubs, Wasm::ImmutableFunctionIndexSpace&& functionIndexSpace, SymbolTable* exportSymbolTable, unsigned calleeCount)
 {
-    auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap, allocationSize(calleeCount))) JSWebAssemblyModule(vm, structure, std::forward<std::unique_ptr<Wasm::ModuleInformation>>(moduleInformation), std::forward<Bag<CallLinkInfo>>(callLinkInfos), std::forward<Vector<Wasm::WasmToJSStub>>(wasmToJSStubs), std::forward<Wasm::FunctionIndexSpace>(functionIndexSpace), calleeCount);
+    auto* instance = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap, allocationSize(calleeCount))) JSWebAssemblyModule(vm, structure, std::forward<std::unique_ptr<Wasm::ModuleInformation>>(moduleInformation), std::forward<Bag<CallLinkInfo>>(callLinkInfos), std::forward<Vector<Wasm::WasmToJSStub>>(wasmToJSStubs), std::forward<Wasm::ImmutableFunctionIndexSpace>(functionIndexSpace), calleeCount);
     instance->finishCreation(vm, exportSymbolTable);
     return instance;
 }
@@ -50,7 +50,7 @@
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>&& moduleInformation, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmToJSStub>&& wasmToJSStubs, Wasm::FunctionIndexSpace&& functionIndexSpace, unsigned calleeCount)
+JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, std::unique_ptr<Wasm::ModuleInformation>&& moduleInformation, Bag<CallLinkInfo>&& callLinkInfos, Vector<Wasm::WasmToJSStub>&& wasmToJSStubs, Wasm::ImmutableFunctionIndexSpace&& functionIndexSpace, unsigned calleeCount)
     : Base(vm, structure)
     , m_moduleInformation(WTFMove(moduleInformation))
     , m_callLinkInfos(WTFMove(callLinkInfos))

Modified: trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h	2016-12-10 07:12:53 UTC (rev 209652)
@@ -42,7 +42,7 @@
 public:
     typedef JSDestructibleObject Base;
 
-    static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmToJSStub>&&, Wasm::FunctionIndexSpace&&, SymbolTable*, unsigned);
+    static JSWebAssemblyModule* create(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmToJSStub>&&, Wasm::ImmutableFunctionIndexSpace&&, SymbolTable*, unsigned);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_INFO;
@@ -49,7 +49,7 @@
 
     const Wasm::ModuleInformation& moduleInformation() const { return *m_moduleInformation.get(); }
     SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); }
-    Wasm::Signature* signatureForFunctionIndexSpace(unsigned functionIndexSpace) const { return m_functionIndexSpace.at(functionIndexSpace).signature; }
+    Wasm::Signature* signatureForFunctionIndexSpace(unsigned functionIndexSpace) const { ASSERT(functionIndexSpace < m_functionIndexSpace.size); return m_functionIndexSpace.buffer.get()[functionIndexSpace].signature; }
     unsigned importCount() const { return m_wasmToJSStubs.size(); }
 
     JSWebAssemblyCallee* calleeFromFunctionIndexSpace(unsigned functionIndexSpace)
@@ -65,8 +65,10 @@
         return bitwise_cast<WriteBarrier<JSWebAssemblyCallee>*>(bitwise_cast<char*>(this) + offsetOfCallees());
     }
 
+    static ptrdiff_t offsetOfFunctionIndexSpace() { return OBJECT_OFFSETOF(JSWebAssemblyModule, m_functionIndexSpace); }
+
 protected:
-    JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmToJSStub>&&, Wasm::FunctionIndexSpace&&, unsigned calleeCount);
+    JSWebAssemblyModule(VM&, Structure*, std::unique_ptr<Wasm::ModuleInformation>&&, Bag<CallLinkInfo>&&, Vector<Wasm::WasmToJSStub>&&, Wasm::ImmutableFunctionIndexSpace&&, unsigned calleeCount);
     void finishCreation(VM&, SymbolTable*);
     static void destroy(JSCell*);
     static void visitChildren(JSCell*, SlotVisitor&);
@@ -86,7 +88,7 @@
     Bag<CallLinkInfo> m_callLinkInfos;
     WriteBarrier<SymbolTable> m_exportSymbolTable;
     Vector<Wasm::WasmToJSStub> m_wasmToJSStubs;
-    Wasm::FunctionIndexSpace m_functionIndexSpace;
+    const Wasm::ImmutableFunctionIndexSpace m_functionIndexSpace;
     unsigned m_calleeCount;
 };
 

Modified: trunk/Source/_javascript_Core/wasm/wasm.json (209651 => 209652)


--- trunk/Source/_javascript_Core/wasm/wasm.json	2016-12-10 07:08:31 UTC (rev 209651)
+++ trunk/Source/_javascript_Core/wasm/wasm.json	2016-12-10 07:12:53 UTC (rev 209652)
@@ -64,7 +64,7 @@
         "get_global":          { "category": "special",    "value":  35, "return": ["global"],   "parameter": [],                       "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "read a global variable" },
         "set_global":          { "category": "special",    "value":  36, "return": [""],         "parameter": ["global"],               "immediate": [{"name": "global_index",   "type": "varuint32"}],                                          "description": "write a global variable" },
         "call":                { "category": "call",       "value":  16, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "function_index", "type": "varuint32"}],                                          "description": "call a function by its index" },
-        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}],                                          "description": "call a function indirect with an expected signature" },
+        "call_indirect":       { "category": "call",       "value":  17, "return": ["call"],     "parameter": ["call"],                 "immediate": [{"name": "type_index",     "type": "varuint32"}, {"name": "reserved",     "type": "varuint1"}], "description": "call a function indirect with an expected signature" },
         "i32.load8_s":         { "category": "memory",     "value":  44, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
         "i32.load8_u":         { "category": "memory",     "value":  45, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
         "i32.load16_s":        { "category": "memory",     "value":  46, "return": ["i32"],      "parameter": ["addr"],                 "immediate": [{"name": "flags",          "type": "varuint32"}, {"name": "offset", "type": "varuint32"}], "description": "load from memory" },
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to