Title: [210402] branches/safari-603-branch
Revision
210402
Author
matthew_han...@apple.com
Date
2017-01-05 17:47:27 -0800 (Thu, 05 Jan 2017)

Log Message

Merge r210026. rdar://problem/29735737

Modified Paths

Added Paths

Diff

Modified: branches/safari-603-branch/JSTests/ChangeLog (210401 => 210402)


--- branches/safari-603-branch/JSTests/ChangeLog	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/JSTests/ChangeLog	2017-01-06 01:47:27 UTC (rev 210402)
@@ -1,5 +1,24 @@
 2017-01-05  Matthew Hanson  <matthew_han...@apple.com>
 
+        Merge r210026. rdar://problem/29735737
+
+    2016-12-20  JF Bastien  <jfbast...@apple.com>
+
+            WebAssembly: unique function signatures
+            https://bugs.webkit.org/show_bug.cgi?id=165957
+            <rdar://problem/29735737>
+
+            Reviewed by Saam Barati.
+
+            * wasm/function-tests/table-basic.js: FIXME is now addressed,
+            though instance to instance calls still need work which bug
+            #165282 will address
+            (i.assert.eq.foo):
+            * wasm/js-api/unique-signature.js: Added.
+            (CallIndirectWithDuplicateSignatures):
+
+2017-01-05  Matthew Hanson  <matthew_han...@apple.com>
+
         Merge r209979. rdar://problem/29735737
 
     2016-12-18  Saam Barati  <sbar...@apple.com>

Modified: branches/safari-603-branch/JSTests/wasm/function-tests/table-basic.js (210401 => 210402)


--- branches/safari-603-branch/JSTests/wasm/function-tests/table-basic.js	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/JSTests/wasm/function-tests/table-basic.js	2017-01-06 01:47:27 UTC (rev 210402)
@@ -44,21 +44,15 @@
     table.set(0, exports.bar);
     assert.eq(table.get(0), exports.bar);
 
-    for (let i = 0; i < 1000; i++) {
-        if (foo(0, i) !== i + 42)
-            throw new Error("Bad call indirect");
-    }
+    for (let i = 0; i < 1000; i++)
+        assert.eq(foo(0, i), i + 42, "call_indirect");
 }
 
-// FIXME: make this work cross module. The reason it doesn't
-// now is that we don't unique Signature*.
-// https://bugs.webkit.org/show_bug.cgi?id=165511
 {
     const {instance, table} = makeInstance();
     const foo = instance.exports.foo;
     table.set(0, makeInstance().instance.exports.bar); // Cross instance function.
 
-    for (let i = 0; i < 1000; i++) {
-        assert.throws(() => foo(0, i), WebAssembly.RuntimeError, "call_indirect to a signature that does not match");
-    }
+    for (let i = 0; i < 1000; i++)
+        assert.eq(foo(0, i), i + 42, "call_indirect");
 }

Added: branches/safari-603-branch/JSTests/wasm/js-api/unique-signature.js (0 => 210402)


--- branches/safari-603-branch/JSTests/wasm/js-api/unique-signature.js	                        (rev 0)
+++ branches/safari-603-branch/JSTests/wasm/js-api/unique-signature.js	2017-01-06 01:47:27 UTC (rev 210402)
@@ -0,0 +1,49 @@
+import * as assert from '../assert.js';
+import Builder from '../Builder.js';
+
+(function CallIndirectWithDuplicateSignatures() {
+    const builder = (new Builder())
+        .Type()
+            .Func(["i32"], "i32")         // 0
+            .Func(["i32"], "i32")         // 1
+            .Func(["i32", "i32"], "i32")  // 2
+            .Func(["i32"], "i32")         // 3
+            .Func(["i32"], "i32")         // 4
+            .Func(["i32", "i32"], "i32")  // 5
+            .Func(["f64", "f64"], "f64")  // 6
+            .Func(["i32"], "f64")         // 7
+            .Func(["i32"], "f64")         // 8
+        .End()
+        .Function().End()
+        .Table()
+            .Table({initial: 4, maximum: 4, element: "anyfunc"})
+        .End()
+        .Export()
+            .Function("entry")
+            .Table("table", 0)
+            .Function("callMe")
+        .End()
+        .Code()
+            .Function("entry", 1)
+                .I32Const(42)
+                .GetLocal(0)
+                .I32Add()
+                .I32Const(0) // Function index 0.
+                .CallIndirect(4, 0) // Different signature index, but same signature.
+                .Return()
+            .End()
+            .Function("callMe", 3)
+                .I32Const(3)
+                .GetLocal(0)
+                .I32Add()
+                .Return()
+            .End()
+        .End();
+    const bin = builder.WebAssembly().get();
+    const module = new WebAssembly.Module(bin);
+    let value0 = undefined;
+    const instance = new WebAssembly.Instance(module);
+    let table = instance.exports.table;
+    table.set(0, instance.exports.callMe);
+    assert.eq(instance.exports.entry(5), 5 + 42 + 3);
+}());

Modified: branches/safari-603-branch/Source/_javascript_Core/CMakeLists.txt (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/CMakeLists.txt	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/CMakeLists.txt	2017-01-06 01:47:27 UTC (rev 210402)
@@ -907,6 +907,7 @@
     wasm/WasmMemoryInformation.cpp
     wasm/WasmModuleParser.cpp
     wasm/WasmPlan.cpp
+    wasm/WasmSignature.cpp
     wasm/WasmValidate.cpp
 
     wasm/js/JSWebAssemblyCallee.cpp

Modified: branches/safari-603-branch/Source/_javascript_Core/ChangeLog (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/ChangeLog	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/ChangeLog	2017-01-06 01:47:27 UTC (rev 210402)
@@ -1,5 +1,124 @@
 2017-01-05  Matthew Hanson  <matthew_han...@apple.com>
 
+        Merge r210026. rdar://problem/29735737
+
+    2016-12-20  JF Bastien  <jfbast...@apple.com>
+
+            WebAssembly: unique function signatures
+            https://bugs.webkit.org/show_bug.cgi?id=165957
+            <rdar://problem/29735737>
+
+            Reviewed by Saam Barati.
+
+            Signatures in a Module's Type section can be duplicated, we
+            therefore need to unique them so that call_indirect only needs to
+            do a single integer compare to check that a callee's Signature is
+            the same as the Signature declared at the call site. Without
+            uniquing we'd either trap when duplicate Signatures are used, or
+            we'd need to do multiple comparisons. This patch makes that narrow
+            usecase function correctly.
+
+            There's further complication when calling from wasm to
+            wasm, in which case the Signatures must also match. Such
+            cross-instance calls will be improved in bug #165282, but this
+            patch sets the groundwork for it:
+
+            - Signatures are now owned by SignatureInformation which lives on
+              VM, and is shared by all Modules.
+            - When parsing a Module, a Signature is created for every Type
+              entry, and then uniqued by SignatureInformation's adopt
+              method. Duplicate Signatures are dropped and the previous
+              SignatureIndex is returned, new Signatures are adopted and a new
+              SignatureIndex is created.
+            - The SignatureIndex values are monotonic. 0 is used to represent
+              invalid indices, which trap. This can only occur through Table.
+            - SignatureInformation is used while generating code to map a
+              SignatureIndex back to the Signature* when return / argument
+              information is needed. This is a simple lookup into a Vector. It
+              isn't used at runtime.
+            - These Signatures live forever on VM because the bookkeeping
+              likely isn't worth it. We may want to empty things out if all
+              Modules die, this is tracked in bug #166037.
+            - We can further improve things by bit-packing SignatureIndex with
+              Code*, which is tracked by bug #165511.
+
+            * CMakeLists.txt:
+            * _javascript_Core.xcodeproj/project.pbxproj:
+            * runtime/VM.h: wasm signatures are uniqued here, but aren't accessed frequently (only during parsing) so indirection is fine
+            * wasm/WasmB3IRGenerator.cpp: use SignatureIndex instead of Signature* when appropriate, and when still using Signature* do so with its new API
+            (JSC::Wasm::createJSToWasmWrapper):
+            (JSC::Wasm::parseAndCompile):
+            * wasm/WasmBinding.cpp:
+            (JSC::Wasm::importStubGenerator): use SignatureIndex
+            * wasm/WasmBinding.h:
+            * wasm/WasmCallingConvention.h:
+            (JSC::Wasm::CallingConvention::loadArguments):
+            * wasm/WasmFormat.cpp: drive-by move of alloc/free functions to the implementation file, allows the .h file to drop an FastMalloc.h
+            (JSC::Wasm::Segment::create):
+            (JSC::Wasm::Segment::destroy):
+            (JSC::Wasm::Segment::createPtr):
+            * wasm/WasmFormat.h: move Signature to its own file
+            (JSC::Wasm::CallableFunction::CallableFunction):
+            * wasm/WasmFunctionParser.h:
+            (JSC::Wasm::FunctionParser<Context>::FunctionParser):
+            * wasm/WasmModuleParser.cpp:
+            * wasm/WasmModuleParser.h:
+            (JSC::Wasm::ModuleParser::ModuleParser):
+            * wasm/WasmParser.h:
+            (JSC::Wasm::Parser<SuccessType>::Parser):
+            * wasm/WasmPlan.cpp:
+            (JSC::Wasm::Plan::parseAndValidateModule):
+            (JSC::Wasm::Plan::run):
+            * wasm/WasmSignature.cpp: Added.
+            (JSC::Wasm::Signature::dump):
+            (JSC::Wasm::Signature::hash):
+            (JSC::Wasm::Signature::create):
+            (JSC::Wasm::Signature::createInvalid):
+            (JSC::Wasm::Signature::destroy):
+            (JSC::Wasm::SignatureInformation::~SignatureInformation):
+            (JSC::Wasm::SignatureInformation::adopt):
+            (JSC::Wasm::SignatureInformation::get):
+            * wasm/WasmSignature.h: Added.
+            (JSC::Wasm::Signature::Signature):
+            (JSC::Wasm::Signature::storage):
+            (JSC::Wasm::Signature::allocatedSize):
+            (JSC::Wasm::Signature::returnType):
+            (JSC::Wasm::Signature::returnCount):
+            (JSC::Wasm::Signature::argumentCount):
+            (JSC::Wasm::Signature::argument):
+            (JSC::Wasm::Signature::operator==):
+            (JSC::Wasm::SignatureHash::empty):
+            (JSC::Wasm::SignatureHash::deleted):
+            (JSC::Wasm::SignatureHash::SignatureHash):
+            (JSC::Wasm::SignatureHash::operator==):
+            (JSC::Wasm::SignatureHash::equal):
+            (JSC::Wasm::SignatureHash::hash):
+            (JSC::Wasm::SignatureHash::isHashTableDeletedValue):
+            * wasm/WasmValidate.cpp:
+            (JSC::Wasm::validateFunction):
+            * wasm/WasmValidate.h:
+            * wasm/js/JSWebAssemblyInstance.cpp:
+            (JSC::JSWebAssemblyInstance::create):
+            * wasm/js/JSWebAssemblyModule.h:
+            (JSC::JSWebAssemblyModule::signatureForFunctionIndexSpace):
+            * wasm/js/JSWebAssemblyTable.cpp:
+            (JSC::JSWebAssemblyTable::JSWebAssemblyTable):
+            (JSC::JSWebAssemblyTable::clearFunction):
+            (JSC::JSWebAssemblyTable::setFunction):
+            * wasm/js/WebAssemblyFunction.cpp:
+            (JSC::callWebAssemblyFunction):
+            (JSC::WebAssemblyFunction::call):
+            (JSC::WebAssemblyFunction::create):
+            (JSC::WebAssemblyFunction::WebAssemblyFunction):
+            (JSC::WebAssemblyFunction::finishCreation):
+            * wasm/js/WebAssemblyFunction.h:
+            (JSC::WebAssemblyFunction::signatureIndex):
+            * wasm/js/WebAssemblyModuleRecord.cpp:
+            (JSC::WebAssemblyModuleRecord::link):
+            (JSC::WebAssemblyModuleRecord::evaluate):
+
+2017-01-05  Matthew Hanson  <matthew_han...@apple.com>
+
         Merge r209979. rdar://problem/29735737
 
     2016-12-18  Saam Barati  <sbar...@apple.com>

Modified: branches/safari-603-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2017-01-06 01:47:27 UTC (rev 210402)
@@ -2022,6 +2022,8 @@
 		AD4937D41DDD27DE0077C807 /* WebAssemblyFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */; };
 		AD4B1DF91DF244E20071AE32 /* WasmBinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD4B1DF71DF244D70071AE32 /* WasmBinding.cpp */; };
 		AD4B1DFA1DF244E20071AE32 /* WasmBinding.h in Headers */ = {isa = PBXBuildFile; fileRef = AD4B1DF81DF244D70071AE32 /* WasmBinding.h */; };
+		AD7438C01E0457A400FD0C2A /* WasmSignature.h in Headers */ = {isa = PBXBuildFile; fileRef = AD7438BF1E04579200FD0C2A /* WasmSignature.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		AD7438C11E0457AA00FD0C2A /* WasmSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AD7438BE1E04579200FD0C2A /* WasmSignature.cpp */; };
 		AD86A93E1AA4D88D002FE77F /* WeakGCMapInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		ADBC54D41DF8EA2B005BF738 /* WebAssemblyToJSCallee.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */; };
 		ADBC54D51DF8EA2B005BF738 /* WebAssemblyToJSCallee.h in Headers */ = {isa = PBXBuildFile; fileRef = ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */; };
@@ -4504,6 +4506,8 @@
 		AD4937CA1DDD27340077C807 /* WebAssemblyFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyFunction.h; path = js/WebAssemblyFunction.h; sourceTree = "<group>"; };
 		AD4B1DF71DF244D70071AE32 /* WasmBinding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmBinding.cpp; sourceTree = "<group>"; };
 		AD4B1DF81DF244D70071AE32 /* WasmBinding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmBinding.h; sourceTree = "<group>"; };
+		AD7438BE1E04579200FD0C2A /* WasmSignature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmSignature.cpp; sourceTree = "<group>"; };
+		AD7438BF1E04579200FD0C2A /* WasmSignature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmSignature.h; sourceTree = "<group>"; };
 		AD86A93D1AA4D87C002FE77F /* WeakGCMapInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakGCMapInlines.h; sourceTree = "<group>"; };
 		ADBC54D21DF8EA00005BF738 /* WebAssemblyToJSCallee.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = WebAssemblyToJSCallee.cpp; path = js/WebAssemblyToJSCallee.cpp; sourceTree = "<group>"; };
 		ADBC54D31DF8EA00005BF738 /* WebAssemblyToJSCallee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = WebAssemblyToJSCallee.h; path = js/WebAssemblyToJSCallee.h; sourceTree = "<group>"; };
@@ -6046,6 +6050,8 @@
 				531374BE1D5CE95000AF7A0B /* WasmPlan.cpp */,
 				531374BC1D5CE67600AF7A0B /* WasmPlan.h */,
 				53F40E841D58F9770099A1B6 /* WasmSections.h */,
+				AD7438BE1E04579200FD0C2A /* WasmSignature.cpp */,
+				AD7438BF1E04579200FD0C2A /* WasmSignature.h */,
 				53FF7F9A1DBFD2B900A26CCC /* WasmValidate.cpp */,
 				53FF7F981DBFCD9000A26CCC /* WasmValidate.h */,
 			);
@@ -8070,6 +8076,7 @@
 				0F3B3A281544C997003ED0FF /* DFGCFGSimplificationPhase.h in Headers */,
 				0F9D36951AE9CC33000D4DFB /* DFGCleanUpPhase.h in Headers */,
 				A77A424017A0BBFD00A8DB81 /* DFGClobberize.h in Headers */,
+				AD7438C01E0457A400FD0C2A /* WasmSignature.h in Headers */,
 				A77A424217A0BBFD00A8DB81 /* DFGClobberSet.h in Headers */,
 				0F3C1F1B1B868E7900ABB08B /* DFGClobbersExitState.h in Headers */,
 				0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */,
@@ -10417,6 +10424,7 @@
 				FED94F2E171E3E2300BE77A4 /* Watchdog.cpp in Sources */,
 				0F919D2515853CE0004A4E7D /* Watchpoint.cpp in Sources */,
 				1ACF7377171CA6FB00C9BB1E /* Weak.cpp in Sources */,
+				AD7438C11E0457AA00FD0C2A /* WasmSignature.cpp in Sources */,
 				14E84F9E14EE1ACC00D6D5D4 /* WeakBlock.cpp in Sources */,
 				14F7256514EE265E00B1652B /* WeakHandleOwner.cpp in Sources */,
 				A7CA3AE317DA41AE006538AF /* WeakMapConstructor.cpp in Sources */,

Modified: branches/safari-603-branch/Source/_javascript_Core/runtime/VM.h (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/runtime/VM.h	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/runtime/VM.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -147,6 +147,11 @@
 namespace DOMJIT {
 class Signature;
 }
+#if ENABLE(WEBASSEMBLY)
+namespace Wasm {
+class SignatureInformation;
+}
+#endif
 
 struct HashTable;
 struct Instruction;
@@ -354,6 +359,11 @@
     Strong<JSCell> iterationTerminator;
     Strong<JSCell> emptyPropertyNameEnumerator;
 
+#if ENABLE(WEBASSEMBLY)
+    std::once_flag m_wasmSignatureInformationOnceFlag;
+    std::unique_ptr<Wasm::SignatureInformation> m_wasmSignatureInformation;
+#endif
+
     AtomicStringTable* m_atomicStringTable;
     WTF::SymbolRegistry m_symbolRegistry;
     TemplateRegistryKeyTable m_templateRegistryKeytable;

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -154,7 +154,7 @@
 
     B3IRGenerator(VM&, const ModuleInformation&, Procedure&, WasmInternalFunction*, Vector<UnlinkedWasmToWasmCall>&, const ImmutableFunctionIndexSpace&);
 
-    PartialResult WARN_UNUSED_RETURN addArguments(const Vector<Type>&);
+    PartialResult WARN_UNUSED_RETURN addArguments(const Signature*);
     PartialResult WARN_UNUSED_RETURN addLocal(Type, uint32_t);
     ExpressionType addConstant(Type, uint64_t);
 
@@ -192,7 +192,7 @@
 
     // Calls
     PartialResult WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature*, Vector<ExpressionType>& args, ExpressionType& result);
-    PartialResult WARN_UNUSED_RETURN addCallIndirect(const Signature*, Vector<ExpressionType>& args, ExpressionType& result);
+    PartialResult WARN_UNUSED_RETURN addCallIndirect(const Signature*, SignatureIndex, Vector<ExpressionType>& args, ExpressionType& result);
     PartialResult WARN_UNUSED_RETURN addUnreachable();
 
     void dump(const Vector<ControlEntry>& controlStack, const ExpressionList& expressionStack);
@@ -302,13 +302,13 @@
     return { };
 }
 
-auto B3IRGenerator::addArguments(const Vector<Type>& types) -> PartialResult
+auto B3IRGenerator::addArguments(const Signature* signature) -> PartialResult
 {
     ASSERT(!m_locals.size());
-    WASM_COMPILE_FAIL_IF(!m_locals.tryReserveCapacity(types.size()), "can't allocate memory for ", types.size(), " arguments");
+    WASM_COMPILE_FAIL_IF(!m_locals.tryReserveCapacity(signature->argumentCount()), "can't allocate memory for ", signature->argumentCount(), " arguments");
 
-    m_locals.grow(types.size());
-    wasmCallingConvention().loadArguments(types, m_proc, m_currentBlock, Origin(),
+    m_locals.grow(signature->argumentCount());
+    wasmCallingConvention().loadArguments(signature, m_proc, m_currentBlock, Origin(),
         [&] (ExpressionType argument, unsigned i) {
             Variable* argumentVariable = m_proc.addVariable(argument->type());
             m_locals[i] = argumentVariable;
@@ -682,9 +682,9 @@
 
 auto B3IRGenerator::addCall(uint32_t functionIndex, const Signature* signature, Vector<ExpressionType>& args, ExpressionType& result) -> PartialResult
 {
-    ASSERT(signature->arguments.size() == args.size());
+    ASSERT(signature->argumentCount() == args.size());
 
-    Type returnType = signature->returnType;
+    Type returnType = signature->returnType();
 
     result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(returnType),
         [&] (PatchpointValue* patchpoint) {
@@ -704,10 +704,11 @@
     return { };
 }
 
-auto B3IRGenerator::addCallIndirect(const Signature* signature, Vector<ExpressionType>& args, ExpressionType& result) -> PartialResult
+auto B3IRGenerator::addCallIndirect(const Signature* signature, SignatureIndex signatureIndex, Vector<ExpressionType>& args, ExpressionType& result) -> PartialResult
 {
+    ASSERT(signatureIndex != Signature::invalidIndex);
     ExpressionType calleeIndex = args.takeLast();
-    ASSERT(signature->arguments.size() == args.size());
+    ASSERT(signature->argumentCount() == args.size());
 
     ExpressionType callableFunctionBuffer;
     ExpressionType callableFunctionBufferSize;
@@ -736,13 +737,14 @@
         m_currentBlock->appendIntConstant(m_proc, Origin(), pointerType(), sizeof(CallableFunction)));
     ExpressionType callableFunction = m_currentBlock->appendNew<Value>(m_proc, Add, Origin(), callableFunctionBuffer, offset);
 
-    // Check that the CallableFunction is initialized. We trap if it isn't. A null Signature* indicates it's not initialized.
-    ExpressionType calleeSignature = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(), callableFunction, OBJECT_OFFSETOF(CallableFunction, signature));
+    // Check that the CallableFunction is initialized. We trap if it isn't. An "invalid" SignatureIndex indicates it's not initialized.
+    static_assert(sizeof(CallableFunction::signatureIndex) == sizeof(uint32_t), "Load codegen assumes i32");
+    ExpressionType calleeSignatureIndex = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, Int32, Origin(), callableFunction, OBJECT_OFFSETOF(CallableFunction, signatureIndex));
     {
         CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(),
-            m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(), 
-                calleeSignature, 
-                m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), 0)));
+            m_currentBlock->appendNew<Value>(m_proc, Equal, Origin(),
+                calleeSignatureIndex,
+                m_currentBlock->appendNew<Const32Value>(m_proc, Origin(), Signature::invalidIndex)));
 
         check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
             this->emitExceptionCheck(jit, ExceptionType::NullTableEntry);
@@ -751,9 +753,9 @@
 
     // Check the signature matches the value we expect.
     {
-        ExpressionType expectedSignature = m_currentBlock->appendNew<ConstPtrValue>(m_proc, Origin(), signature);
+        ExpressionType expectedSignatureIndex = m_currentBlock->appendNew<Const32Value>(m_proc, Origin(), signatureIndex);
         CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, Origin(),
-            m_currentBlock->appendNew<Value>(m_proc, NotEqual, Origin(), calleeSignature, expectedSignature));
+            m_currentBlock->appendNew<Value>(m_proc, NotEqual, Origin(), calleeSignatureIndex, expectedSignatureIndex));
 
         check->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
             this->emitExceptionCheck(jit, ExceptionType::BadSignature);
@@ -762,7 +764,7 @@
 
     ExpressionType calleeCode = m_currentBlock->appendNew<MemoryValue>(m_proc, Load, pointerType(), Origin(), callableFunction, OBJECT_OFFSETOF(CallableFunction, code));
 
-    Type returnType = signature->returnType;
+    Type returnType = signature->returnType();
     result = wasmCallingConvention().setupCall(m_proc, m_currentBlock, Origin(), args, toB3Type(returnType),
         [&] (PatchpointValue* patchpoint) {
             patchpoint->effects.writesPinned = true;
@@ -834,7 +836,7 @@
         Value* argumentCount = block->appendNew<MemoryValue>(proc, Load, Int32, origin,
             block->appendNew<Value>(proc, Add, origin, framePointer, offSetOfArgumentCount));
 
-        Value* expectedArgumentCount = block->appendNew<Const32Value>(proc, origin, signature->arguments.size());
+        Value* expectedArgumentCount = block->appendNew<Const32Value>(proc, origin, signature->argumentCount());
 
         CheckValue* argumentCountCheck = block->appendNew<CheckValue>(proc, Check, origin,
             block->appendNew<Value>(proc, Above, origin, expectedArgumentCount, argumentCount));
@@ -861,12 +863,12 @@
 
     // Get our arguments.
     Vector<Value*> arguments;
-    jscCallingConvention().loadArguments(signature->arguments, proc, block, origin, [&] (Value* argument, unsigned) {
+    jscCallingConvention().loadArguments(signature, proc, block, origin, [&] (Value* argument, unsigned) {
         arguments.append(argument);
     });
 
     // Move the arguments into place.
-    Value* result = wasmCallingConvention().setupCall(proc, block, origin, arguments, toB3Type(signature->returnType), [&] (PatchpointValue* patchpoint) {
+    Value* result = wasmCallingConvention().setupCall(proc, block, origin, arguments, toB3Type(signature->returnType()), [&] (PatchpointValue* patchpoint) {
         if (!!memory) {
             ASSERT(sizes.size() == memory.pinnedRegisters().sizeRegisters.size());
             patchpoint->append(ConstrainedValue(baseMemory, ValueRep::reg(memory.pinnedRegisters().baseMemoryPointer)));
@@ -885,7 +887,7 @@
     });
 
     // Return the result, if needed.
-    switch (signature->returnType) {
+    switch (signature->returnType()) {
     case Wasm::Void:
         block->appendNewControlValue(proc, B3::Return, origin);
         break;
@@ -913,7 +915,7 @@
 
     Procedure procedure;
     B3IRGenerator context(vm, info, procedure, result.get(), unlinkedWasmToWasmCalls, functionIndexSpace);
-    FunctionParser<B3IRGenerator> parser(context, functionStart, functionLength, signature, functionIndexSpace, info);
+    FunctionParser<B3IRGenerator> parser(&vm, context, functionStart, functionLength, signature, functionIndexSpace, info);
     WASM_FAIL_IF_HELPER_FAILS(parser.parse());
 
     procedure.resetReachability();

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmBinding.cpp (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmBinding.cpp	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmBinding.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -36,11 +36,12 @@
 
 namespace JSC { namespace Wasm {
 
-WasmToJSStub importStubGenerator(VM* vm, Bag<CallLinkInfo>& callLinkInfos, Signature* signature, unsigned importIndex)
+WasmToJSStub importStubGenerator(VM* vm, Bag<CallLinkInfo>& callLinkInfos, SignatureIndex signatureIndex, unsigned importIndex)
 {
     const WasmCallingConvention& wasmCC = wasmCallingConvention();
     const JSCCallingConvention& jsCC = jscCallingConvention();
-    unsigned argCount = signature->arguments.size();
+    const Signature* signature = SignatureInformation::get(vm, signatureIndex);
+    unsigned argCount = signature->argumentCount();
     typedef AssemblyHelpers JIT;
     JIT jit(vm, nullptr);
 
@@ -72,7 +73,7 @@
     unsigned calleeFrameOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register));
     unsigned frOffset = CallFrameSlot::firstArgument * static_cast<int>(sizeof(Register));
     for (unsigned argNum = 0; argNum < argCount; ++argNum) {
-        Type argType = signature->arguments[argNum];
+        Type argType = signature->argument(argNum);
         switch (argType) {
         case Void:
         case Func:
@@ -161,7 +162,7 @@
     JIT::Call slowCall = jit.nearCall();
     done.link(&jit);
 
-    switch (signature->returnType) {
+    switch (signature->returnType()) {
     case Void:
         // Discard.
         break;
@@ -230,7 +231,7 @@
     CodeLocationLabel hotPathBegin(patchBuffer.locationOf(targetToCheck));
     CodeLocationNearCall hotPathOther = patchBuffer.locationOfNearCall(fastCall);
     callLinkInfo->setCallLocations(callReturnLocation, hotPathBegin, hotPathOther);
-    return FINALIZE_CODE(patchBuffer, ("WebAssembly import[%i] stub for signature %p", importIndex, signature));
+    return FINALIZE_CODE(patchBuffer, ("WebAssembly import[%i] stub for signature %i", importIndex, signatureIndex));
 }
 
 } } // namespace JSC::Wasm

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmBinding.h (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmBinding.h	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmBinding.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -38,7 +38,7 @@
 
 namespace Wasm {
 
-WasmToJSStub importStubGenerator(VM*, Bag<CallLinkInfo>&, Signature*, unsigned);
+WasmToJSStub importStubGenerator(VM*, Bag<CallLinkInfo>&, SignatureIndex, unsigned);
 
 } } // namespace JSC::Wasm
 

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmCallingConvention.h (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmCallingConvention.h	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmCallingConvention.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -118,7 +118,7 @@
     }
 
     template<typename Functor>
-    void loadArguments(const Vector<Type>& argumentTypes, B3::Procedure& proc, B3::BasicBlock* block, B3::Origin origin, const Functor& functor) const
+    void loadArguments(const Signature* signature, B3::Procedure& proc, B3::BasicBlock* block, B3::Origin origin, const Functor& functor) const
     {
         B3::Value* framePointer = block->appendNew<B3::Value>(proc, B3::FramePointer, origin);
 
@@ -126,8 +126,8 @@
         size_t fpArgumentCount = 0;
         size_t stackOffset = headerSize;
 
-        for (size_t i = 0; i < argumentTypes.size(); ++i) {
-            B3::Type type = toB3Type(argumentTypes[i]);
+        for (size_t i = 0; i < signature->argumentCount(); ++i) {
+            B3::Type type = toB3Type(signature->argument(i));
             B3::Value* argument;
             B3::ValueRep rep = marshallArgument(type, gpArgumentCount, fpArgumentCount, stackOffset);
             if (rep.isReg()) {

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmFormat.cpp (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmFormat.cpp	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmFormat.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -30,9 +30,31 @@
 #if ENABLE(WEBASSEMBLY)
 
 #include "WasmMemory.h"
+#include <wtf/FastMalloc.h>
 
 namespace JSC { namespace Wasm {
 
+Segment* Segment::create(uint32_t offset, uint32_t sizeInBytes)
+{
+    auto allocated = tryFastCalloc(sizeof(Segment) + sizeInBytes, 1);
+    Segment* segment;
+    if (!allocated.getValue(segment))
+        return nullptr;
+    segment->offset = offset;
+    segment->sizeInBytes = sizeInBytes;
+    return segment;
+}
+
+void Segment::destroy(Segment *segment)
+{
+    fastFree(segment);
+}
+
+Segment::Ptr Segment::adoptPtr(Segment* segment)
+{
+    return Ptr(segment, &Segment::destroy);
+}
+
 JS_EXPORT_PRIVATE ModuleInformation::~ModuleInformation() { }
 
 } } // namespace JSC::Wasm

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmFormat.h (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmFormat.h	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmFormat.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -36,8 +36,9 @@
 #include "WasmMemoryInformation.h"
 #include "WasmOps.h"
 #include "WasmPageCount.h"
+#include "WasmSignature.h"
+#include <limits>
 #include <memory>
-#include <wtf/FastMalloc.h>
 #include <wtf/Optional.h>
 #include <wtf/Vector.h>
 
@@ -100,11 +101,6 @@
     return "?";
 }
 
-struct Signature {
-    Type returnType;
-    Vector<Type> arguments;
-};
-
 struct Import {
     Identifier module;
     Identifier field;
@@ -146,30 +142,15 @@
     uint32_t offset;
     uint32_t sizeInBytes;
     // Bytes are allocated at the end.
-    static Segment* make(uint32_t offset, uint32_t sizeInBytes)
-    {
-        auto allocated = tryFastCalloc(sizeof(Segment) + sizeInBytes, 1);
-        Segment* segment;
-        if (!allocated.getValue(segment))
-            return nullptr;
-        segment->offset = offset;
-        segment->sizeInBytes = sizeInBytes;
-        return segment;
-    }
-    static void destroy(Segment *segment)
-    {
-        fastFree(segment);
-    }
     uint8_t& byte(uint32_t pos)
     {
         ASSERT(pos < sizeInBytes);
         return *reinterpret_cast<uint8_t*>(reinterpret_cast<char*>(this) + sizeof(offset) + sizeof(sizeInBytes) + pos);
     }
+    static Segment* create(uint32_t, uint32_t);
+    static void destroy(Segment*);
     typedef std::unique_ptr<Segment, decltype(&Segment::destroy)> Ptr;
-    static Ptr makePtr(Segment* segment)
-    {
-        return Ptr(segment, &Segment::destroy);
-    }
+    static Ptr adoptPtr(Segment*);
 };
 
 struct Element {
@@ -206,10 +187,10 @@
 };
 
 struct ModuleInformation {
-    Vector<Signature> signatures;
+    Vector<SignatureIndex> signatureIndices;
     Vector<Import> imports;
-    Vector<Signature*> importFunctions;
-    Vector<Signature*> internalFunctionSignatures;
+    Vector<SignatureIndex> importFunctionSignatureIndices;
+    Vector<SignatureIndex> internalFunctionSignatureIndices;
     MemoryInformation memory;
     Vector<Export> exports;
     std::optional<uint32_t> startFunctionIndexSpace;
@@ -247,15 +228,14 @@
 struct CallableFunction {
     CallableFunction() = default;
 
-    CallableFunction(Signature* signature, void* code = nullptr)
-        : signature(signature)
+    CallableFunction(SignatureIndex signatureIndex, void* code = nullptr)
+        : signatureIndex(signatureIndex)
         , code(code)
     {
     }
 
-    // FIXME pack this inside a (uniqued) integer (for correctness the parser should unique Signatures),
-    // and then pack that integer into the code pointer. https://bugs.webkit.org/show_bug.cgi?id=165511
-    Signature* signature { nullptr }; 
+    // FIXME pack the SignatureIndex and the code pointer into one 64-bit value. https://bugs.webkit.org/show_bug.cgi?id=165511
+    SignatureIndex signatureIndex { Signature::invalidIndex };
     void* code { nullptr };
 };
 typedef Vector<CallableFunction> FunctionIndexSpace;

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmFunctionParser.h (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmFunctionParser.h	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmFunctionParser.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -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 ImmutableFunctionIndexSpace&, const ModuleInformation&);
+    FunctionParser(VM*, Context&, const uint8_t* functionStart, size_t functionLength, const Signature*, const ImmutableFunctionIndexSpace&, const ModuleInformation&);
 
     Result WARN_UNUSED_RETURN parse();
 
@@ -88,8 +88,8 @@
 };
 
 template<typename Context>
-FunctionParser<Context>::FunctionParser(Context& context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& info)
-    : Parser(functionStart, functionLength)
+FunctionParser<Context>::FunctionParser(VM* vm, Context& context, const uint8_t* functionStart, size_t functionLength, const Signature* signature, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& info)
+    : Parser(vm, functionStart, functionLength)
     , m_context(context)
     , m_signature(signature)
     , m_functionIndexSpace(functionIndexSpace)
@@ -104,7 +104,7 @@
 {
     uint32_t localCount;
 
-    WASM_PARSER_FAIL_IF(!m_context.addArguments(m_signature->arguments), "can't add ", m_signature->arguments.size(), " arguments to Function");
+    WASM_PARSER_FAIL_IF(!m_context.addArguments(m_signature), "can't add ", m_signature->argumentCount(), " arguments to Function");
     WASM_PARSER_FAIL_IF(!parseVarUInt32(localCount), "can't get local count");
     WASM_PARSER_FAIL_IF(localCount == std::numeric_limits<uint32_t>::max(), "Function section's local count is too big ", localCount);
 
@@ -155,7 +155,7 @@
 auto FunctionParser<Context>::addReturn() -> PartialResult
 {
     ExpressionList returnValues;
-    if (m_signature->returnType != Void) {
+    if (m_signature->returnType() != Void) {
         ExpressionType returnValue;
         WASM_TRY_POP_EXPRESSION_STACK_INTO(returnValue, "return");
         returnValues.append(returnValue);
@@ -329,12 +329,13 @@
         WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), "can't parse call's function index");
         WASM_PARSER_FAIL_IF(functionIndex >= m_functionIndexSpace.size, "call function index ", functionIndex, " exceeds function index space ", m_functionIndexSpace.size);
 
-        const Signature* calleeSignature = m_functionIndexSpace.buffer.get()[functionIndex].signature;
-        WASM_PARSER_FAIL_IF(calleeSignature->arguments.size() > m_expressionStack.size(), "call function index ", functionIndex, " has ", calleeSignature->arguments.size(), " arguments, but the _expression_ stack currently holds ", m_expressionStack.size(), " values");
+        SignatureIndex calleeSignatureIndex = m_functionIndexSpace.buffer.get()[functionIndex].signatureIndex;
+        const Signature* calleeSignature = SignatureInformation::get(m_vm, calleeSignatureIndex);
+        WASM_PARSER_FAIL_IF(calleeSignature->argumentCount() > m_expressionStack.size(), "call function index ", functionIndex, " has ", calleeSignature->argumentCount(), " arguments, but the _expression_ stack currently holds ", m_expressionStack.size(), " values");
 
-        size_t firstArgumentIndex = m_expressionStack.size() - calleeSignature->arguments.size();
+        size_t firstArgumentIndex = m_expressionStack.size() - calleeSignature->argumentCount();
         Vector<ExpressionType> args;
-        WASM_PARSER_FAIL_IF(!args.tryReserveCapacity(calleeSignature->arguments.size()), "can't allocate enough memory for call's ", calleeSignature->arguments.size(), " arguments");
+        WASM_PARSER_FAIL_IF(!args.tryReserveCapacity(calleeSignature->argumentCount()), "can't allocate enough memory for call's ", calleeSignature->argumentCount(), " arguments");
         for (size_t i = firstArgumentIndex; i < m_expressionStack.size(); ++i)
             args.uncheckedAppend(m_expressionStack[i]);
         m_expressionStack.shrink(firstArgumentIndex);
@@ -355,10 +356,11 @@
         WASM_PARSER_FAIL_IF(!parseVarUInt32(signatureIndex), "can't get call_indirect's signature index");
         WASM_PARSER_FAIL_IF(!parseVarUInt1(reserved), "can't get call_indirect's reserved byte");
         WASM_PARSER_FAIL_IF(reserved, "call_indirect's 'reserved' varuint1 must be 0x0");
-        WASM_PARSER_FAIL_IF(m_info.signatures.size() <= signatureIndex, "call_indirect's signature index ", signatureIndex, " exceeds known signatures ", m_info.signatures.size());
+        WASM_PARSER_FAIL_IF(m_info.signatureIndices.size() <= signatureIndex, "call_indirect's signature index ", signatureIndex, " exceeds known signatures ", m_info.signatureIndices.size());
 
-        const Signature* calleeSignature = &m_info.signatures[signatureIndex];
-        size_t argumentCount = calleeSignature->arguments.size() + 1; // Add the callee's index.
+        SignatureIndex calleeSignatureIndex = m_info.signatureIndices[signatureIndex];
+        const Signature* calleeSignature = SignatureInformation::get(m_vm, calleeSignatureIndex);
+        size_t argumentCount = calleeSignature->argumentCount() + 1; // Add the callee's index.
         WASM_PARSER_FAIL_IF(argumentCount > m_expressionStack.size(), "call_indirect expects ", argumentCount, " arguments, but the _expression_ stack currently holds ", m_expressionStack.size(), " values");
 
         Vector<ExpressionType> args;
@@ -369,7 +371,7 @@
         m_expressionStack.shrink(firstArgumentIndex);
 
         ExpressionType result = Context::emptyExpression;
-        WASM_TRY_ADD_TO_CONTEXT(addCallIndirect(calleeSignature, args, result));
+        WASM_TRY_ADD_TO_CONTEXT(addCallIndirect(calleeSignature, calleeSignatureIndex, args, result));
 
         if (result != Context::emptyExpression)
             m_expressionStack.append(result);

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmModuleParser.cpp (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmModuleParser.cpp	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmModuleParser.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -99,7 +99,7 @@
 
     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Type section's count");
     WASM_PARSER_FAIL_IF(count == std::numeric_limits<uint32_t>::max(), "Type section's count is too big ", count);
-    WASM_PARSER_FAIL_IF(!m_result.module->signatures.tryReserveCapacity(count), "can't allocate enough memory for Type section's ", count, " entries");
+    WASM_PARSER_FAIL_IF(!m_result.module->signatureIndices.tryReserveCapacity(count), "can't allocate enough memory for Type section's ", count, " entries");
 
     for (uint32_t i = 0; i < count; ++i) {
         int8_t type;
@@ -110,18 +110,18 @@
         WASM_PARSER_FAIL_IF(type != Func, i, "th Type is non-Func ", type);
         WASM_PARSER_FAIL_IF(!parseVarUInt32(argumentCount), "can't get ", i, "th Type's argument count");
         WASM_PARSER_FAIL_IF(argumentCount == std::numeric_limits<uint32_t>::max(), i, "th argument count is too big ", argumentCount);
-        WASM_PARSER_FAIL_IF(!argumentTypes.tryReserveCapacity(argumentCount), "can't allocate enough memory for Type section's ", i, "th ", argumentCount, " arguments");
+        std::unique_ptr<Signature, void (*)(Signature*)> signature(Signature::create(argumentCount), &Signature::destroy);
+        WASM_PARSER_FAIL_IF(!signature, "can't allocate enough memory for Type section's ", i, "th signature");
 
         for (unsigned i = 0; i < argumentCount; ++i) {
             Type argumentType;
             WASM_PARSER_FAIL_IF(!parseResultType(argumentType), "can't get ", i, "th argument Type");
-            argumentTypes.uncheckedAppend(argumentType);
+            signature->argument(i) = argumentType;
         }
 
         uint8_t returnCount;
         WASM_PARSER_FAIL_IF(!parseVarUInt1(returnCount), "can't get ", i, "th Type's return count");
         Type returnType;
-
         if (returnCount) {
             Type value;
             WASM_PARSER_FAIL_IF(!parseValueType(value), "can't get ", i, "th Type's return value");
@@ -128,8 +128,10 @@
             returnType = static_cast<Type>(value);
         } else
             returnType = Type::Void;
+        signature->returnType() = returnType;
 
-        m_result.module->signatures.uncheckedAppend({ returnType, WTFMove(argumentTypes) });
+        SignatureIndex signatureIndex = SignatureInformation::adopt(m_vm, signature.release());
+        m_result.module->signatureIndices.uncheckedAppend(signatureIndex);
     }
     return { };
 }
@@ -141,7 +143,7 @@
     WASM_PARSER_FAIL_IF(importCount == std::numeric_limits<uint32_t>::max(), "Import section's count is too big ", importCount);
     WASM_PARSER_FAIL_IF(!m_result.module->globals.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " globals"); // FIXME this over-allocates when we fix the FIXMEs below.
     WASM_PARSER_FAIL_IF(!m_result.module->imports.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " imports"); // FIXME this over-allocates when we fix the FIXMEs below.
-    WASM_PARSER_FAIL_IF(!m_result.module->importFunctions.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " import functions"); // FIXME this over-allocates when we fix the FIXMEs below.
+    WASM_PARSER_FAIL_IF(!m_result.module->importFunctionSignatureIndices.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " import function signatures"); // FIXME this over-allocates when we fix the FIXMEs below.
     WASM_PARSER_FAIL_IF(!m_result.functionIndexSpace.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " functions in the index space"); // FIXME this over-allocates when we fix the FIXMEs below. We'll allocate some more here when we know how many functions to expect.
 
     for (uint32_t importNumber = 0; importNumber < importCount; ++importNumber) {
@@ -164,11 +166,11 @@
         case ExternalKind::Function: {
             uint32_t functionSignatureIndex;
             WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSignatureIndex), "can't get ", importNumber, "th Import's function signature in module '", moduleString, "' field '", fieldString, "'");
-            WASM_PARSER_FAIL_IF(functionSignatureIndex >= m_result.module->signatures.size(), "invalid function signature for ", importNumber, "th Import, ", functionSignatureIndex, " is out of range of ", m_result.module->signatures.size(), " in module '", moduleString, "' field '", fieldString, "'");
-            imp.kindIndex = m_result.module->importFunctions.size();
-            Signature* signature = &m_result.module->signatures[functionSignatureIndex];
-            m_result.module->importFunctions.uncheckedAppend(signature);
-            m_result.functionIndexSpace.uncheckedAppend(signature);
+            WASM_PARSER_FAIL_IF(functionSignatureIndex >= m_result.module->signatureIndices.size(), "invalid function signature for ", importNumber, "th Import, ", functionSignatureIndex, " is out of range of ", m_result.module->signatureIndices.size(), " in module '", moduleString, "' field '", fieldString, "'");
+            imp.kindIndex = m_result.module->importFunctionSignatureIndices.size();
+            SignatureIndex signatureIndex = m_result.module->signatureIndices[functionSignatureIndex];
+            m_result.module->importFunctionSignatureIndices.uncheckedAppend(signatureIndex);
+            m_result.functionIndexSpace.uncheckedAppend(signatureIndex);
             break;
         }
         case ExternalKind::Table: {
@@ -208,7 +210,7 @@
     uint32_t count;
     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Function section's count");
     WASM_PARSER_FAIL_IF(count == std::numeric_limits<uint32_t>::max(), "Function section's count is too big ", count);
-    WASM_PARSER_FAIL_IF(!m_result.module->internalFunctionSignatures.tryReserveCapacity(count), "can't allocate enough memory for ", count, " Function signatures");
+    WASM_PARSER_FAIL_IF(!m_result.module->internalFunctionSignatureIndices.tryReserveCapacity(count), "can't allocate enough memory for ", count, " Function signatures");
     WASM_PARSER_FAIL_IF(!m_result.functionLocationInBinary.tryReserveCapacity(count), "can't allocate enough memory for ", count, "Function locations");
     WASM_PARSER_FAIL_IF(!m_result.functionIndexSpace.tryReserveCapacity(m_result.functionIndexSpace.size() + count), "can't allocate enough memory for ", count, " more functions in the function index space");
 
@@ -215,15 +217,15 @@
     for (uint32_t i = 0; i < count; ++i) {
         uint32_t typeNumber;
         WASM_PARSER_FAIL_IF(!parseVarUInt32(typeNumber), "can't get ", i, "th Function's type number");
-        WASM_PARSER_FAIL_IF(typeNumber >= m_result.module->signatures.size(), i, "th Function type number is invalid ", typeNumber);
+        WASM_PARSER_FAIL_IF(typeNumber >= m_result.module->signatureIndices.size(), i, "th Function type number is invalid ", typeNumber);
 
-        Signature* signature = &m_result.module->signatures[typeNumber];
+        SignatureIndex signatureIndex = m_result.module->signatureIndices[typeNumber];
         // The Code section fixes up start and end.
         size_t start = 0;
         size_t end = 0;
-        m_result.module->internalFunctionSignatures.uncheckedAppend(signature);
+        m_result.module->internalFunctionSignatureIndices.uncheckedAppend(signatureIndex);
         m_result.functionLocationInBinary.uncheckedAppend({ start, end });
-        m_result.functionIndexSpace.uncheckedAppend(signature);
+        m_result.functionIndexSpace.uncheckedAppend(signatureIndex);
     }
 
     return { };
@@ -425,9 +427,10 @@
     uint32_t startFunctionIndex;
     WASM_PARSER_FAIL_IF(!parseVarUInt32(startFunctionIndex), "can't get Start index");
     WASM_PARSER_FAIL_IF(startFunctionIndex >= m_result.functionIndexSpace.size(), "Start index ", startFunctionIndex, " exceeds function index space ", m_result.functionIndexSpace.size());
-    Signature* signature = m_result.functionIndexSpace[startFunctionIndex].signature;
-    WASM_PARSER_FAIL_IF(!signature->arguments.isEmpty(), "Start function can't have arguments");
-    WASM_PARSER_FAIL_IF(signature->returnType != Void, "Start function can't return a value");
+    SignatureIndex signatureIndex = m_result.functionIndexSpace[startFunctionIndex].signatureIndex;
+    const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
+    WASM_PARSER_FAIL_IF(signature->argumentCount(), "Start function can't have arguments");
+    WASM_PARSER_FAIL_IF(signature->returnType() != Void, "Start function can't return a value");
     m_result.module->startFunctionIndexSpace = startFunctionIndex;
     return { };
 }
@@ -594,9 +597,9 @@
         WASM_PARSER_FAIL_IF(!parseVarUInt32(dataByteLength), "can't get ", segmentNumber, "th Data segment's data byte length");
         WASM_PARSER_FAIL_IF(dataByteLength == std::numeric_limits<uint32_t>::max(), segmentNumber, "th Data segment's data byte length is too big ", dataByteLength);
 
-        Segment* segment = Segment::make(offset, dataByteLength);
+        Segment* segment = Segment::create(offset, dataByteLength);
         WASM_PARSER_FAIL_IF(!segment, "can't allocate enough memory for ", segmentNumber, "th Data segment of size ", dataByteLength);
-        m_result.module->data.uncheckedAppend(Segment::makePtr(segment));
+        m_result.module->data.uncheckedAppend(Segment::adoptPtr(segment));
         for (uint32_t dataByte = 0; dataByte < dataByteLength; ++dataByte) {
             uint8_t byte;
             WASM_PARSER_FAIL_IF(!parseUInt8(byte), "can't get ", dataByte, "th data byte from ", segmentNumber, "th Data segment");

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmModuleParser.h (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmModuleParser.h	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmModuleParser.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -44,8 +44,7 @@
 public:
 
     ModuleParser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength)
-        : Parser(sourceBuffer, sourceLength)
-        , m_vm(vm)
+        : Parser(vm, sourceBuffer, sourceLength)
     {
     }
     ModuleParser(VM* vm, const Vector<uint8_t>& sourceBuffer)
@@ -67,7 +66,6 @@
     PartialResult WARN_UNUSED_RETURN parseResizableLimits(uint32_t& initial, std::optional<uint32_t>& maximum);
     PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&, uint64_t&);
 
-    VM* m_vm;
     ModuleParserResult m_result;
     bool m_hasTable { false };
 };

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmParser.h (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmParser.h	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmParser.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -56,7 +56,7 @@
     typedef Expected<SuccessType, ErrorType> Result;
 
 protected:
-    Parser(const uint8_t*, size_t);
+    Parser(VM*, const uint8_t*, size_t);
 
     bool WARN_UNUSED_RETURN consumeCharacter(char);
     bool WARN_UNUSED_RETURN consumeString(const char*);
@@ -81,6 +81,7 @@
     const uint8_t* source() const { return m_source; }
     size_t length() const { return m_sourceLength; }
 
+    VM* m_vm;
     size_t m_offset = 0;
 
     template <typename ...Args>
@@ -106,8 +107,9 @@
 };
 
 template<typename SuccessType>
-ALWAYS_INLINE Parser<SuccessType>::Parser(const uint8_t* sourceBuffer, size_t sourceLength)
-    : m_source(sourceBuffer)
+ALWAYS_INLINE Parser<SuccessType>::Parser(VM* vm, const uint8_t* sourceBuffer, size_t sourceLength)
+    : m_vm(vm)
+    , m_source(sourceBuffer)
     , m_sourceLength(sourceLength)
 {
 }

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmPlan.cpp (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmPlan.cpp	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmPlan.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -79,9 +79,10 @@
         const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start;
         size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start;
         ASSERT(Checked<uintptr_t>(bitwise_cast<uintptr_t>(functionStart)) + functionLength <= Checked<uintptr_t>(bitwise_cast<uintptr_t>(m_source)) + m_sourceLength);
-        Signature* signature = m_moduleInformation->internalFunctionSignatures[functionIndex];
+        SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex];
+        const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
 
-        auto validationResult = validateFunction(functionStart, functionLength, signature, m_functionIndexSpace, *m_moduleInformation);
+        auto validationResult = validateFunction(m_vm, functionStart, functionLength, signature, m_functionIndexSpace, *m_moduleInformation);
         if (!validationResult) {
             if (verbose) {
                 for (unsigned i = 0; i < functionLength; ++i)
@@ -114,7 +115,7 @@
     };
 
     Vector<Vector<UnlinkedWasmToWasmCall>> unlinkedWasmToWasmCalls;
-    if (!tryReserveCapacity(m_wasmToJSStubs, m_moduleInformation->importFunctions.size(), " WebAssembly to _javascript_ stubs")
+    if (!tryReserveCapacity(m_wasmToJSStubs, m_moduleInformation->importFunctionSignatureIndices.size(), " WebAssembly to _javascript_ stubs")
         || !tryReserveCapacity(unlinkedWasmToWasmCalls, m_functionLocationInBinary.size(), " unlinked WebAssembly to WebAssembly calls")
         || !tryReserveCapacity(m_wasmInternalFunctions, m_functionLocationInBinary.size(), " WebAssembly functions"))
         return;
@@ -126,8 +127,8 @@
         unsigned importFunctionIndex = m_wasmToJSStubs.size();
         if (verbose)
             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));
+        SignatureIndex signatureIndex = m_moduleInformation->importFunctionSignatureIndices.at(import->kindIndex);
+        m_wasmToJSStubs.uncheckedAppend(importStubGenerator(m_vm, m_callLinkInfos, signatureIndex, importFunctionIndex));
         m_functionIndexSpace.buffer.get()[importFunctionIndex].code = m_wasmToJSStubs[importFunctionIndex].code().executableAddress();
     }
 
@@ -137,11 +138,12 @@
         const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start;
         size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start;
         ASSERT(functionLength <= m_sourceLength);
-        Signature* signature = m_moduleInformation->internalFunctionSignatures[functionIndex];
+        SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex];
+        const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
         unsigned functionIndexSpace = m_wasmToJSStubs.size() + functionIndex;
-        ASSERT(m_functionIndexSpace.buffer.get()[functionIndexSpace].signature == signature);
+        ASSERT(m_functionIndexSpace.buffer.get()[functionIndexSpace].signatureIndex == signatureIndex);
 
-        ASSERT(validateFunction(functionStart, functionLength, signature, m_functionIndexSpace, *m_moduleInformation));
+        ASSERT(validateFunction(m_vm, functionStart, functionLength, signature, m_functionIndexSpace, *m_moduleInformation));
 
         unlinkedWasmToWasmCalls.uncheckedAppend(Vector<UnlinkedWasmToWasmCall>());
         auto parseAndCompileResult = parseAndCompile(*m_vm, functionStart, functionLength, signature, unlinkedWasmToWasmCalls.at(functionIndex), m_functionIndexSpace, *m_moduleInformation);

Added: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmSignature.cpp (0 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmSignature.cpp	                        (rev 0)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmSignature.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WasmSignature.h"
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "VM.h"
+#include <wtf/FastMalloc.h>
+#include <wtf/HashFunctions.h>
+#include <wtf/PrintStream.h>
+
+namespace JSC { namespace Wasm {
+
+namespace {
+const bool verbose = false;
+}
+
+const constexpr SignatureIndex Signature::invalidIndex;
+
+void Signature::dump(PrintStream& out) const
+{
+    out.print(makeString(returnType()), " (");
+    for (SignatureArgCount arg = 0; arg < argumentCount(); ++arg)
+        out.print((arg ? ", " : ""), makeString(argument(arg)));
+    out.print(")");
+}
+
+unsigned Signature::hash() const
+{
+    uint32_t sizeToHash = allocatedSize(argumentCount()) / sizeof(allocationSizeRoundsUpTo);
+    // Assumes over-allocated memory was zero-initialized, and rounded-up to allocationSizeRoundsUpTo so that a wider hash can be performed.
+    ASSERT(sizeToHash * sizeof(allocationSizeRoundsUpTo) == allocatedSize(argumentCount()));
+    unsigned accumulator = 0xa1bcedd8u;
+    const auto* pos = reinterpret_cast<const allocationSizeRoundsUpTo*>(this);
+    for (uint32_t i = 0; i < sizeToHash; ++i)
+        accumulator = WTF::pairIntHash(accumulator, WTF::IntHash<allocationSizeRoundsUpTo>::hash(*pos));
+    return accumulator;
+}
+
+Signature* Signature::create(SignatureArgCount argumentCount)
+{
+    // Hashing relies on allocation zero-initializing trailing elements.
+    auto allocated = tryFastCalloc(allocatedSize(argumentCount), 1);
+    Signature* signature;
+    if (!allocated.getValue(signature))
+        return nullptr;
+    new (signature) Signature(argumentCount);
+    return signature;
+}
+
+Signature* Signature::createInvalid()
+{
+    Signature* signature = create(0);
+    RELEASE_ASSERT(signature);
+    new (signature) Signature(std::numeric_limits<SignatureArgCount>::max());
+    return signature;
+}
+
+void Signature::destroy(Signature* signature)
+{
+    fastFree(signature);
+}
+
+SignatureInformation::~SignatureInformation()
+{
+    for (size_t i = 0; i < m_signatures.size(); ++i)
+        Signature::destroy(m_signatures[i]);
+}
+
+SignatureInformation::SignatureInformation()
+{
+    // The zeroth entry is an invalid signature, to match invalidIndex.
+    ASSERT(!Signature::invalidIndex);
+    Signature* invalidSignature = Signature::createInvalid();
+    auto addResult = m_signatureMap.add(SignatureHash { invalidSignature }, Signature::invalidIndex);
+    RELEASE_ASSERT(addResult.isNewEntry);
+    ASSERT(Signature::invalidIndex == addResult.iterator->value);
+    m_signatures.append(invalidSignature);
+}
+
+SignatureInformation* SignatureInformation::get(VM* vm)
+{
+    std::call_once(vm->m_wasmSignatureInformationOnceFlag, [vm] {
+        vm->m_wasmSignatureInformation = std::unique_ptr<SignatureInformation>(new SignatureInformation());
+    });
+    return vm->m_wasmSignatureInformation.get();
+}
+
+SignatureIndex SignatureInformation::adopt(VM* vm, Signature* signature)
+{
+    SignatureInformation* info = get(vm);
+    LockHolder lock(info->m_lock);
+
+    SignatureIndex nextValue = info->m_signatures.size();
+    auto addResult = info->m_signatureMap.add(SignatureHash { signature }, nextValue);
+    if (addResult.isNewEntry) {
+        ASSERT(nextValue == addResult.iterator->value);
+        if (verbose)
+            dataLogLn("Adopt new signature ", *signature, " with index ", addResult.iterator->value, " hash: ", signature->hash());
+        info->m_signatures.append(signature);
+        return nextValue;
+    }
+    if (verbose)
+        dataLogLn("Existing signature ", *signature, " with index ", addResult.iterator->value, " hash: ", signature->hash());
+    Signature::destroy(signature);
+    ASSERT(addResult.iterator->value != Signature::invalidIndex);
+    return addResult.iterator->value;
+}
+
+const Signature* SignatureInformation::get(VM* vm, SignatureIndex index)
+{
+    ASSERT(index != Signature::invalidIndex);
+    SignatureInformation* info = get(vm);
+    LockHolder lock(info->m_lock);
+
+    if (verbose)
+        dataLogLn("Got signature ", *info->m_signatures.at(index), " at index ", index);
+    return info->m_signatures.at(index);
+}
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)

Added: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmSignature.h (0 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmSignature.h	                        (rev 0)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmSignature.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBASSEMBLY)
+
+#include "B3Type.h"
+#include "WasmOps.h"
+#include <cstdint>
+#include <cstring>
+#include <wtf/HashMap.h>
+#include <wtf/HashTraits.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+namespace WTF {
+class PrintStream;
+}
+
+namespace JSC {
+
+class VM;
+
+namespace Wasm {
+
+typedef uint32_t SignatureArgCount;
+typedef uint32_t SignatureIndex;
+
+class Signature {
+    static const constexpr SignatureArgCount s_retCount = 1;
+    typedef uint64_t allocationSizeRoundsUpTo;
+
+    Signature() = delete;
+    Signature(const Signature&) = delete;
+    Signature(SignatureArgCount argCount)
+        : m_argCount(argCount)
+    {
+    }
+
+    Type* storage(SignatureArgCount i)
+    {
+        return i + reinterpret_cast<Type*>(reinterpret_cast<char*>(this) + sizeof(Signature));
+    }
+    Type* storage(SignatureArgCount i) const { return const_cast<Signature*>(this)->storage(i); }
+    static uint32_t allocatedSize(SignatureArgCount argCount)
+    {
+        return WTF::roundUpToMultipleOf<sizeof(allocationSizeRoundsUpTo)>(sizeof(Signature) + (s_retCount + argCount) * sizeof(Type));
+    }
+
+public:
+    Type& returnType() { return *storage(0); }
+    Type returnType() const { return *storage(0); }
+    SignatureArgCount returnCount() const { return s_retCount; }
+    SignatureArgCount argumentCount() const { return m_argCount; }
+    Type& argument(SignatureArgCount i)
+    {
+        ASSERT(i < argumentCount());
+        return *storage(returnCount() + i);
+    }
+    Type argument(SignatureArgCount i) const { return const_cast<Signature*>(this)->argument(i); }
+
+    void dump(WTF::PrintStream& out) const;
+    bool operator==(const Signature& rhs) const
+    {
+        return allocatedSize(argumentCount()) == allocatedSize(rhs.argumentCount()) && !memcmp(this, &rhs, allocatedSize(argumentCount()));
+    }
+    unsigned hash() const;
+
+    static Signature* create(SignatureArgCount);
+    static void destroy(Signature*);
+
+    // Signatures are uniqued and, for call_indirect, validated at runtime. Tables can create invalid SignatureIndex values which cause call_indirect to fail. We use 0 as the invalidIndex so that the codegen can easily test for it and trap, and we add a token invalid entry in SignatureInformation.
+    static const constexpr SignatureIndex invalidIndex = 0;
+
+private:
+    friend class SignatureInformation;
+    static Signature* createInvalid();
+    SignatureArgCount m_argCount;
+    // Return Type and arguments are stored here.
+};
+
+struct SignatureHash {
+    const Signature* key;
+    static const Signature* empty() { return nullptr; }
+    static const Signature* deleted() { return reinterpret_cast<const Signature*>(1); }
+    SignatureHash()
+        : key(empty())
+    {
+    }
+    explicit SignatureHash(const Signature* key)
+        : key(key)
+    {
+        ASSERT(key != empty());
+        ASSERT(key != deleted());
+    }
+    explicit SignatureHash(WTF::HashTableDeletedValueType)
+        : key(deleted())
+    {
+    }
+    bool operator==(const SignatureHash& rhs) const { return equal(*this, rhs); }
+    static bool equal(const SignatureHash& lhs, const SignatureHash& rhs) { return lhs.key == rhs.key || (lhs.key && rhs.key && *lhs.key == *rhs.key); }
+    static unsigned hash(const SignatureHash& signature) { return signature.key->hash(); }
+    static const bool safeToCompareToEmptyOrDeleted = false;
+    bool isHashTableDeletedValue() const { return key == deleted(); }
+};
+
+} } // namespace JSC::Wasm
+
+
+namespace WTF {
+
+template<typename T> struct DefaultHash;
+template<> struct DefaultHash<JSC::Wasm::SignatureHash> {
+    typedef JSC::Wasm::SignatureHash Hash;
+};
+
+template<typename T> struct HashTraits;
+template<> struct HashTraits<JSC::Wasm::SignatureHash> : SimpleClassHashTraits<JSC::Wasm::SignatureHash> {
+    static const bool emptyValueIsZero = true;
+};
+
+} // namespace WTF
+
+
+namespace JSC { namespace Wasm {
+
+// Signature information is held globally on VM to allow all signatures to be unique. This is required when wasm calls another wasm instance.
+// Note: signatures are never removed from VM because that would require accounting for all WebAssembly.Module and which signatures they use. The maximum number of signatures is bounded, and isn't worth the counting overhead. We could clear everything when we reach zero outstanding WebAssembly.Module. https://bugs.webkit.org/show_bug.cgi?id=166037
+class SignatureInformation {
+    HashMap<Wasm::SignatureHash, Wasm::SignatureIndex> m_signatureMap;
+    Vector<Signature*> m_signatures;
+    Lock m_lock;
+    static SignatureInformation* get(VM*);
+    SignatureInformation();
+    SignatureInformation(const SignatureInformation&) = delete;
+
+public:
+    ~SignatureInformation();
+    static SignatureIndex WARN_UNUSED_RETURN adopt(VM*, Signature*);
+    static const Signature* WARN_UNUSED_RETURN get(VM*, SignatureIndex);
+};
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmValidate.cpp (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmValidate.cpp	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmValidate.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -92,7 +92,7 @@
         return fail(__VA_ARGS__);                   \
     } while (0)
 
-    Result WARN_UNUSED_RETURN addArguments(const Vector<Type>&);
+    Result WARN_UNUSED_RETURN addArguments(const Signature*);
     Result WARN_UNUSED_RETURN addLocal(Type, uint32_t);
     ExpressionType addConstant(Type type, uint64_t) { return type; }
 
@@ -132,7 +132,7 @@
 
     // Calls
     Result WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const Signature*, const Vector<ExpressionType>& args, ExpressionType& result);
-    Result WARN_UNUSED_RETURN addCallIndirect(const Signature*, const Vector<ExpressionType>& args, ExpressionType& result);
+    Result WARN_UNUSED_RETURN addCallIndirect(const Signature*, SignatureIndex, const Vector<ExpressionType>& args, ExpressionType& result);
 
     bool hasMemory() const { return !!m_module.memory; }
 
@@ -155,10 +155,10 @@
     const ModuleInformation& m_module;
 };
 
-auto Validate::addArguments(const Vector<Type>& args) -> Result
+auto Validate::addArguments(const Signature* signature) -> Result
 {
-    for (Type arg : args)
-        WASM_FAIL_IF_HELPER_FAILS(addLocal(arg, 1));
+    for (size_t i = 0; i < signature->argumentCount(); ++i)
+        WASM_FAIL_IF_HELPER_FAILS(addLocal(signature->argument(i), 1));
     return { };
 }
 
@@ -310,26 +310,28 @@
 
 auto Validate::addCall(unsigned, const Signature* signature, const Vector<ExpressionType>& args, ExpressionType& result) -> Result
 {
-    WASM_VALIDATOR_FAIL_IF(signature->arguments.size() != args.size(), "arity mismatch in call, got ", args.size(), " arguments, expected ", signature->arguments.size());
+    WASM_VALIDATOR_FAIL_IF(signature->argumentCount() != args.size(), "arity mismatch in call, got ", args.size(), " arguments, expected ", signature->argumentCount());
 
     for (unsigned i = 0; i < args.size(); ++i)
-        WASM_VALIDATOR_FAIL_IF(args[i] != signature->arguments[i], "argument type mismatch in call, got ", args[i], ", expected ", signature->arguments[i]);
+        WASM_VALIDATOR_FAIL_IF(args[i] != signature->argument(i), "argument type mismatch in call, got ", args[i], ", expected ", signature->argument(i));
 
-    result = signature->returnType;
+    result = signature->returnType();
     return { };
 }
 
-auto Validate::addCallIndirect(const Signature* signature, const Vector<ExpressionType>& args, ExpressionType& result) -> Result
+auto Validate::addCallIndirect(const Signature* signature, SignatureIndex signatureIndex, const Vector<ExpressionType>& args, ExpressionType& result) -> Result
 {
-    const auto argumentCount = signature->arguments.size();
+    UNUSED_PARAM(signatureIndex);
+    ASSERT(signatureIndex != Signature::invalidIndex);
+    const auto argumentCount = signature->argumentCount();
     WASM_VALIDATOR_FAIL_IF(argumentCount != args.size() - 1, "arity mismatch in call_indirect, got ", args.size() - 1, " arguments, expected ", argumentCount);
 
     for (unsigned i = 0; i < argumentCount; ++i)
-        WASM_VALIDATOR_FAIL_IF(args[i] != signature->arguments[i], "argument type mismatch in call_indirect, got ", args[i], ", expected ", signature->arguments[i]);
+        WASM_VALIDATOR_FAIL_IF(args[i] != signature->argument(i), "argument type mismatch in call_indirect, got ", args[i], ", expected ", signature->argument(i));
 
     WASM_VALIDATOR_FAIL_IF(args.last() != I32, "non-i32 call_indirect index ", args.last());
 
-    result = signature->returnType;
+    result = signature->returnType();
     return { };
 }
 
@@ -351,10 +353,10 @@
     // Think of this as penance for the sin of bad error messages.
 }
 
-Expected<void, String> validateFunction(const uint8_t* source, size_t length, const Signature* signature, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& module)
+Expected<void, String> validateFunction(VM* vm, const uint8_t* source, size_t length, const Signature* signature, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& module)
 {
-    Validate context(signature->returnType, module);
-    FunctionParser<Validate> validator(context, source, length, signature, functionIndexSpace, module);
+    Validate context(signature->returnType(), module);
+    FunctionParser<Validate> validator(vm, context, source, length, signature, functionIndexSpace, module);
     WASM_FAIL_IF_HELPER_FAILS(validator.parse());
     return { };
 }

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/WasmValidate.h (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/WasmValidate.h	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/WasmValidate.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -30,10 +30,14 @@
 #include "WasmFormat.h"
 #include <wtf/Expected.h>
 
-namespace JSC { namespace Wasm {
+namespace JSC {
 
-Expected<void, String> validateFunction(const uint8_t*, size_t, const Signature*, const ImmutableFunctionIndexSpace&, const ModuleInformation&);
+class VM;
 
+namespace Wasm {
+
+Expected<void, String> validateFunction(VM*, const uint8_t*, size_t, const Signature*, const ImmutableFunctionIndexSpace&, const ModuleInformation&);
+
 } } // namespace JSC::Wasm
 
 #endif // ENABLE(WEBASSEMBLY)

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyInstance.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -41,7 +41,7 @@
 JSWebAssemblyInstance* JSWebAssemblyInstance::create(VM& vm, Structure* structure, JSWebAssemblyModule* module, JSModuleNamespaceObject* moduleNamespaceObject)
 {
     // FIXME: These objects could be pretty big we should try to throw OOM here.
-    auto* instance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap, allocationSize(module->moduleInformation().importFunctions.size()))) JSWebAssemblyInstance(vm, structure, module->moduleInformation().importFunctions.size());
+    auto* instance = new (NotNull, allocateCell<JSWebAssemblyInstance>(vm.heap, allocationSize(module->moduleInformation().importFunctionSignatureIndices.size()))) JSWebAssemblyInstance(vm, structure, module->moduleInformation().importFunctionSignatureIndices.size());
     instance->finishCreation(vm, module, moduleNamespaceObject);
     return instance;
 }

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyModule.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -50,7 +50,11 @@
 
     const Wasm::ModuleInformation& moduleInformation() const { return *m_moduleInformation.get(); }
     SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); }
-    Wasm::Signature* signatureForFunctionIndexSpace(unsigned functionIndexSpace) const { ASSERT(functionIndexSpace < m_functionIndexSpace.size); return m_functionIndexSpace.buffer.get()[functionIndexSpace].signature; }
+    Wasm::SignatureIndex signatureForFunctionIndexSpace(unsigned functionIndexSpace) const
+    {
+        ASSERT(functionIndexSpace < m_functionIndexSpace.size);
+        return m_functionIndexSpace.buffer.get()[functionIndexSpace].signatureIndex;
+    }
     unsigned importCount() const { return m_wasmToJSStubs.size(); }
 
     JSWebAssemblyCallee* jsEntrypointCalleeFromFunctionIndexSpace(unsigned functionIndexSpace)

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/js/JSWebAssemblyTable.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -67,7 +67,7 @@
     m_jsFunctions = MallocPtr<WriteBarrier<WebAssemblyFunction>>::malloc(sizeof(WriteBarrier<WebAssemblyFunction>) * static_cast<size_t>(m_size));
     for (uint32_t i = 0; i < m_size; ++i) {
         new (&m_functions.get()[i]) Wasm::CallableFunction();
-        ASSERT(!m_functions.get()[i].signature); // We rely on this in compiled code.
+        ASSERT(m_functions.get()[i].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
         new (&m_jsFunctions.get()[i]) WriteBarrier<WebAssemblyFunction>();
     }
 }
@@ -121,7 +121,7 @@
     RELEASE_ASSERT(index < m_size);
     m_jsFunctions.get()[index] = WriteBarrier<WebAssemblyFunction>();
     m_functions.get()[index] = Wasm::CallableFunction();
-    ASSERT(!m_functions.get()[index].signature); // We rely on this in compiled code.
+    ASSERT(m_functions.get()[index].signatureIndex == Wasm::Signature::invalidIndex); // We rely on this in compiled code.
 }
 
 void JSWebAssemblyTable::setFunction(VM& vm, uint32_t index, WebAssemblyFunction* function)
@@ -128,7 +128,7 @@
 {
     RELEASE_ASSERT(index < m_size);
     m_jsFunctions.get()[index].set(vm, this, function);
-    m_functions.get()[index] = Wasm::CallableFunction(function->signature(), function->wasmEntrypoint());
+    m_functions.get()[index] = Wasm::CallableFunction(function->signatureIndex(), function->wasmEntrypoint());
 }
 
 } // namespace JSC

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/js/WebAssemblyFunction.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -52,10 +52,11 @@
     WebAssemblyFunction* wasmFunction = jsDynamicCast<WebAssemblyFunction*>(exec->jsCallee());
     if (!wasmFunction)
         return JSValue::encode(throwException(exec, scope, createTypeError(exec, "expected a WebAssembly function", defaultSourceAppender, runtimeTypeForValue(exec->jsCallee()))));
-    const Wasm::Signature* signature = wasmFunction->signature();
+    Wasm::SignatureIndex signatureIndex = wasmFunction->signatureIndex();
+    const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
 
     // FIXME is this the right behavior? https://bugs.webkit.org/show_bug.cgi?id=164876
-    if (exec->argumentCount() != signature->arguments.size())
+    if (exec->argumentCount() != signature->argumentCount())
         return JSValue::encode(throwException(exec, scope, createNotEnoughArgumentsError(exec, defaultSourceAppender)));
 
     // FIXME is this boxing correct? https://bugs.webkit.org/show_bug.cgi?id=164876
@@ -62,7 +63,7 @@
     Vector<JSValue> boxedArgs;
     for (unsigned argIndex = 0; argIndex < exec->argumentCount(); ++argIndex) {
         JSValue arg = exec->uncheckedArgument(argIndex);
-        switch (signature->arguments[argIndex]) {
+        switch (signature->argument(argIndex)) {
         case Wasm::I32:
             arg = JSValue::decode(arg.toInt32(exec));
             break;
@@ -121,7 +122,7 @@
     vm.topJSWebAssemblyInstance = prevJSWebAssemblyInstance;
 
     // FIXME is this correct? https://bugs.webkit.org/show_bug.cgi?id=164876
-    switch (signature()->returnType) {
+    switch (m_returnType) {
     case Wasm::Void:
         return JSValue::encode(jsUndefined());
     case Wasm::I32:
@@ -140,12 +141,12 @@
     return EncodedJSValue();
 }
 
-WebAssemblyFunction* WebAssemblyFunction::create(VM& vm, JSGlobalObject* globalObject, unsigned length, const String& name, JSWebAssemblyInstance* instance, JSWebAssemblyCallee* jsEntrypoint, JSWebAssemblyCallee* wasmEntrypoint, Wasm::Signature* signature)
+WebAssemblyFunction* WebAssemblyFunction::create(VM& vm, JSGlobalObject* globalObject, unsigned length, const String& name, JSWebAssemblyInstance* instance, JSWebAssemblyCallee* jsEntrypoint, JSWebAssemblyCallee* wasmEntrypoint, Wasm::SignatureIndex signatureIndex)
 {
     NativeExecutable* executable = vm.getHostFunction(callWebAssemblyFunction, NoIntrinsic, callHostFunctionAsConstructor, nullptr, name);
     Structure* structure = globalObject->webAssemblyFunctionStructure();
-    WebAssemblyFunction* function = new (NotNull, allocateCell<WebAssemblyFunction>(vm.heap)) WebAssemblyFunction(vm, globalObject, structure);
-    function->finishCreation(vm, executable, length, name, instance, jsEntrypoint, wasmEntrypoint, signature);
+    WebAssemblyFunction* function = new (NotNull, allocateCell<WebAssemblyFunction>(vm.heap)) WebAssemblyFunction(vm, globalObject, structure, signatureIndex);
+    function->finishCreation(vm, executable, length, name, instance, jsEntrypoint, wasmEntrypoint);
     return function;
 }
 
@@ -155,9 +156,13 @@
     return Structure::create(vm, globalObject, prototype, TypeInfo(JSFunctionType, StructureFlags), info());
 }
 
-WebAssemblyFunction::WebAssemblyFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure)
+WebAssemblyFunction::WebAssemblyFunction(VM& vm, JSGlobalObject* globalObject, Structure* structure, Wasm::SignatureIndex signatureIndex)
     : Base(vm, globalObject, structure)
+    , m_signatureIndex(signatureIndex)
 {
+    // Don't cache the signature pointer: it's a global on VM and can change as new WebAssembly.Module are created.
+    const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, m_signatureIndex);
+    m_returnType = signature->returnType();
 }
 
 void WebAssemblyFunction::visitChildren(JSCell* cell, SlotVisitor& visitor)
@@ -170,7 +175,7 @@
     visitor.append(thisObject->m_wasmEntrypoint);
 }
 
-void WebAssemblyFunction::finishCreation(VM& vm, NativeExecutable* executable, unsigned length, const String& name, JSWebAssemblyInstance* instance, JSWebAssemblyCallee* jsEntrypoint, JSWebAssemblyCallee* wasmEntrypoint, Wasm::Signature* signature)
+void WebAssemblyFunction::finishCreation(VM& vm, NativeExecutable* executable, unsigned length, const String& name, JSWebAssemblyInstance* instance, JSWebAssemblyCallee* jsEntrypoint, JSWebAssemblyCallee* wasmEntrypoint)
 {
     Base::finishCreation(vm, executable, length, name);
     ASSERT(inherits(info()));
@@ -178,7 +183,6 @@
     ASSERT(jsEntrypoint != wasmEntrypoint);
     m_jsEntrypoint.set(vm, this, jsEntrypoint);
     m_wasmEntrypoint.set(vm, this, wasmEntrypoint);
-    m_signature = signature;
 }
 
 } // namespace JSC

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/js/WebAssemblyFunction.h (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/js/WebAssemblyFunction.h	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/js/WebAssemblyFunction.h	2017-01-06 01:47:27 UTC (rev 210402)
@@ -41,10 +41,6 @@
 class Compilation;
 }
 
-namespace Wasm {
-struct Signature;
-}
-
 class WebAssemblyFunction : public JSFunction {
 public:
     typedef JSFunction Base;
@@ -53,15 +49,11 @@
 
     DECLARE_EXPORT_INFO;
 
-    JS_EXPORT_PRIVATE static WebAssemblyFunction* create(VM&, JSGlobalObject*, unsigned, const String&, JSWebAssemblyInstance*, JSWebAssemblyCallee* jsEntrypoint, JSWebAssemblyCallee* wasmEntrypoint, Wasm::Signature*);
+    JS_EXPORT_PRIVATE static WebAssemblyFunction* create(VM&, JSGlobalObject*, unsigned, const String&, JSWebAssemblyInstance*, JSWebAssemblyCallee* jsEntrypoint, JSWebAssemblyCallee* wasmEntrypoint, Wasm::SignatureIndex);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     JSWebAssemblyInstance* instance() const { return m_instance.get(); }
-    Wasm::Signature* signature()
-    { 
-        ASSERT(m_signature);
-        return m_signature;
-    }
+    Wasm::SignatureIndex signatureIndex() const { return m_signatureIndex; }
     EncodedJSValue call(VM&, ProtoCallFrame*);
     void* wasmEntrypoint() { return m_wasmEntrypoint->entrypoint(); }
 
@@ -68,15 +60,16 @@
 protected:
     static void visitChildren(JSCell*, SlotVisitor&);
 
-    void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name, JSWebAssemblyInstance*, JSWebAssemblyCallee* jsEntrypoint, JSWebAssemblyCallee* wasmEntrypoint, Wasm::Signature*);
+    void finishCreation(VM&, NativeExecutable*, unsigned length, const String& name, JSWebAssemblyInstance*, JSWebAssemblyCallee* jsEntrypoint, JSWebAssemblyCallee* wasmEntrypoint);
 
 private:
-    WebAssemblyFunction(VM&, JSGlobalObject*, Structure*);
+    WebAssemblyFunction(VM&, JSGlobalObject*, Structure*, Wasm::SignatureIndex);
 
     WriteBarrier<JSWebAssemblyInstance> m_instance;
     WriteBarrier<JSWebAssemblyCallee> m_jsEntrypoint;
     WriteBarrier<JSWebAssemblyCallee> m_wasmEntrypoint;
-    Wasm::Signature* m_signature;
+    Wasm::SignatureIndex m_signatureIndex;
+    Wasm::Type m_returnType;
 };
 
 } // namespace JSC

Modified: branches/safari-603-branch/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp (210401 => 210402)


--- branches/safari-603-branch/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp	2017-01-06 01:47:16 UTC (rev 210401)
+++ branches/safari-603-branch/Source/_javascript_Core/wasm/js/WebAssemblyModuleRecord.cpp	2017-01-06 01:47:27 UTC (rev 210402)
@@ -37,6 +37,7 @@
 #include "JSWebAssemblyModule.h"
 #include "ProtoCallFrame.h"
 #include "WasmFormat.h"
+#include "WasmSignature.h"
 #include "WebAssemblyFunction.h"
 #include <limits>
 
@@ -120,8 +121,9 @@
             //     c. Return func.
             JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
             JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
-            Wasm::Signature* signature = module->signatureForFunctionIndexSpace(exp.kindIndex);
-            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->arguments.size(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signature);
+            Wasm::SignatureIndex signatureIndex = module->signatureForFunctionIndexSpace(exp.kindIndex);
+            const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
+            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), exp.field.string(), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
             exportedValue = function;
             if (hasStart && startFunctionIndexSpace == exp.kindIndex)
                 m_startFunction.set(vm, this, function);
@@ -176,16 +178,17 @@
     }
 
     if (hasStart) {
-        Wasm::Signature* signature = module->signatureForFunctionIndexSpace(startFunctionIndexSpace);
+        Wasm::SignatureIndex signatureIndex = module->signatureForFunctionIndexSpace(startFunctionIndexSpace);
+        const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
         // The start function must not take any arguments or return anything. This is enforced by the parser.
-        ASSERT(!signature->arguments.size());
-        ASSERT(signature->returnType == Wasm::Void);
+        ASSERT(!signature->argumentCount());
+        ASSERT(signature->returnType() == Wasm::Void);
         // FIXME can start call imports / tables? This assumes not. https://github.com/WebAssembly/design/issues/896
         if (!m_startFunction.get()) {
             // The start function wasn't added above. It must be a purely internal function.
             JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
             JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(startFunctionIndexSpace);
-            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->arguments.size(), "start", instance, jsEntrypointCallee, wasmEntrypointCallee, signature);
+            WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature->argumentCount(), "start", instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
             m_startFunction.set(vm, this, function);
         }
     }
@@ -237,13 +240,14 @@
 
                 JSWebAssemblyCallee* jsEntrypointCallee = module->jsEntrypointCalleeFromFunctionIndexSpace(functionIndex);
                 JSWebAssemblyCallee* wasmEntrypointCallee = module->wasmEntrypointCalleeFromFunctionIndexSpace(functionIndex);
-                Wasm::Signature* signature = module->signatureForFunctionIndexSpace(functionIndex);
+                Wasm::SignatureIndex signatureIndex = module->signatureForFunctionIndexSpace(functionIndex);
+                const Wasm::Signature* signature = Wasm::SignatureInformation::get(&vm, signatureIndex);
                 // FIXME: Say we export local function "foo" at funciton index 0.
                 // What if we also set it to the table an Element w/ index 0.
                 // Does (new Instance(...)).exports.foo === table.get(0)?
                 // https://bugs.webkit.org/show_bug.cgi?id=165825
                 WebAssemblyFunction* function = WebAssemblyFunction::create(
-                    vm, m_instance->globalObject(), signature->arguments.size(), String(), m_instance.get(), jsEntrypointCallee, wasmEntrypointCallee, signature);
+                    vm, m_instance->globalObject(), signature->argumentCount(), String(), m_instance.get(), jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
 
                 table->setFunction(vm, tableIndex, function);
                 ++tableIndex;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to