WebAssembly: ModuleInformation should be a ref counted thing that can be shared acros...
authorkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 5 Apr 2017 00:55:54 +0000 (00:55 +0000)
committerkeith_miller@apple.com <keith_miller@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 5 Apr 2017 00:55:54 +0000 (00:55 +0000)
https://bugs.webkit.org/show_bug.cgi?id=170478

Reviewed by Saam Barati.

Source/JavaScriptCore:

ModuleInformation has been moved to its own file and is now
ThreadSafeRefCounted.  All the Strings we used to keep in the
ModuleInformation have been switched to Vector<LChar> this has the
advantage that it can be passed across threads. However, this does
mean that we need to decode the utf8 strings in each thread. This
is likely not a problem because:

1) most modules have few imports/exports/custom sections.
2) most of the time they are ascii so the conversion is cheap.
3) we only have to do it once per thread, and there shouldn't be too many.

This patch also removes
moduleSignatureIndicesToUniquedSignatureIndices since that
information can already be recovered from the
SignatureInformation.

* JavaScriptCore.xcodeproj/project.pbxproj:
* jsc.cpp:
(functionTestWasmModuleFunctions):
* runtime/Identifier.h:
(JSC::Identifier::fromString):
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::parseAndCompile):
* wasm/WasmB3IRGenerator.h:
* wasm/WasmFormat.cpp:
(JSC::Wasm::makeString):
(JSC::Wasm::ModuleInformation::~ModuleInformation): Deleted.
* wasm/WasmFormat.h:
(JSC::Wasm::makeString):
(JSC::Wasm::ModuleInformation::functionIndexSpaceSize): Deleted.
(JSC::Wasm::ModuleInformation::isImportedFunctionFromFunctionIndexSpace): Deleted.
(JSC::Wasm::ModuleInformation::signatureIndexFromFunctionIndexSpace): Deleted.
(JSC::Wasm::ModuleInformation::importFunctionCount): Deleted.
(JSC::Wasm::ModuleInformation::internalFunctionCount): Deleted.
* wasm/WasmFunctionParser.h:
(JSC::Wasm::FunctionParser<Context>::FunctionParser):
* wasm/WasmModuleInformation.cpp: Copied from Source/JavaScriptCore/wasm/WasmValidate.h.
(JSC::Wasm::ModuleInformation::~ModuleInformation):
* wasm/WasmModuleInformation.h: Added.
(JSC::Wasm::ModuleInformation::functionIndexSpaceSize):
(JSC::Wasm::ModuleInformation::isImportedFunctionFromFunctionIndexSpace):
(JSC::Wasm::ModuleInformation::signatureIndexFromFunctionIndexSpace):
(JSC::Wasm::ModuleInformation::importFunctionCount):
(JSC::Wasm::ModuleInformation::internalFunctionCount):
(JSC::Wasm::ModuleInformation::ModuleInformation):
* wasm/WasmModuleParser.cpp:
* wasm/WasmModuleParser.h:
(JSC::Wasm::ModuleParser::ModuleParser):
* wasm/WasmParser.h:
(JSC::Wasm::Parser<SuccessType>::consumeUTF8String):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::Plan):
(JSC::Wasm::Plan::parseAndValidateModule):
(JSC::Wasm::Plan::prepare):
(JSC::Wasm::Plan::compileFunctions):
(JSC::Wasm::Plan::complete):
(JSC::Wasm::Plan::cancel):
* wasm/WasmPlan.h:
(JSC::Wasm::Plan::internalFunctionCount):
(JSC::Wasm::Plan::takeModuleInformation):
* wasm/WasmSignature.cpp:
(JSC::Wasm::SignatureInformation::get):
* wasm/WasmSignature.h:
* wasm/WasmValidate.cpp:
(JSC::Wasm::validateFunction):
* wasm/WasmValidate.h:
* wasm/js/JSWebAssemblyHelpers.h:
(JSC::createSourceBufferFromValue):
* wasm/js/JSWebAssemblyModule.cpp:
(JSC::JSWebAssemblyModule::createStub):
(JSC::JSWebAssemblyModule::JSWebAssemblyModule):
(JSC::JSWebAssemblyModule::finishCreation):
* wasm/js/JSWebAssemblyModule.h:
(JSC::JSWebAssemblyModule::moduleInformation):
(JSC::JSWebAssemblyModule::source):
* wasm/js/WebAssemblyInstanceConstructor.cpp:
(JSC::constructJSWebAssemblyInstance):
* wasm/js/WebAssemblyModuleConstructor.cpp:
(JSC::WebAssemblyModuleConstructor::createModule):
* wasm/js/WebAssemblyModulePrototype.cpp:
(JSC::webAssemblyModuleProtoCustomSections):
(JSC::webAssemblyModuleProtoImports):
(JSC::webAssemblyModuleProtoExports):
* wasm/js/WebAssemblyModuleRecord.cpp:
(JSC::WebAssemblyModuleRecord::link):
* wasm/js/WebAssemblyModuleRecord.h:
* wasm/js/WebAssemblyPrototype.cpp:
(JSC::webAssemblyCompileFunc):
(JSC::instantiate):
(JSC::compileAndInstantiate):

Source/WTF:

This adds a new String::fromUTF8 that converts a vector of characters to
a string.

Also, it cleans up some style.

* wtf/text/WTFString.h:
(WTF::String::fromUTF8):
* wtf/unicode/UTF8.cpp:
(WTF::Unicode::convertLatin1ToUTF8):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214919 268f45cc-cd09-0410-ab3c-d52691b4dbfc

33 files changed:
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/jsc.cpp
Source/JavaScriptCore/runtime/Identifier.h
Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
Source/JavaScriptCore/wasm/WasmB3IRGenerator.h
Source/JavaScriptCore/wasm/WasmFormat.cpp
Source/JavaScriptCore/wasm/WasmFormat.h
Source/JavaScriptCore/wasm/WasmFunctionParser.h
Source/JavaScriptCore/wasm/WasmModuleInformation.cpp [new file with mode: 0644]
Source/JavaScriptCore/wasm/WasmModuleInformation.h [new file with mode: 0644]
Source/JavaScriptCore/wasm/WasmModuleParser.cpp
Source/JavaScriptCore/wasm/WasmModuleParser.h
Source/JavaScriptCore/wasm/WasmParser.h
Source/JavaScriptCore/wasm/WasmPlan.cpp
Source/JavaScriptCore/wasm/WasmPlan.h
Source/JavaScriptCore/wasm/WasmSignature.cpp
Source/JavaScriptCore/wasm/WasmSignature.h
Source/JavaScriptCore/wasm/WasmValidate.cpp
Source/JavaScriptCore/wasm/WasmValidate.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyHelpers.h
Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.cpp
Source/JavaScriptCore/wasm/js/JSWebAssemblyModule.h
Source/JavaScriptCore/wasm/js/WebAssemblyInstanceConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleConstructor.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModulePrototype.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.cpp
Source/JavaScriptCore/wasm/js/WebAssemblyModuleRecord.h
Source/JavaScriptCore/wasm/js/WebAssemblyPrototype.cpp
Source/WTF/ChangeLog
Source/WTF/wtf/text/WTFString.h
Source/WTF/wtf/unicode/UTF8.cpp

index a762fff..fbb76fc 100644 (file)
@@ -943,6 +943,7 @@ set(JavaScriptCore_SOURCES
     wasm/WasmFormat.cpp
     wasm/WasmMemory.cpp
     wasm/WasmMemoryInformation.cpp
+    wasm/WasmModuleInformation.cpp
     wasm/WasmModuleParser.cpp
     wasm/WasmPageCount.cpp
     wasm/WasmPlan.cpp
index b3f95c1..840ad3b 100644 (file)
@@ -1,3 +1,101 @@
+2017-04-04  Keith Miller  <keith_miller@apple.com>
+
+        WebAssembly: ModuleInformation should be a ref counted thing that can be shared across threads.
+        https://bugs.webkit.org/show_bug.cgi?id=170478
+
+        Reviewed by Saam Barati.
+
+        ModuleInformation has been moved to its own file and is now
+        ThreadSafeRefCounted.  All the Strings we used to keep in the
+        ModuleInformation have been switched to Vector<LChar> this has the
+        advantage that it can be passed across threads. However, this does
+        mean that we need to decode the utf8 strings in each thread. This
+        is likely not a problem because:
+
+        1) most modules have few imports/exports/custom sections.
+        2) most of the time they are ascii so the conversion is cheap.
+        3) we only have to do it once per thread, and there shouldn't be too many.
+
+        This patch also removes
+        moduleSignatureIndicesToUniquedSignatureIndices since that
+        information can already be recovered from the
+        SignatureInformation.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * jsc.cpp:
+        (functionTestWasmModuleFunctions):
+        * runtime/Identifier.h:
+        (JSC::Identifier::fromString):
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::parseAndCompile):
+        * wasm/WasmB3IRGenerator.h:
+        * wasm/WasmFormat.cpp:
+        (JSC::Wasm::makeString):
+        (JSC::Wasm::ModuleInformation::~ModuleInformation): Deleted.
+        * wasm/WasmFormat.h:
+        (JSC::Wasm::makeString):
+        (JSC::Wasm::ModuleInformation::functionIndexSpaceSize): Deleted.
+        (JSC::Wasm::ModuleInformation::isImportedFunctionFromFunctionIndexSpace): Deleted.
+        (JSC::Wasm::ModuleInformation::signatureIndexFromFunctionIndexSpace): Deleted.
+        (JSC::Wasm::ModuleInformation::importFunctionCount): Deleted.
+        (JSC::Wasm::ModuleInformation::internalFunctionCount): Deleted.
+        * wasm/WasmFunctionParser.h:
+        (JSC::Wasm::FunctionParser<Context>::FunctionParser):
+        * wasm/WasmModuleInformation.cpp: Copied from Source/JavaScriptCore/wasm/WasmValidate.h.
+        (JSC::Wasm::ModuleInformation::~ModuleInformation):
+        * wasm/WasmModuleInformation.h: Added.
+        (JSC::Wasm::ModuleInformation::functionIndexSpaceSize):
+        (JSC::Wasm::ModuleInformation::isImportedFunctionFromFunctionIndexSpace):
+        (JSC::Wasm::ModuleInformation::signatureIndexFromFunctionIndexSpace):
+        (JSC::Wasm::ModuleInformation::importFunctionCount):
+        (JSC::Wasm::ModuleInformation::internalFunctionCount):
+        (JSC::Wasm::ModuleInformation::ModuleInformation):
+        * wasm/WasmModuleParser.cpp:
+        * wasm/WasmModuleParser.h:
+        (JSC::Wasm::ModuleParser::ModuleParser):
+        * wasm/WasmParser.h:
+        (JSC::Wasm::Parser<SuccessType>::consumeUTF8String):
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::Plan):
+        (JSC::Wasm::Plan::parseAndValidateModule):
+        (JSC::Wasm::Plan::prepare):
+        (JSC::Wasm::Plan::compileFunctions):
+        (JSC::Wasm::Plan::complete):
+        (JSC::Wasm::Plan::cancel):
+        * wasm/WasmPlan.h:
+        (JSC::Wasm::Plan::internalFunctionCount):
+        (JSC::Wasm::Plan::takeModuleInformation):
+        * wasm/WasmSignature.cpp:
+        (JSC::Wasm::SignatureInformation::get):
+        * wasm/WasmSignature.h:
+        * wasm/WasmValidate.cpp:
+        (JSC::Wasm::validateFunction):
+        * wasm/WasmValidate.h:
+        * wasm/js/JSWebAssemblyHelpers.h:
+        (JSC::createSourceBufferFromValue):
+        * wasm/js/JSWebAssemblyModule.cpp:
+        (JSC::JSWebAssemblyModule::createStub):
+        (JSC::JSWebAssemblyModule::JSWebAssemblyModule):
+        (JSC::JSWebAssemblyModule::finishCreation):
+        * wasm/js/JSWebAssemblyModule.h:
+        (JSC::JSWebAssemblyModule::moduleInformation):
+        (JSC::JSWebAssemblyModule::source):
+        * wasm/js/WebAssemblyInstanceConstructor.cpp:
+        (JSC::constructJSWebAssemblyInstance):
+        * wasm/js/WebAssemblyModuleConstructor.cpp:
+        (JSC::WebAssemblyModuleConstructor::createModule):
+        * wasm/js/WebAssemblyModulePrototype.cpp:
+        (JSC::webAssemblyModuleProtoCustomSections):
+        (JSC::webAssemblyModuleProtoImports):
+        (JSC::webAssemblyModuleProtoExports):
+        * wasm/js/WebAssemblyModuleRecord.cpp:
+        (JSC::WebAssemblyModuleRecord::link):
+        * wasm/js/WebAssemblyModuleRecord.h:
+        * wasm/js/WebAssemblyPrototype.cpp:
+        (JSC::webAssemblyCompileFunc):
+        (JSC::instantiate):
+        (JSC::compileAndInstantiate):
+
 2017-04-04  Filip Pizlo  <fpizlo@apple.com>
 
         B3::fixSSA() needs a tune-up
index cdc1f76..3ed537d 100644 (file)
                53C6FEF11E8AFE0C00B18425 /* WasmOpcodeOrigin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53C6FEF01E8AFE0C00B18425 /* WasmOpcodeOrigin.cpp */; };
                53D444DC1DAF08AB00B92784 /* B3WasmAddressValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 53D444DB1DAF08AB00B92784 /* B3WasmAddressValue.h */; };
                53D444DE1DAF09A000B92784 /* B3WasmAddressValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53D444DD1DAF09A000B92784 /* B3WasmAddressValue.cpp */; };
+               53E777E31E92E265007CBEC4 /* WasmModuleInformation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 53E777E11E92E265007CBEC4 /* WasmModuleInformation.cpp */; };
+               53E777E41E92E265007CBEC4 /* WasmModuleInformation.h in Headers */ = {isa = PBXBuildFile; fileRef = 53E777E21E92E265007CBEC4 /* WasmModuleInformation.h */; };
                53F40E851D58F9770099A1B6 /* WasmSections.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E841D58F9770099A1B6 /* WasmSections.h */; };
                53F40E8B1D5901BB0099A1B6 /* WasmFunctionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */; };
                53F40E8D1D5901F20099A1B6 /* WasmParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8C1D5901F20099A1B6 /* WasmParser.h */; };
                53C6FEF01E8AFE0C00B18425 /* WasmOpcodeOrigin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmOpcodeOrigin.cpp; sourceTree = "<group>"; };
                53D444DB1DAF08AB00B92784 /* B3WasmAddressValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = B3WasmAddressValue.h; path = b3/B3WasmAddressValue.h; sourceTree = "<group>"; };
                53D444DD1DAF09A000B92784 /* B3WasmAddressValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = B3WasmAddressValue.cpp; path = b3/B3WasmAddressValue.cpp; sourceTree = "<group>"; };
+               53E777E11E92E265007CBEC4 /* WasmModuleInformation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmModuleInformation.cpp; sourceTree = "<group>"; };
+               53E777E21E92E265007CBEC4 /* WasmModuleInformation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmModuleInformation.h; sourceTree = "<group>"; };
                53F256E11B87E28000B4B768 /* JSTypedArrayViewPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSTypedArrayViewPrototype.cpp; sourceTree = "<group>"; };
                53F40E841D58F9770099A1B6 /* WasmSections.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmSections.h; sourceTree = "<group>"; };
                53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmFunctionParser.h; sourceTree = "<group>"; };
                                535557131D9D9EA5006D583B /* WasmMemory.h */,
                                79B759711DFA4C600052174C /* WasmMemoryInformation.cpp */,
                                79B759721DFA4C600052174C /* WasmMemoryInformation.h */,
+                               53E777E11E92E265007CBEC4 /* WasmModuleInformation.cpp */,
+                               53E777E21E92E265007CBEC4 /* WasmModuleInformation.h */,
                                53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */,
                                53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */,
                                ADB6F67C1E15D7500082F384 /* WasmPageCount.cpp */,
                                0FFFC95A14EF90A900C72532 /* DFGCSEPhase.h in Headers */,
                                0F2FC77316E12F740038D976 /* DFGDCEPhase.h in Headers */,
                                0F8F2B9A172F0501007DBDA5 /* DFGDesiredIdentifiers.h in Headers */,
+                               53E777E41E92E265007CBEC4 /* WasmModuleInformation.h in Headers */,
                                0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */,
                                C2C0F7CE17BBFC5B00464FE4 /* DFGDesiredTransitions.h in Headers */,
                                0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */,
                                0FC0977214693AF900CF2442 /* DFGOSRExitCompiler64.cpp in Sources */,
                                0F7025A91714B0FA00382C0E /* DFGOSRExitCompilerCommon.cpp in Sources */,
                                0F392C891B46188400844728 /* DFGOSRExitFuzz.cpp in Sources */,
+                               53E777E31E92E265007CBEC4 /* WasmModuleInformation.cpp in Sources */,
                                0FEFC9AA1681A3B300567F53 /* DFGOSRExitJumpPlaceholder.cpp in Sources */,
                                0F235BED17178E7300690C7F /* DFGOSRExitPreparation.cpp in Sources */,
                                0F6237971AE45CA700D402EA /* DFGPhantomInsertionPhase.cpp in Sources */,
index 852f680..678ab38 100644 (file)
@@ -3214,7 +3214,7 @@ static EncodedJSValue JSC_HOST_CALL functionTestWasmModuleFunctions(ExecState* e
                 lastIndex = calleeIndex;
             });
     }
-    std::unique_ptr<Wasm::ModuleInformation> moduleInformation = plan->takeModuleInformation();
+    Ref<Wasm::ModuleInformation> moduleInformation = plan->takeModuleInformation();
     RELEASE_ASSERT(!moduleInformation->memory);
 
     for (uint32_t i = 0; i < functionCount; ++i) {
index a963b43..bc3dbd4 100644 (file)
@@ -122,6 +122,7 @@ public:
     static Identifier fromString(ExecState*, const AtomicString&);
     static Identifier fromString(ExecState*, const String&);
     static Identifier fromString(ExecState*, const char*);
+    static Identifier fromString(VM* vm, const Vector<LChar>& characters) { return fromString(vm, characters.data(), characters.size()); }
 
     static Identifier fromUid(VM*, UniquedStringImpl* uid);
     static Identifier fromUid(ExecState*, UniquedStringImpl* uid);
index 8cb84ad..f827add 100644 (file)
@@ -205,7 +205,7 @@ public:
 
     // Calls
     PartialResult WARN_UNUSED_RETURN addCall(uint32_t calleeIndex, const Signature&, Vector<ExpressionType>& args, ExpressionType& result);
-    PartialResult WARN_UNUSED_RETURN addCallIndirect(const Signature&, SignatureIndex, Vector<ExpressionType>& args, ExpressionType& result);
+    PartialResult WARN_UNUSED_RETURN addCallIndirect(const Signature&, Vector<ExpressionType>& args, ExpressionType& result);
     PartialResult WARN_UNUSED_RETURN addUnreachable();
 
     void dump(const Vector<ControlEntry>& controlStack, const ExpressionList* expressionStack);
@@ -968,9 +968,8 @@ auto B3IRGenerator::addCall(uint32_t functionIndex, const Signature& signature,
     return { };
 }
 
-auto B3IRGenerator::addCallIndirect(const Signature& signature, SignatureIndex signatureIndex, Vector<ExpressionType>& args, ExpressionType& result) -> PartialResult
+auto B3IRGenerator::addCallIndirect(const Signature& signature, Vector<ExpressionType>& args, ExpressionType& result) -> PartialResult
 {
-    ASSERT(signatureIndex != Signature::invalidIndex);
     ExpressionType calleeIndex = args.takeLast();
     ASSERT(signature.argumentCount() == args.size());
 
@@ -1017,7 +1016,7 @@ auto B3IRGenerator::addCallIndirect(const Signature& signature, SignatureIndex s
 
     // Check the signature matches the value we expect.
     {
-        ExpressionType expectedSignatureIndex = m_currentBlock->appendNew<Const32Value>(m_proc, origin(), signatureIndex);
+        ExpressionType expectedSignatureIndex = m_currentBlock->appendNew<Const32Value>(m_proc, origin(), SignatureInformation::get(signature));
         CheckValue* check = m_currentBlock->appendNew<CheckValue>(m_proc, Check, origin(),
             m_currentBlock->appendNew<Value>(m_proc, NotEqual, origin(), calleeSignatureIndex, expectedSignatureIndex));
 
@@ -1269,7 +1268,7 @@ auto B3IRGenerator::origin() -> Origin
     return bitwise_cast<Origin>(OpcodeOrigin(m_parser->currentOpcode(), m_parser->currentOpcodeStartingOffset()));
 }
 
-Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(CompilationContext& compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature& signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ModuleInformation& info, const Vector<SignatureIndex>& moduleSignatureIndicesToUniquedSignatureIndices, MemoryMode mode, unsigned optLevel)
+Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(CompilationContext& compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature& signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ModuleInformation& info, MemoryMode mode, unsigned optLevel)
 {
     auto result = std::make_unique<WasmInternalFunction>();
 
@@ -1292,7 +1291,7 @@ Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(Compilat
     procedure.setOptLevel(optLevel);
 
     B3IRGenerator context(info, procedure, result.get(), unlinkedWasmToWasmCalls, mode);
-    FunctionParser<B3IRGenerator> parser(context, functionStart, functionLength, signature, info, moduleSignatureIndicesToUniquedSignatureIndices);
+    FunctionParser<B3IRGenerator> parser(context, functionStart, functionLength, signature, info);
     WASM_FAIL_IF_HELPER_FAILS(parser.parse());
 
     context.insertConstants();
index c08b8d1..1ec101f 100644 (file)
@@ -30,8 +30,8 @@
 #include "B3Common.h"
 #include "B3Compilation.h"
 #include "CCallHelpers.h"
-#include "WasmFormat.h"
 #include "WasmMemory.h"
+#include "WasmModuleInformation.h"
 #include <wtf/Expected.h>
 
 extern "C" void dumpProcedure(void*);
@@ -48,7 +48,7 @@ struct CompilationContext {
     CCallHelpers::Call jsEntrypointToWasmEntrypointCall;
 };
 
-Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(CompilationContext&, const uint8_t*, size_t, const Signature&, Vector<UnlinkedWasmToWasmCall>&, const ModuleInformation&, const Vector<SignatureIndex>&, MemoryMode, unsigned optLevel);
+Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(CompilationContext&, const uint8_t*, size_t, const Signature&, Vector<UnlinkedWasmToWasmCall>&, const ModuleInformation&, MemoryMode, unsigned optLevel);
 
 } } // namespace JSC::Wasm
 
index b047875..e260601 100644 (file)
@@ -55,7 +55,12 @@ Segment::Ptr Segment::adoptPtr(Segment* segment)
     return Ptr(segment, &Segment::destroy);
 }
 
-JS_EXPORT_PRIVATE ModuleInformation::~ModuleInformation() { }
+String makeString(const Vector<LChar>& characters)
+{
+    String result = String::fromUTF8(characters);
+    ASSERT(result);
+    return result;
+}
 
 } } // namespace JSC::Wasm
 
index e80dd7a..67f7056 100644 (file)
@@ -89,7 +89,7 @@ static_assert(static_cast<int>(ExternalKind::Table)    == 1, "Wasm needs Table t
 static_assert(static_cast<int>(ExternalKind::Memory)   == 2, "Wasm needs Memory to have the value 2");
 static_assert(static_cast<int>(ExternalKind::Global)   == 3, "Wasm needs Global to have the value 3");
 
-static inline const char* makeString(ExternalKind kind)
+inline const char* makeString(ExternalKind kind)
 {
     switch (kind) {
     case ExternalKind::Function: return "function";
@@ -102,18 +102,20 @@ static inline const char* makeString(ExternalKind kind)
 }
 
 struct Import {
-    String module;
-    String field;
+    const Vector<LChar> module;
+    const Vector<LChar> field;
     ExternalKind kind;
     unsigned kindIndex; // Index in the vector of the corresponding kind.
 };
 
 struct Export {
-    String field;
+    const Vector<LChar> field;
     ExternalKind kind;
     unsigned kindIndex; // Index in the vector of the corresponding kind.
 };
 
+String makeString(const Vector<LChar>& characters);
+
 struct Global {
     enum Mutability : uint8_t {
         // FIXME auto-generate this. https://bugs.webkit.org/show_bug.cgi?id=165231
@@ -226,46 +228,10 @@ private:
 };
     
 struct CustomSection {
-    String name;
+    Vector<LChar> name;
     Vector<uint8_t> payload;
 };
 
-struct ModuleInformation {
-    Vector<Import> imports;
-    Vector<SignatureIndex> importFunctionSignatureIndices;
-    Vector<SignatureIndex> internalFunctionSignatureIndices;
-    Vector<Ref<Signature>> usedSignatures;
-
-    MemoryInformation memory;
-
-    Vector<Export> exports;
-    std::optional<uint32_t> startFunctionIndexSpace;
-    Vector<Segment::Ptr> data;
-    Vector<Element> elements;
-    TableInformation tableInformation;
-    Vector<Global> globals;
-    unsigned firstInternalGlobal { 0 };
-    Vector<CustomSection> customSections;
-
-    size_t functionIndexSpaceSize() const { return importFunctionSignatureIndices.size() + internalFunctionSignatureIndices.size(); }
-    bool isImportedFunctionFromFunctionIndexSpace(size_t functionIndex) const
-    {
-        ASSERT(functionIndex < functionIndexSpaceSize());
-        return functionIndex < importFunctionSignatureIndices.size();
-    }
-    SignatureIndex signatureIndexFromFunctionIndexSpace(size_t functionIndex) const
-    {
-        return isImportedFunctionFromFunctionIndexSpace(functionIndex)
-            ? importFunctionSignatureIndices[functionIndex]
-            : internalFunctionSignatureIndices[functionIndex - importFunctionSignatureIndices.size()];
-    }
-
-    uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); }
-    uint32_t internalFunctionCount() const { return internalFunctionSignatureIndices.size(); }
-
-    ~ModuleInformation();
-};
-
 struct UnlinkedWasmToWasmCall {
     CodeLocationCall callLocation;
     size_t functionIndex;
index 07f53ab..1fa0058 100644 (file)
@@ -46,7 +46,7 @@ public:
     typedef typename Context::ControlType ControlType;
     typedef typename Context::ExpressionList ExpressionList;
 
-    FunctionParser(Context&, const uint8_t* functionStart, size_t functionLength, const Signature&, const ModuleInformation&, const Vector<SignatureIndex>&);
+    FunctionParser(Context&, const uint8_t* functionStart, size_t functionLength, const Signature&, const ModuleInformation&);
 
     Result WARN_UNUSED_RETURN parse();
 
@@ -86,7 +86,6 @@ private:
     Vector<ControlEntry> m_controlStack;
     const Signature& m_signature;
     const ModuleInformation& m_info;
-    const Vector<SignatureIndex>& m_moduleSignatureIndicesToUniquedSignatureIndices;
 
     OpType m_currentOpcode;
     size_t m_currentOpcodeStartingOffset { 0 };
@@ -95,12 +94,11 @@ private:
 };
 
 template<typename Context>
-FunctionParser<Context>::FunctionParser(Context& context, const uint8_t* functionStart, size_t functionLength, const Signature& signature, const ModuleInformation& info, const Vector<SignatureIndex>& moduleSignatureIndicesToUniquedSignatureIndices)
+FunctionParser<Context>::FunctionParser(Context& context, const uint8_t* functionStart, size_t functionLength, const Signature& signature, const ModuleInformation& info)
     : Parser(functionStart, functionLength)
     , m_context(context)
     , m_signature(signature)
     , m_info(info)
-    , m_moduleSignatureIndicesToUniquedSignatureIndices(moduleSignatureIndicesToUniquedSignatureIndices)
 {
     if (verbose)
         dataLogLn("Parsing function starting at: ", (uintptr_t)functionStart, " of length: ", functionLength);
@@ -350,10 +348,9 @@ auto FunctionParser<Context>::parseExpression() -> PartialResult
         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_moduleSignatureIndicesToUniquedSignatureIndices.size() <= signatureIndex, "call_indirect's signature index ", signatureIndex, " exceeds known signatures ", m_moduleSignatureIndicesToUniquedSignatureIndices.size());
+        WASM_PARSER_FAIL_IF(m_info.usedSignatures.size() <= signatureIndex, "call_indirect's signature index ", signatureIndex, " exceeds known signatures ", m_info.usedSignatures.size());
 
-        SignatureIndex calleeSignatureIndex = m_moduleSignatureIndicesToUniquedSignatureIndices[signatureIndex];
-        const Signature& calleeSignature = SignatureInformation::get(calleeSignatureIndex);
+        const Signature& calleeSignature = m_info.usedSignatures[signatureIndex].get();
         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");
 
@@ -365,7 +362,7 @@ auto FunctionParser<Context>::parseExpression() -> PartialResult
         m_expressionStack.shrink(firstArgumentIndex);
 
         ExpressionType result = Context::emptyExpression;
-        WASM_TRY_ADD_TO_CONTEXT(addCallIndirect(calleeSignature, calleeSignatureIndex, args, result));
+        WASM_TRY_ADD_TO_CONTEXT(addCallIndirect(calleeSignature, args, result));
 
         if (result != Context::emptyExpression)
             m_expressionStack.append(result);
diff --git a/Source/JavaScriptCore/wasm/WasmModuleInformation.cpp b/Source/JavaScriptCore/wasm/WasmModuleInformation.cpp
new file mode 100644 (file)
index 0000000..896abdd
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 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 "WasmModuleInformation.h"
+
+#if ENABLE(WEBASSEMBLY)
+
+namespace JSC { namespace Wasm {
+
+ModuleInformation::~ModuleInformation() { }
+
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
diff --git a/Source/JavaScriptCore/wasm/WasmModuleInformation.h b/Source/JavaScriptCore/wasm/WasmModuleInformation.h
new file mode 100644 (file)
index 0000000..176339a
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 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 "WasmFormat.h"
+
+namespace JSC { namespace Wasm {
+
+struct ModuleInformation : public ThreadSafeRefCounted<ModuleInformation> {
+    size_t functionIndexSpaceSize() const { return importFunctionSignatureIndices.size() + internalFunctionSignatureIndices.size(); }
+    bool isImportedFunctionFromFunctionIndexSpace(size_t functionIndex) const
+    {
+        ASSERT(functionIndex < functionIndexSpaceSize());
+        return functionIndex < importFunctionSignatureIndices.size();
+    }
+    SignatureIndex signatureIndexFromFunctionIndexSpace(size_t functionIndex) const
+    {
+        return isImportedFunctionFromFunctionIndexSpace(functionIndex)
+            ? importFunctionSignatureIndices[functionIndex]
+            : internalFunctionSignatureIndices[functionIndex - importFunctionSignatureIndices.size()];
+    }
+
+    uint32_t importFunctionCount() const { return importFunctionSignatureIndices.size(); }
+    uint32_t internalFunctionCount() const { return internalFunctionSignatureIndices.size(); }
+
+    ModuleInformation(Vector<uint8_t>&& sourceBytes)
+        : source(WTFMove(sourceBytes))
+    {
+    }
+
+    JS_EXPORT_PRIVATE ~ModuleInformation();
+
+    const Vector<uint8_t> source;
+
+    Vector<Import> imports;
+    Vector<SignatureIndex> importFunctionSignatureIndices;
+    Vector<SignatureIndex> internalFunctionSignatureIndices;
+    Vector<Ref<Signature>> usedSignatures;
+
+    MemoryInformation memory;
+
+    Vector<FunctionLocationInBinary> functionLocationInBinary;
+
+    Vector<Export> exports;
+    std::optional<uint32_t> startFunctionIndexSpace;
+    Vector<Segment::Ptr> data;
+    Vector<Element> elements;
+    TableInformation tableInformation;
+    Vector<Global> globals;
+    unsigned firstInternalGlobal { 0 };
+    Vector<CustomSection> customSections;
+
+};
+
+    
+} } // namespace JSC::Wasm
+
+#endif // ENABLE(WEBASSEMBLY)
index 2239122..ee714c1 100644 (file)
@@ -49,7 +49,6 @@ ALWAYS_INLINE I32InitExpr makeI32InitExpr(uint8_t opcode, uint32_t bits)
 
 auto ModuleParser::parse() -> Result
 {
-    m_result.module = std::make_unique<ModuleInformation>();
     const size_t minSize = 8;
     uint32_t versionNumber;
 
@@ -98,7 +97,7 @@ auto ModuleParser::parse() -> Result
         previousSection = section;
     }
 
-    return WTFMove(m_result);
+    return { };
 }
 
 auto ModuleParser::parseType() -> PartialResult
@@ -107,8 +106,7 @@ auto ModuleParser::parseType() -> PartialResult
 
     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.moduleSignatureIndicesToUniquedSignatureIndices.tryReserveCapacity(count), "can't allocate enough memory for Type section's ", count, " entries");
-    WASM_PARSER_FAIL_IF(!m_result.module->usedSignatures.tryReserveCapacity(count), "can't allocate enough memory for Type section's ", count, " entries");
+    WASM_PARSER_FAIL_IF(!m_info->usedSignatures.tryReserveCapacity(count), "can't allocate enough memory for Type section's ", count, " entries");
 
     for (uint32_t i = 0; i < count; ++i) {
         int8_t type;
@@ -141,8 +139,7 @@ auto ModuleParser::parseType() -> PartialResult
         signature->returnType() = returnType;
 
         std::pair<SignatureIndex, Ref<Signature>> result = SignatureInformation::adopt(WTFMove(signature));
-        m_result.moduleSignatureIndicesToUniquedSignatureIndices.uncheckedAppend(result.first);
-        m_result.module->usedSignatures.uncheckedAppend(WTFMove(result.second));
+        m_info->usedSignatures.uncheckedAppend(WTFMove(result.second));
     }
     return { };
 }
@@ -152,34 +149,33 @@ auto ModuleParser::parseImport() -> PartialResult
     uint32_t importCount;
     WASM_PARSER_FAIL_IF(!parseVarUInt32(importCount), "can't get Import section's count");
     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->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_info->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_info->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_info->importFunctionSignatureIndices.tryReserveCapacity(importCount), "can't allocate enough memory for ", importCount, " import function signatures"); // FIXME this over-allocates when we fix the FIXMEs below.
 
     for (uint32_t importNumber = 0; importNumber < importCount; ++importNumber) {
-        Import imp;
         uint32_t moduleLen;
         uint32_t fieldLen;
-        String moduleString;
-        String fieldString;
+        Vector<LChar> moduleString;
+        Vector<LChar> fieldString;
+        ExternalKind kind;
+        unsigned kindIndex { 0 };
 
         WASM_PARSER_FAIL_IF(!parseVarUInt32(moduleLen), "can't get ", importNumber, "th Import's module name length");
         WASM_PARSER_FAIL_IF(!consumeUTF8String(moduleString, moduleLen), "can't get ", importNumber, "th Import's module name of length ", moduleLen);
-        imp.module = moduleString;
 
         WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", importNumber, "th Import's field name length in module '", moduleString, "'");
         WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", importNumber, "th Import's field name of length ", moduleLen, " in module '", moduleString, "'");
-        imp.field = fieldString;
 
-        WASM_PARSER_FAIL_IF(!parseExternalKind(imp.kind), "can't get ", importNumber, "th Import's kind in module '", moduleString, "' field '", fieldString, "'");
-        switch (imp.kind) {
+        WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", importNumber, "th Import's kind in module '", moduleString, "' field '", fieldString, "'");
+        switch (kind) {
         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.moduleSignatureIndicesToUniquedSignatureIndices.size(), "invalid function signature for ", importNumber, "th Import, ", functionSignatureIndex, " is out of range of ", m_result.moduleSignatureIndicesToUniquedSignatureIndices.size(), " in module '", moduleString, "' field '", fieldString, "'");
-            imp.kindIndex = m_result.module->importFunctionSignatureIndices.size();
-            SignatureIndex signatureIndex = m_result.moduleSignatureIndicesToUniquedSignatureIndices[functionSignatureIndex];
-            m_result.module->importFunctionSignatureIndices.uncheckedAppend(signatureIndex);
+            WASM_PARSER_FAIL_IF(functionSignatureIndex >= m_info->usedSignatures.size(), "invalid function signature for ", importNumber, "th Import, ", functionSignatureIndex, " is out of range of ", m_info->usedSignatures.size(), " in module '", moduleString, "' field '", fieldString, "'");
+            kindIndex = m_info->importFunctionSignatureIndices.size();
+            SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[functionSignatureIndex]);
+            m_info->importFunctionSignatureIndices.uncheckedAppend(signatureIndex);
             break;
         }
         case ExternalKind::Table: {
@@ -201,16 +197,16 @@ auto ModuleParser::parseImport() -> PartialResult
             WASM_FAIL_IF_HELPER_FAILS(parseGlobalType(global));
             WASM_PARSER_FAIL_IF(global.mutability == Global::Mutable, "Mutable Globals aren't supported");
 
-            imp.kindIndex = m_result.module->globals.size();
-            m_result.module->globals.uncheckedAppend(WTFMove(global));
+            kindIndex = m_info->globals.size();
+            m_info->globals.uncheckedAppend(WTFMove(global));
             break;
         }
         }
 
-        m_result.module->imports.uncheckedAppend(imp);
+        m_info->imports.uncheckedAppend({ WTFMove(moduleString), WTFMove(fieldString), kind, kindIndex });
     }
 
-    m_result.module->firstInternalGlobal = m_result.module->globals.size();
+    m_info->firstInternalGlobal = m_info->globals.size();
     return { };
 }
 
@@ -219,20 +215,20 @@ auto ModuleParser::parseFunction() -> PartialResult
     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->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_info->internalFunctionSignatureIndices.tryReserveCapacity(count), "can't allocate enough memory for ", count, " Function signatures");
+    WASM_PARSER_FAIL_IF(!m_info->functionLocationInBinary.tryReserveCapacity(count), "can't allocate enough memory for ", count, "Function locations");
 
     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.moduleSignatureIndicesToUniquedSignatureIndices.size(), i, "th Function type number is invalid ", typeNumber);
+        WASM_PARSER_FAIL_IF(typeNumber >= m_info->usedSignatures.size(), i, "th Function type number is invalid ", typeNumber);
 
-        SignatureIndex signatureIndex = m_result.moduleSignatureIndicesToUniquedSignatureIndices[typeNumber];
+        SignatureIndex signatureIndex = SignatureInformation::get(m_info->usedSignatures[typeNumber]);
         // The Code section fixes up start and end.
         size_t start = 0;
         size_t end = 0;
-        m_result.module->internalFunctionSignatureIndices.uncheckedAppend(signatureIndex);
-        m_result.functionLocationInBinary.uncheckedAppend({ start, end });
+        m_info->internalFunctionSignatureIndices.uncheckedAppend(signatureIndex);
+        m_info->functionLocationInBinary.uncheckedAppend({ start, end });
     }
 
     return { };
@@ -275,7 +271,7 @@ auto ModuleParser::parseTableHelper(bool isImport) -> PartialResult
 
     ASSERT(!maximum || *maximum >= initial);
 
-    m_result.module->tableInformation = TableInformation(initial, maximum, isImport);
+    m_info->tableInformation = TableInformation(initial, maximum, isImport);
 
     return { };
 }
@@ -296,7 +292,7 @@ auto ModuleParser::parseTable() -> PartialResult
 
 auto ModuleParser::parseMemoryHelper(bool isImport) -> PartialResult
 {
-    WASM_PARSER_FAIL_IF(!!m_result.module->memory, "Memory section cannot exist if an Import has a memory");
+    WASM_PARSER_FAIL_IF(!!m_info->memory, "Memory section cannot exist if an Import has a memory");
 
     PageCount initialPageCount;
     PageCount maximumPageCount;
@@ -319,7 +315,7 @@ auto ModuleParser::parseMemoryHelper(bool isImport) -> PartialResult
     ASSERT(initialPageCount);
     ASSERT(!maximumPageCount || maximumPageCount >= initialPageCount);
 
-    m_result.module->memory = MemoryInformation(initialPageCount, maximumPageCount, isImport);
+    m_info->memory = MemoryInformation(initialPageCount, maximumPageCount, isImport);
     return { };
 }
 
@@ -341,7 +337,7 @@ auto ModuleParser::parseGlobal() -> PartialResult
 {
     uint32_t globalCount;
     WASM_PARSER_FAIL_IF(!parseVarUInt32(globalCount), "can't get Global section's count");
-    WASM_PARSER_FAIL_IF(!m_result.module->globals.tryReserveCapacity(globalCount + m_result.module->firstInternalGlobal), "can't allocate memory for ", globalCount + m_result.module->firstInternalGlobal, " globals");
+    WASM_PARSER_FAIL_IF(!m_info->globals.tryReserveCapacity(globalCount + m_info->firstInternalGlobal), "can't allocate memory for ", globalCount + m_info->firstInternalGlobal, " globals");
 
     for (uint32_t globalIndex = 0; globalIndex < globalCount; ++globalIndex) {
         Global global;
@@ -356,7 +352,7 @@ auto ModuleParser::parseGlobal() -> PartialResult
             global.initializationType = Global::FromExpression;
         WASM_PARSER_FAIL_IF(typeForInitOpcode != global.type, "Global init_expr opcode of type ", typeForInitOpcode, " doesn't match global's type ", global.type);
 
-        m_result.module->globals.uncheckedAppend(WTFMove(global));
+        m_info->globals.uncheckedAppend(WTFMove(global));
     }
 
     return { };
@@ -367,45 +363,46 @@ auto ModuleParser::parseExport() -> PartialResult
     uint32_t exportCount;
     WASM_PARSER_FAIL_IF(!parseVarUInt32(exportCount), "can't get Export section's count");
     WASM_PARSER_FAIL_IF(exportCount == std::numeric_limits<uint32_t>::max(), "Export section's count is too big ", exportCount);
-    WASM_PARSER_FAIL_IF(!m_result.module->exports.tryReserveCapacity(exportCount), "can't allocate enough memory for ", exportCount, " exports");
+    WASM_PARSER_FAIL_IF(!m_info->exports.tryReserveCapacity(exportCount), "can't allocate enough memory for ", exportCount, " exports");
 
     HashSet<String> exportNames;
     for (uint32_t exportNumber = 0; exportNumber < exportCount; ++exportNumber) {
-        Export exp;
         uint32_t fieldLen;
-        String fieldString;
+        Vector<LChar> fieldString;
+        ExternalKind kind;
+        unsigned kindIndex;
 
         WASM_PARSER_FAIL_IF(!parseVarUInt32(fieldLen), "can't get ", exportNumber, "th Export's field name length");
         WASM_PARSER_FAIL_IF(!consumeUTF8String(fieldString, fieldLen), "can't get ", exportNumber, "th Export's field name of length ", fieldLen);
-        WASM_PARSER_FAIL_IF(exportNames.contains(fieldString), "duplicate export: '", fieldString, "'");
-        exportNames.add(fieldString);
-        exp.field = fieldString;
+        String fieldName = String::fromUTF8(fieldString);
+        WASM_PARSER_FAIL_IF(exportNames.contains(fieldName), "duplicate export: '", fieldString, "'");
+        exportNames.add(fieldName);
 
-        WASM_PARSER_FAIL_IF(!parseExternalKind(exp.kind), "can't get ", exportNumber, "th Export's kind, named '", fieldString, "'");
-        WASM_PARSER_FAIL_IF(!parseVarUInt32(exp.kindIndex), "can't get ", exportNumber, "th Export's kind index, named '", fieldString, "'");
-        switch (exp.kind) {
+        WASM_PARSER_FAIL_IF(!parseExternalKind(kind), "can't get ", exportNumber, "th Export's kind, named '", fieldString, "'");
+        WASM_PARSER_FAIL_IF(!parseVarUInt32(kindIndex), "can't get ", exportNumber, "th Export's kind index, named '", fieldString, "'");
+        switch (kind) {
         case ExternalKind::Function: {
-            WASM_PARSER_FAIL_IF(exp.kindIndex >= m_result.module->functionIndexSpaceSize(), exportNumber, "th Export has invalid function number ", exp.kindIndex, " it exceeds the function index space ", m_result.module->functionIndexSpaceSize(), ", named '", fieldString, "'");
+            WASM_PARSER_FAIL_IF(kindIndex >= m_info->functionIndexSpaceSize(), exportNumber, "th Export has invalid function number ", kindIndex, " it exceeds the function index space ", m_info->functionIndexSpaceSize(), ", named '", fieldString, "'");
             break;
         }
         case ExternalKind::Table: {
             WASM_PARSER_FAIL_IF(!m_hasTable, "can't export a non-existent Table");
-            WASM_PARSER_FAIL_IF(exp.kindIndex, "can't export Table ", exp.kindIndex, " only zero-index Table is currently supported");
+            WASM_PARSER_FAIL_IF(kindIndex, "can't export Table ", kindIndex, " only zero-index Table is currently supported");
             break;
         }
         case ExternalKind::Memory: {
-            WASM_PARSER_FAIL_IF(!m_result.module->memory, "can't export a non-existent Memory");
-            WASM_PARSER_FAIL_IF(exp.kindIndex, "can't export Memory ", exp.kindIndex, " only one Table is currently supported");
+            WASM_PARSER_FAIL_IF(!m_info->memory, "can't export a non-existent Memory");
+            WASM_PARSER_FAIL_IF(kindIndex, "can't export Memory ", kindIndex, " only one Table is currently supported");
             break;
         }
         case ExternalKind::Global: {
-            WASM_PARSER_FAIL_IF(exp.kindIndex >= m_result.module->globals.size(), exportNumber, "th Export has invalid global number ", exp.kindIndex, " it exceeds the globals count ", m_result.module->globals.size(), ", named '", fieldString, "'");
-            WASM_PARSER_FAIL_IF(m_result.module->globals[exp.kindIndex].mutability != Global::Immutable, exportNumber, "th Export isn't immutable, named '", fieldString, "'");
+            WASM_PARSER_FAIL_IF(kindIndex >= m_info->globals.size(), exportNumber, "th Export has invalid global number ", kindIndex, " it exceeds the globals count ", m_info->globals.size(), ", named '", fieldString, "'");
+            WASM_PARSER_FAIL_IF(m_info->globals[kindIndex].mutability != Global::Immutable, exportNumber, "th Export isn't immutable, named '", fieldString, "'");
             break;
         }
         }
 
-        m_result.module->exports.uncheckedAppend(exp);
+        m_info->exports.uncheckedAppend({ WTFMove(fieldString), kind, kindIndex });
     }
 
     return { };
@@ -415,12 +412,12 @@ auto ModuleParser::parseStart() -> PartialResult
 {
     uint32_t startFunctionIndex;
     WASM_PARSER_FAIL_IF(!parseVarUInt32(startFunctionIndex), "can't get Start index");
-    WASM_PARSER_FAIL_IF(startFunctionIndex >= m_result.module->functionIndexSpaceSize(), "Start index ", startFunctionIndex, " exceeds function index space ", m_result.module->functionIndexSpaceSize());
-    SignatureIndex signatureIndex = m_result.module->signatureIndexFromFunctionIndexSpace(startFunctionIndex);
+    WASM_PARSER_FAIL_IF(startFunctionIndex >= m_info->functionIndexSpaceSize(), "Start index ", startFunctionIndex, " exceeds function index space ", m_info->functionIndexSpaceSize());
+    SignatureIndex signatureIndex = m_info->signatureIndexFromFunctionIndexSpace(startFunctionIndex);
     const Signature& signature = SignatureInformation::get(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;
+    m_info->startFunctionIndexSpace = startFunctionIndex;
     return { };
 }
 
@@ -431,7 +428,7 @@ auto ModuleParser::parseElement() -> PartialResult
     uint32_t elementCount;
     WASM_PARSER_FAIL_IF(!parseVarUInt32(elementCount), "can't get Element section's count");
     WASM_PARSER_FAIL_IF(elementCount == std::numeric_limits<uint32_t>::max(), "Element section's count is too big ", elementCount);
-    WASM_PARSER_FAIL_IF(!m_result.module->elements.tryReserveCapacity(elementCount), "can't allocate memory for ", elementCount, " Elements");
+    WASM_PARSER_FAIL_IF(!m_info->elements.tryReserveCapacity(elementCount), "can't allocate memory for ", elementCount, " Elements");
     for (unsigned elementNum = 0; elementNum < elementCount; ++elementNum) {
         uint32_t tableIndex;
         uint64_t initExprBits;
@@ -446,7 +443,7 @@ auto ModuleParser::parseElement() -> PartialResult
         WASM_PARSER_FAIL_IF(!parseVarUInt32(indexCount), "can't get ", elementNum, "th index count for Element section");
         WASM_PARSER_FAIL_IF(indexCount == std::numeric_limits<uint32_t>::max(), "Element section's ", elementNum, "th index count is too big ", indexCount);
 
-        ASSERT(!!m_result.module->tableInformation);
+        ASSERT(!!m_info->tableInformation);
 
         Element element(makeI32InitExpr(initOpcode, initExprBits));
         WASM_PARSER_FAIL_IF(!element.functionIndices.tryReserveCapacity(indexCount), "can't allocate memory for ", indexCount, " Element indices");
@@ -454,12 +451,12 @@ auto ModuleParser::parseElement() -> PartialResult
         for (unsigned index = 0; index < indexCount; ++index) {
             uint32_t functionIndex;
             WASM_PARSER_FAIL_IF(!parseVarUInt32(functionIndex), "can't get Element section's ", elementNum, "th element's ", index, "th index");
-            WASM_PARSER_FAIL_IF(functionIndex >= m_result.module->functionIndexSpaceSize(), "Element section's ", elementNum, "th element's ", index, "th index is ", functionIndex, " which exceeds the function index space size of ", m_result.module->functionIndexSpaceSize());
+            WASM_PARSER_FAIL_IF(functionIndex >= m_info->functionIndexSpaceSize(), "Element section's ", elementNum, "th element's ", index, "th index is ", functionIndex, " which exceeds the function index space size of ", m_info->functionIndexSpaceSize());
 
             element.functionIndices.uncheckedAppend(functionIndex);
         }
 
-        m_result.module->elements.uncheckedAppend(WTFMove(element));
+        m_info->elements.uncheckedAppend(WTFMove(element));
     }
 
     return { };
@@ -470,7 +467,7 @@ auto ModuleParser::parseCode() -> PartialResult
     uint32_t count;
     WASM_PARSER_FAIL_IF(!parseVarUInt32(count), "can't get Code section's count");
     WASM_PARSER_FAIL_IF(count == std::numeric_limits<uint32_t>::max(), "Code section's count is too big ", count);
-    WASM_PARSER_FAIL_IF(count != m_result.functionLocationInBinary.size(), "Code section count ", count, " exceeds the declared number of functions ", m_result.functionLocationInBinary.size());
+    WASM_PARSER_FAIL_IF(count != m_info->functionLocationInBinary.size(), "Code section count ", count, " exceeds the declared number of functions ", m_info->functionLocationInBinary.size());
 
     for (uint32_t i = 0; i < count; ++i) {
         uint32_t functionSize;
@@ -478,9 +475,9 @@ auto ModuleParser::parseCode() -> PartialResult
         WASM_PARSER_FAIL_IF(functionSize > length(), "Code function's size ", functionSize, " exceeds the module's size ", length());
         WASM_PARSER_FAIL_IF(functionSize > length() - m_offset, "Code function's size ", functionSize, " exceeds the module's remaining size", length() - m_offset);
 
-        m_result.functionLocationInBinary[i].start = m_offset;
-        m_result.functionLocationInBinary[i].end = m_offset + functionSize;
-        m_offset = m_result.functionLocationInBinary[i].end;
+        m_info->functionLocationInBinary[i].start = m_offset;
+        m_info->functionLocationInBinary[i].end = m_offset + functionSize;
+        m_offset = m_info->functionLocationInBinary[i].end;
     }
 
     return { };
@@ -527,11 +524,11 @@ auto ModuleParser::parseInitExpr(uint8_t& opcode, uint64_t& bitsOrImportNumber,
         uint32_t index;
         WASM_PARSER_FAIL_IF(!parseVarUInt32(index), "can't get get_global's index");
 
-        WASM_PARSER_FAIL_IF(index >= m_result.module->globals.size(), "get_global's index ", index, " exceeds the number of globals ", m_result.module->globals.size());
-        WASM_PARSER_FAIL_IF(index >= m_result.module->firstInternalGlobal, "get_global import kind index ", index, " exceeds the first internal global ", m_result.module->firstInternalGlobal);
+        WASM_PARSER_FAIL_IF(index >= m_info->globals.size(), "get_global's index ", index, " exceeds the number of globals ", m_info->globals.size());
+        WASM_PARSER_FAIL_IF(index >= m_info->firstInternalGlobal, "get_global import kind index ", index, " exceeds the first internal global ", m_info->firstInternalGlobal);
 
-        ASSERT(m_result.module->globals[index].mutability == Global::Immutable);
-        resultType = m_result.module->globals[index].type;
+        ASSERT(m_info->globals[index].mutability == Global::Immutable);
+        resultType = m_info->globals[index].type;
         bitsOrImportNumber = index;
         break;
     }
@@ -559,10 +556,10 @@ auto ModuleParser::parseGlobalType(Global& global) -> PartialResult
 auto ModuleParser::parseData() -> PartialResult
 {
     uint32_t segmentCount;
-    WASM_PARSER_FAIL_IF(!m_result.module->memory, "Data section cannot exist without a Memory section or Import");
+    WASM_PARSER_FAIL_IF(!m_info->memory, "Data section cannot exist without a Memory section or Import");
     WASM_PARSER_FAIL_IF(!parseVarUInt32(segmentCount), "can't get Data section's count");
     WASM_PARSER_FAIL_IF(segmentCount == std::numeric_limits<uint32_t>::max(), "Data section's count is too big ", segmentCount);
-    WASM_PARSER_FAIL_IF(!m_result.module->data.tryReserveCapacity(segmentCount), "can't allocate enough memory for Data section's ", segmentCount, " segments");
+    WASM_PARSER_FAIL_IF(!m_info->data.tryReserveCapacity(segmentCount), "can't allocate enough memory for Data section's ", segmentCount, " segments");
 
     for (uint32_t segmentNumber = 0; segmentNumber < segmentCount; ++segmentNumber) {
         uint32_t index;
@@ -580,7 +577,7 @@ auto ModuleParser::parseData() -> PartialResult
 
         Segment* segment = Segment::create(makeI32InitExpr(initOpcode, initExprBits), 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::adoptPtr(segment));
+        m_info->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");
@@ -595,9 +592,9 @@ auto ModuleParser::parseCustom(uint32_t sectionLength) -> PartialResult
     const uint32_t customSectionStartOffset = m_offset;
 
     CustomSection section;
-    uint32_t customSectionNumber = m_result.module->customSections.size() + 1;
+    uint32_t customSectionNumber = m_info->customSections.size() + 1;
     uint32_t nameLen;
-    WASM_PARSER_FAIL_IF(!m_result.module->customSections.tryReserveCapacity(customSectionNumber), "can't allocate enough memory for ", customSectionNumber, "th custom section");
+    WASM_PARSER_FAIL_IF(!m_info->customSections.tryReserveCapacity(customSectionNumber), "can't allocate enough memory for ", customSectionNumber, "th custom section");
     WASM_PARSER_FAIL_IF(!parseVarUInt32(nameLen), "can't get ", customSectionNumber, "th custom section's name length");
     WASM_PARSER_FAIL_IF(!consumeUTF8String(section.name, nameLen), "nameLen get ", customSectionNumber, "th custom section's name of length ", nameLen);
 
@@ -609,7 +606,7 @@ auto ModuleParser::parseCustom(uint32_t sectionLength) -> PartialResult
         section.payload.uncheckedAppend(byte);
     }
     
-    m_result.module->customSections.uncheckedAppend(WTFMove(section));
+    m_info->customSections.uncheckedAppend(WTFMove(section));
 
     return { };
 }
index e377ef5..b549f86 100644 (file)
 
 namespace JSC { namespace Wasm {
 
-struct ModuleParserResult {
-    std::unique_ptr<ModuleInformation> module;
-    Vector<FunctionLocationInBinary> functionLocationInBinary;
-    Vector<SignatureIndex> moduleSignatureIndicesToUniquedSignatureIndices;
-};
-
-class ModuleParser : public Parser<ModuleParserResult> {
+class ModuleParser : public Parser<void> {
 public:
-
-
-    ModuleParser(const uint8_t* sourceBuffer, size_t sourceLength)
+    ModuleParser(const uint8_t* sourceBuffer, size_t sourceLength, ModuleInformation& info)
         : Parser(sourceBuffer, sourceLength)
+        , m_info(info)
     {
     }
 
@@ -65,7 +58,7 @@ private:
     PartialResult WARN_UNUSED_RETURN parseResizableLimits(uint32_t& initial, std::optional<uint32_t>& maximum);
     PartialResult WARN_UNUSED_RETURN parseInitExpr(uint8_t&, uint64_t&, Type& initExprType);
 
-    ModuleParserResult m_result;
+    Ref<ModuleInformation> m_info;
     bool m_hasTable { false };
 };
 
index 8ec8422..89ff10c 100644 (file)
@@ -30,6 +30,7 @@
 #include "B3Compilation.h"
 #include "B3Procedure.h"
 #include "WasmFormat.h"
+#include "WasmModuleInformation.h"
 #include "WasmOps.h"
 #include "WasmSections.h"
 #include <type_traits>
@@ -37,6 +38,7 @@
 #include <wtf/LEBDecoder.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/text/WTFString.h>
+#include <wtf/unicode/UTF8.h>
 
 namespace JSC { namespace Wasm {
 
@@ -60,7 +62,7 @@ protected:
 
     bool WARN_UNUSED_RETURN consumeCharacter(char);
     bool WARN_UNUSED_RETURN consumeString(const char*);
-    bool WARN_UNUSED_RETURN consumeUTF8String(String&, size_t);
+    bool WARN_UNUSED_RETURN consumeUTF8String(Vector<LChar>&, size_t);
 
     bool WARN_UNUSED_RETURN parseVarUInt1(uint8_t&);
     bool WARN_UNUSED_RETURN parseInt7(int8_t&);
@@ -140,18 +142,29 @@ ALWAYS_INLINE bool Parser<SuccessType>::consumeString(const char* str)
 }
 
 template<typename SuccessType>
-ALWAYS_INLINE bool Parser<SuccessType>::consumeUTF8String(String& result, size_t stringLength)
+ALWAYS_INLINE bool Parser<SuccessType>::consumeUTF8String(Vector<LChar>& result, size_t stringLength)
 {
-    if (stringLength == 0) {
-        result = emptyString();
-        return true;
-    }
     if (length() < stringLength || m_offset > length() - stringLength)
         return false;
-    result = String::fromUTF8(static_cast<const LChar*>(&source()[m_offset]), stringLength);
-    m_offset += stringLength;
-    if (result.isEmpty())
+    if (!result.tryReserveCapacity(stringLength))
         return false;
+
+    const uint8_t* stringStart = source() + m_offset;
+
+    // We don't cache the UTF-16 characters since it seems likely the string is ascii.
+    if (UNLIKELY(!charactersAreAllASCII(stringStart, stringLength))) {
+        Vector<UChar, 1024> buffer(stringLength);
+        UChar* bufferStart = buffer.data();
+
+        UChar* bufferCurrent = bufferStart;
+        const char* stringCurrent = reinterpret_cast<const char*>(stringStart);
+        if (WTF::Unicode::convertUTF8ToUTF16(&stringCurrent, reinterpret_cast<const char *>(stringStart + stringLength), &bufferCurrent, bufferCurrent + buffer.size()) != WTF::Unicode::conversionOK)
+            return false;
+    }
+
+    result.grow(stringLength);
+    memcpy(result.data(), stringStart, stringLength);
+    m_offset += stringLength;
     return true;
 }
 
index d65f662..67f7595 100644 (file)
@@ -50,21 +50,30 @@ namespace JSC { namespace Wasm {
 
 static const bool verbose = false;
 
-Plan::Plan(VM& vm, ArrayBuffer& source, AsyncWork work, CompletionTask&& task)
-    : Plan(vm, reinterpret_cast<uint8_t*>(source.data()), source.byteLength(), work, WTFMove(task))
+Plan::Plan(VM& vm, Ref<ModuleInformation> info, AsyncWork work, CompletionTask&& task)
+    : m_moduleInformation(WTFMove(info))
+    , m_vm(vm)
+    , m_completionTask(task)
+    , m_source(m_moduleInformation->source.data())
+    , m_sourceLength(m_moduleInformation->source.size())
+    , m_state(State::Validated)
+    , m_asyncWork(work)
 {
 }
 
-Plan::Plan(VM& vm, Vector<uint8_t>& source, AsyncWork work, CompletionTask&& task)
-    : Plan(vm, source.data(), source.size(), work, WTFMove(task))
+Plan::Plan(VM& vm, Vector<uint8_t>&& source, AsyncWork work, CompletionTask&& task)
+    : Plan(vm, makeRef(*new ModuleInformation(WTFMove(source))), work, WTFMove(task))
 {
+    m_state = State::Initial;
 }
 
 Plan::Plan(VM& vm, const uint8_t* source, size_t sourceLength, AsyncWork work, CompletionTask&& task)
-    : m_vm(vm)
+    : m_moduleInformation(makeRef(*new ModuleInformation(Vector<uint8_t>())))
+    , m_vm(vm)
     , m_completionTask(task)
     , m_source(source)
     , m_sourceLength(sourceLength)
+    , m_state(State::Initial)
     , m_asyncWork(work)
 {
 }
@@ -97,33 +106,33 @@ void Plan::fail(const AbstractLocker& locker, String&& errorMessage)
 
 bool Plan::parseAndValidateModule()
 {
-    ASSERT(m_state == State::Initial);
+    if (m_state != State::Initial)
+        return true;
+
     dataLogLnIf(verbose, "starting validation");
     MonotonicTime startTime;
     if (verbose || Options::reportCompileTimes())
         startTime = MonotonicTime::now();
 
     {
-        ModuleParser moduleParser(m_source, m_sourceLength);
+        ModuleParser moduleParser(m_source, m_sourceLength, m_moduleInformation);
         auto parseResult = moduleParser.parse();
         if (!parseResult) {
             fail(holdLock(m_lock), WTFMove(parseResult.error()));
             return false;
         }
-        m_moduleInformation = WTFMove(parseResult->module);
-        m_functionLocationInBinary = WTFMove(parseResult->functionLocationInBinary);
-        m_moduleSignatureIndicesToUniquedSignatureIndices = WTFMove(parseResult->moduleSignatureIndicesToUniquedSignatureIndices);
     }
 
-    for (unsigned functionIndex = 0; functionIndex < m_functionLocationInBinary.size(); ++functionIndex) {
-        dataLogLnIf(verbose, "Processing function starting at: ", m_functionLocationInBinary[functionIndex].start, " and ending at: ", m_functionLocationInBinary[functionIndex].end);
-        const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start;
-        size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start;
+    const auto& functionLocations = m_moduleInformation->functionLocationInBinary;
+    for (unsigned functionIndex = 0; functionIndex < functionLocations.size(); ++functionIndex) {
+        dataLogLnIf(verbose, "Processing function starting at: ", functionLocations[functionIndex].start, " and ending at: ", functionLocations[functionIndex].end);
+        const uint8_t* functionStart = m_source + functionLocations[functionIndex].start;
+        size_t functionLength = functionLocations[functionIndex].end - functionLocations[functionIndex].start;
         ASSERT(functionLength <= m_sourceLength);
         SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex];
         const Signature& signature = SignatureInformation::get(signatureIndex);
 
-        auto validationResult = validateFunction(functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices);
+        auto validationResult = validateFunction(functionStart, functionLength, signature, m_moduleInformation.get());
         if (!validationResult) {
             if (verbose) {
                 for (unsigned i = 0; i < functionLength; ++i)
@@ -163,22 +172,23 @@ void Plan::prepare()
         return true;
     };
 
+    const auto& functionLocations = m_moduleInformation->functionLocationInBinary;
     if (!tryReserveCapacity(m_wasmExitStubs, m_moduleInformation->importFunctionSignatureIndices.size(), " WebAssembly to JavaScript stubs")
-        || !tryReserveCapacity(m_unlinkedWasmToWasmCalls, m_functionLocationInBinary.size(), " unlinked WebAssembly to WebAssembly calls")
-        || !tryReserveCapacity(m_wasmInternalFunctions, m_functionLocationInBinary.size(), " WebAssembly functions")
-        || !tryReserveCapacity(m_compilationContexts, m_functionLocationInBinary.size(), " compilation contexts"))
+        || !tryReserveCapacity(m_unlinkedWasmToWasmCalls, functionLocations.size(), " unlinked WebAssembly to WebAssembly calls")
+        || !tryReserveCapacity(m_wasmInternalFunctions, functionLocations.size(), " WebAssembly functions")
+        || !tryReserveCapacity(m_compilationContexts, functionLocations.size(), " compilation contexts"))
         return;
 
-    m_unlinkedWasmToWasmCalls.resize(m_functionLocationInBinary.size());
-    m_wasmInternalFunctions.resize(m_functionLocationInBinary.size());
-    m_compilationContexts.resize(m_functionLocationInBinary.size());
+    m_unlinkedWasmToWasmCalls.resize(functionLocations.size());
+    m_wasmInternalFunctions.resize(functionLocations.size());
+    m_compilationContexts.resize(functionLocations.size());
 
     for (unsigned importIndex = 0; importIndex < m_moduleInformation->imports.size(); ++importIndex) {
         Import* import = &m_moduleInformation->imports[importIndex];
         if (import->kind != ExternalKind::Function)
             continue;
         unsigned importFunctionIndex = m_wasmExitStubs.size();
-        dataLogLnIf(verbose, "Processing import function number ", importFunctionIndex, ": ", import->module, ": ", import->field);
+        dataLogLnIf(verbose, "Processing import function number ", importFunctionIndex, ": ", makeString(import->module), ": ", makeString(import->field));
         SignatureIndex signatureIndex = m_moduleInformation->importFunctionSignatureIndices.at(import->kindIndex);
         m_wasmExitStubs.uncheckedAppend(exitStubGenerator(&m_vm, m_callLinkInfos, signatureIndex, importFunctionIndex));
     }
@@ -219,6 +229,7 @@ void Plan::compileFunctions(CompilationEffort effort)
     ThreadCountHolder holder(*this);
 
     size_t bytesCompiled = 0;
+    const auto& functionLocations = m_moduleInformation->functionLocationInBinary;
     while (true) {
         if (effort == Partial && bytesCompiled >= Options::webAssemblyPartialCompileLimit())
             return;
@@ -226,7 +237,7 @@ void Plan::compileFunctions(CompilationEffort effort)
         uint32_t functionIndex;
         {
             auto locker = holdLock(m_lock);
-            if (m_currentIndex >= m_functionLocationInBinary.size()) {
+            if (m_currentIndex >= functionLocations.size()) {
                 if (hasWork())
                     moveToState(State::Compiled);
                 return;
@@ -235,17 +246,17 @@ void Plan::compileFunctions(CompilationEffort effort)
             ++m_currentIndex;
         }
 
-        const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start;
-        size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start;
+        const uint8_t* functionStart = m_source + functionLocations[functionIndex].start;
+        size_t functionLength = functionLocations[functionIndex].end - functionLocations[functionIndex].start;
         ASSERT(functionLength <= m_sourceLength);
         SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex];
         const Signature& signature = SignatureInformation::get(signatureIndex);
         unsigned functionIndexSpace = m_wasmExitStubs.size() + functionIndex;
         ASSERT_UNUSED(functionIndexSpace, m_moduleInformation->signatureIndexFromFunctionIndexSpace(functionIndexSpace) == signatureIndex);
-        ASSERT(validateFunction(functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices));
+        ASSERT(validateFunction(functionStart, functionLength, signature, m_moduleInformation.get()));
 
         m_unlinkedWasmToWasmCalls[functionIndex] = Vector<UnlinkedWasmToWasmCall>();
-        auto parseAndCompileResult = parseAndCompile(m_compilationContexts[functionIndex], functionStart, functionLength, signature, m_unlinkedWasmToWasmCalls[functionIndex], *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices, m_mode, Options::webAssemblyB3OptimizationLevel());
+        auto parseAndCompileResult = parseAndCompile(m_compilationContexts[functionIndex], functionStart, functionLength, signature, m_unlinkedWasmToWasmCalls[functionIndex], m_moduleInformation.get(), m_mode, Options::webAssemblyB3OptimizationLevel());
 
         if (UNLIKELY(!parseAndCompileResult)) {
             auto locker = holdLock(m_lock);
@@ -253,7 +264,7 @@ void Plan::compileFunctions(CompilationEffort effort)
                 // Multiple compiles could fail simultaneously. We arbitrarily choose the first.
                 fail(locker, makeString(parseAndCompileResult.error(), ", in function at index ", String::number(functionIndex))); // FIXME make this an Expected.
             }
-            m_currentIndex = m_functionLocationInBinary.size();
+            m_currentIndex = functionLocations.size();
             return;
         }
 
@@ -264,11 +275,11 @@ void Plan::compileFunctions(CompilationEffort effort)
 
 void Plan::complete(const AbstractLocker&)
 {
-    ASSERT(m_state != State::Compiled || m_currentIndex >= m_functionLocationInBinary.size());
+    ASSERT(m_state != State::Compiled || m_currentIndex >= m_moduleInformation->functionLocationInBinary.size());
     dataLogLnIf(verbose, "Starting Completion");
 
     if (m_state == State::Compiled) {
-        for (uint32_t functionIndex = 0; functionIndex < m_functionLocationInBinary.size(); functionIndex++) {
+        for (uint32_t functionIndex = 0; functionIndex < m_moduleInformation->functionLocationInBinary.size(); functionIndex++) {
             {
                 CompilationContext& context = m_compilationContexts[functionIndex];
                 SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex];
@@ -324,7 +335,7 @@ void Plan::cancel()
 {
     LockHolder locker(m_lock);
     if (m_state != State::Completed) {
-        m_currentIndex = m_functionLocationInBinary.size();
+        m_currentIndex = m_moduleInformation->functionLocationInBinary.size();
         fail(locker, ASCIILiteral("WebAssembly Plan was canceled. If you see this error message please file a bug at bugs.webkit.org!"));
     }
 }
index 008ddaf..3b820ca 100644 (file)
@@ -30,7 +30,7 @@
 #include "CompilationResult.h"
 #include "VM.h"
 #include "WasmB3IRGenerator.h"
-#include "WasmFormat.h"
+#include "WasmModuleInformation.h"
 #include <wtf/Bag.h>
 #include <wtf/ThreadSafeRefCounted.h>
 #include <wtf/Vector.h>
@@ -49,8 +49,10 @@ public:
     typedef std::function<void(Plan&)> CompletionTask;
     enum AsyncWork : uint8_t { FullCompile, Validation };
     // Note: CompletionTask should not hold a reference to the Plan otherwise there will be a reference cycle.
-    Plan(VM&, ArrayBuffer&, AsyncWork, CompletionTask&&);
-    JS_EXPORT_PRIVATE Plan(VM&, Vector<uint8_t>&, AsyncWork, CompletionTask&&);
+    Plan(VM&, Ref<ModuleInformation>, AsyncWork, CompletionTask&&);
+    JS_EXPORT_PRIVATE Plan(VM&, Vector<uint8_t>&&, AsyncWork, CompletionTask&&);
+    // Note: This constructor should only be used if you are not actually building a module e.g. validation/function tests
+    // FIXME: When we get rid of function tests we should remove AsyncWork from this constructor.
     JS_EXPORT_PRIVATE Plan(VM&, const uint8_t*, size_t, AsyncWork, CompletionTask&&);
     JS_EXPORT_PRIVATE ~Plan();
 
@@ -72,10 +74,10 @@ public:
     size_t internalFunctionCount() const
     {
         RELEASE_ASSERT(!failed() && !hasWork());
-        return m_functionLocationInBinary.size();
+        return m_moduleInformation->internalFunctionCount();
     }
 
-    std::unique_ptr<ModuleInformation>&& takeModuleInformation()
+    Ref<ModuleInformation>&& takeModuleInformation()
     {
         RELEASE_ASSERT(!failed() && !hasWork());
         return WTFMove(m_moduleInformation);
@@ -130,9 +132,7 @@ private:
 
     const char* stateString(State);
 
-    std::unique_ptr<ModuleInformation> m_moduleInformation;
-    Vector<FunctionLocationInBinary> m_functionLocationInBinary;
-    Vector<SignatureIndex> m_moduleSignatureIndicesToUniquedSignatureIndices;
+    Ref<ModuleInformation> m_moduleInformation;
     Bag<CallLinkInfo> m_callLinkInfos;
     Vector<WasmExitStubs> m_wasmExitStubs;
     Vector<std::unique_ptr<WasmInternalFunction>> m_wasmInternalFunctions;
@@ -149,7 +149,7 @@ private:
     MemoryMode m_mode { MemoryMode::BoundsChecking };
     Lock m_lock;
     Condition m_completed;
-    State m_state { State::Initial };
+    State m_state;
     const AsyncWork m_asyncWork;
     uint8_t m_numberOfActiveThreads { 0 };
     uint32_t m_currentIndex { 0 };
index 2eb5728..f12af23 100644 (file)
@@ -127,6 +127,16 @@ const Signature& SignatureInformation::get(SignatureIndex index)
     return *info.m_indexMap.get(index);
 }
 
+SignatureIndex SignatureInformation::get(const Signature& signature)
+{
+    SignatureInformation& info = singleton();
+    LockHolder lock(info.m_lock);
+
+    auto result = info.m_signatureMap.get(SignatureHash { &signature });
+    ASSERT(result != Signature::invalidIndex);
+    return result;
+}
+
 void SignatureInformation::tryCleanup()
 {
     SignatureInformation& info = singleton();
index 61ac359..8f470d8 100644 (file)
@@ -168,6 +168,7 @@ public:
 
     static std::pair<SignatureIndex, Ref<Signature>> WARN_UNUSED_RETURN adopt(Ref<Signature>&&);
     static const Signature& WARN_UNUSED_RETURN get(SignatureIndex);
+    static SignatureIndex WARN_UNUSED_RETURN get(const Signature&);
     static void tryCleanup();
 
 private:
index 63a1e27..d949819 100644 (file)
@@ -139,7 +139,7 @@ public:
 
     // Calls
     Result WARN_UNUSED_RETURN addCall(unsigned calleeIndex, const Signature&, const Vector<ExpressionType>& args, ExpressionType& result);
-    Result WARN_UNUSED_RETURN addCallIndirect(const Signature&, SignatureIndex, const Vector<ExpressionType>& args, ExpressionType& result);
+    Result WARN_UNUSED_RETURN addCallIndirect(const Signature&, const Vector<ExpressionType>& args, ExpressionType& result);
 
     bool hasMemory() const { return !!m_module.memory; }
 
@@ -335,10 +335,8 @@ auto Validate::addCall(unsigned, const Signature& signature, const Vector<Expres
     return { };
 }
 
-auto Validate::addCallIndirect(const Signature& signature, SignatureIndex signatureIndex, const Vector<ExpressionType>& args, ExpressionType& result) -> Result
+auto Validate::addCallIndirect(const Signature& signature, const Vector<ExpressionType>& args, ExpressionType& result) -> Result
 {
-    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);
 
@@ -382,10 +380,10 @@ void Validate::dump(const Vector<ControlEntry>& controlStack, const ExpressionLi
     dataLogLn();
 }
 
-Expected<void, String> validateFunction(const uint8_t* source, size_t length, const Signature& signature, const ModuleInformation& module, const Vector<SignatureIndex>& moduleSignatureIndicesToUniquedSignatureIndices)
+Expected<void, String> validateFunction(const uint8_t* source, size_t length, const Signature& signature, const ModuleInformation& module)
 {
     Validate context(module);
-    FunctionParser<Validate> validator(context, source, length, signature, module, moduleSignatureIndicesToUniquedSignatureIndices);
+    FunctionParser<Validate> validator(context, source, length, signature, module);
     WASM_FAIL_IF_HELPER_FAILS(validator.parse());
     return { };
 }
index a4fec59..28283cf 100644 (file)
 
 #if ENABLE(WEBASSEMBLY)
 
-#include "WasmFormat.h"
+#include "WasmModuleInformation.h"
 #include <wtf/Expected.h>
 
 namespace JSC {
 
 namespace Wasm {
 
-Expected<void, String> validateFunction(const uint8_t*, size_t, const Signature&, const ModuleInformation&, const Vector<SignatureIndex>&);
+Expected<void, String> validateFunction(const uint8_t*, size_t, const Signature&, const ModuleInformation&);
 
 } } // namespace JSC::Wasm
 
index 578a69f..14487f0 100644 (file)
@@ -73,20 +73,23 @@ ALWAYS_INLINE uint8_t* getWasmBufferFromValue(ExecState* exec, JSValue value, si
     return arrayBufferView ? static_cast<uint8_t*>(arrayBufferView->vector()) : static_cast<uint8_t*>(arrayBuffer->impl()->data());
 }
 
-ALWAYS_INLINE RefPtr<ArrayBuffer> createSourceBufferFromValue(VM& vm, ExecState* exec, JSValue value)
+ALWAYS_INLINE Vector<uint8_t> createSourceBufferFromValue(VM& vm, ExecState* exec, JSValue value)
 {
     auto throwScope = DECLARE_THROW_SCOPE(vm);
     size_t byteOffset;
     size_t byteSize;
     uint8_t* data = getWasmBufferFromValue(exec, value, byteOffset, byteSize);
-    RETURN_IF_EXCEPTION(throwScope, nullptr);
+    RETURN_IF_EXCEPTION(throwScope, Vector<uint8_t>());
 
-    auto buffer = ArrayBuffer::tryCreate(data + byteOffset, byteSize);
-    if (buffer)
-        return buffer;
+    Vector<uint8_t> result;
+    if (!result.tryReserveCapacity(byteSize)) {
+        throwException(exec, throwScope, createOutOfMemoryError(exec));
+        return result;
+    }
 
-    throwException(exec, throwScope, createOutOfMemoryError(exec));
-    return nullptr;
+    result.grow(byteSize);
+    memcpy(result.data(), data + byteOffset, byteSize);
+    return result;
 }
 
 ALWAYS_INLINE bool isWebAssemblyHostFunction(VM& vm, JSObject* object, WebAssemblyFunction*& wasmFunction, WebAssemblyWrapperFunction*& wasmWrapperFunction)
index 81c2b6b..15def1c 100644 (file)
@@ -43,7 +43,7 @@ namespace JSC {
 
 const ClassInfo JSWebAssemblyModule::s_info = { "WebAssembly.Module", &Base::s_info, nullptr, CREATE_METHOD_TABLE(JSWebAssemblyModule) };
 
-JSWebAssemblyModule* JSWebAssemblyModule::createStub(VM& vm, ExecState* exec, Structure* structure, RefPtr<ArrayBuffer>&& source, RefPtr<Wasm::Plan>&& plan)
+JSWebAssemblyModule* JSWebAssemblyModule::createStub(VM& vm, ExecState* exec, Structure* structure, RefPtr<Wasm::Plan>&& plan)
 {
     ASSERT(!plan->hasWork());
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -52,8 +52,8 @@ JSWebAssemblyModule* JSWebAssemblyModule::createStub(VM& vm, ExecState* exec, St
         return nullptr;
     }
 
-    auto* module = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap)) JSWebAssemblyModule(vm, structure, WTFMove(source));
-    module->finishCreation(vm, WTFMove(plan));
+    auto* module = new (NotNull, allocateCell<JSWebAssemblyModule>(vm.heap)) JSWebAssemblyModule(vm, structure, *plan.get());
+    module->finishCreation(vm);
     return module;
 }
 
@@ -62,37 +62,23 @@ Structure* JSWebAssemblyModule::createStructure(VM& vm, JSGlobalObject* globalOb
     return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
 }
 
-JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, RefPtr<ArrayBuffer>&& source)
+JSWebAssemblyModule::JSWebAssemblyModule(VM& vm, Structure* structure, Wasm::Plan& plan)
     : Base(vm, structure)
-    , m_sourceBuffer(source.releaseNonNull())
+    , m_moduleInformation(plan.takeModuleInformation())
 {
 }
 
-void JSWebAssemblyModule::finishCreation(VM& vm, RefPtr<Wasm::Plan>&& plan)
+void JSWebAssemblyModule::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
     ASSERT(inherits(vm, info()));
 
-    std::unique_ptr<Wasm::ModuleInformation> moduleInformation = plan->takeModuleInformation();
-    for (auto& exp : moduleInformation->exports) {
-        ASSERT(exp.field.isSafeToSendToAnotherThread());
-        exp.field = AtomicString(exp.field);
-    }
-    for (auto& imp : moduleInformation->imports) {
-        ASSERT(imp.field.isSafeToSendToAnotherThread());
-        imp.field = AtomicString(imp.field);
-        ASSERT(imp.module.isSafeToSendToAnotherThread());
-        imp.module = AtomicString(imp.module);
-    }
-
-    m_moduleInformation = WTFMove(moduleInformation);
-
     // On success, a new WebAssembly.Module object is returned with [[Module]] set to the validated Ast.module.
     SymbolTable* exportSymbolTable = SymbolTable::create(vm);
     for (auto& exp : m_moduleInformation->exports) {
         auto offset = exportSymbolTable->takeNextScopeOffset(NoLockingNecessary);
-        ASSERT(exp.field.impl()->isAtomic());
-        exportSymbolTable->set(NoLockingNecessary, static_cast<AtomicStringImpl*>(exp.field.impl()), SymbolTableEntry(VarOffset(offset)));
+        String field = String::fromUTF8(exp.field);
+        exportSymbolTable->set(NoLockingNecessary, AtomicString(field).impl(), SymbolTableEntry(VarOffset(offset)));
     }
 
     m_exportSymbolTable.set(vm, this, exportSymbolTable);
index 549ae82..577c036 100644 (file)
@@ -31,7 +31,7 @@
 #include "JSObject.h"
 #include "JSWebAssemblyCodeBlock.h"
 #include "UnconditionalFinalizer.h"
-#include "WasmFormat.h"
+#include "WasmModuleInformation.h"
 #include <wtf/Bag.h>
 #include <wtf/Vector.h>
 
@@ -49,12 +49,12 @@ class JSWebAssemblyModule : public JSDestructibleObject {
 public:
     typedef JSDestructibleObject Base;
 
-    static JSWebAssemblyModule* createStub(VM&, ExecState*, Structure*, RefPtr<ArrayBuffer>&& source, RefPtr<Wasm::Plan>&&);
+    static JSWebAssemblyModule* createStub(VM&, ExecState*, Structure*, RefPtr<Wasm::Plan>&&);
     static Structure* createStructure(VM&, JSGlobalObject*, JSValue);
 
     DECLARE_INFO;
 
-    const Wasm::ModuleInformation& moduleInformation() const { return *m_moduleInformation.get(); }
+    const Wasm::ModuleInformation& moduleInformation() const { return m_moduleInformation.get(); }
     SymbolTable* exportSymbolTable() const { return m_exportSymbolTable.get(); }
     Wasm::SignatureIndex signatureIndexFromFunctionIndexSpace(unsigned functionIndexSpace) const
     {
@@ -64,20 +64,19 @@ public:
 
     JSWebAssemblyCodeBlock* codeBlock(Wasm::MemoryMode mode) { return m_codeBlocks[static_cast<size_t>(mode)].get(); }
 
-    ArrayBuffer& source() const { return m_sourceBuffer.get(); }
+    const Vector<uint8_t>& source() const { return moduleInformation().source; }
 
 private:
     friend class JSWebAssemblyCodeBlock;
 
     void setCodeBlock(VM&, Wasm::MemoryMode, JSWebAssemblyCodeBlock*);
 
-    JSWebAssemblyModule(VM&, Structure*, RefPtr<ArrayBuffer>&&);
-    void finishCreation(VM&, RefPtr<Wasm::Plan>&&);
+    JSWebAssemblyModule(VM&, Structure*, Wasm::Plan&);
+    void finishCreation(VM&);
     static void destroy(JSCell*);
     static void visitChildren(JSCell*, SlotVisitor&);
 
-    Ref<ArrayBuffer> m_sourceBuffer;
-    std::unique_ptr<const Wasm::ModuleInformation> m_moduleInformation;
+    Ref<Wasm::ModuleInformation> m_moduleInformation;
     WriteBarrier<SymbolTable> m_exportSymbolTable;
     WriteBarrier<JSWebAssemblyCodeBlock> m_codeBlocks[Wasm::NumberOfMemoryModes];
     WriteBarrier<WebAssemblyToJSCallee> m_callee;
index 041dd35..3c47f41 100644 (file)
@@ -87,7 +87,7 @@ static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyInstance(ExecState* ex
         if (instance->codeBlock())
             Wasm::ensureWorklist().completePlanSynchronously(instance->codeBlock()->plan());
         else {
-            Ref<Wasm::Plan> plan = adoptRef(*new Plan(vm, module->source(), Plan::FullCompile, Plan::dontFinalize));
+            Ref<Wasm::Plan> plan = adoptRef(*new Plan(vm, makeRef(const_cast<Wasm::ModuleInformation&>(module->moduleInformation())), Plan::FullCompile, Plan::dontFinalize));
             plan->setModeAndPromise(instance->memoryMode(), nullptr);
             instance->addUnitializedCodeBlock(vm, plan.copyRef());
 
index f75e9a7..8eacc1e 100644 (file)
@@ -75,13 +75,13 @@ JSValue WebAssemblyModuleConstructor::createModule(ExecState* exec, JSValue buff
     VM& vm = exec->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
-    RefPtr<ArrayBuffer> source = createSourceBufferFromValue(vm, exec, buffer);
+    Vector<uint8_t> source = createSourceBufferFromValue(vm, exec, buffer);
     RETURN_IF_EXCEPTION(scope, { });
 
-    RefPtr<Wasm::Plan> plan = adoptRef(new Wasm::Plan(vm, *source, Wasm::Plan::Validation, Wasm::Plan::dontFinalize));
+    RefPtr<Wasm::Plan> plan = adoptRef(new Wasm::Plan(vm, WTFMove(source), Wasm::Plan::Validation, Wasm::Plan::dontFinalize));
     if (!plan->parseAndValidateModule())
         return throwException(exec, scope, JSWebAssemblyCompileError::create(exec, vm, exec->lexicalGlobalObject()->WebAssemblyCompileErrorStructure(), plan->errorMessage()));
-    return JSWebAssemblyModule::createStub(vm, exec, structure, WTFMove(source), WTFMove(plan));
+    return JSWebAssemblyModule::createStub(vm, exec, structure, WTFMove(plan));
 }
 
 WebAssemblyModuleConstructor* WebAssemblyModuleConstructor::create(VM& vm, Structure* structure, WebAssemblyModulePrototype* thisPrototype)
index cea97dc..7e8fa01 100644 (file)
@@ -73,7 +73,7 @@ EncodedJSValue JSC_HOST_CALL webAssemblyModuleProtoCustomSections(ExecState* exe
 
     const auto& customSections = module->moduleInformation().customSections;
     for (const Wasm::CustomSection& section : customSections) {
-        if (section.name == sectionNameString) {
+        if (String::fromUTF8(section.name) == sectionNameString) {
             auto buffer = ArrayBuffer::tryCreate(section.payload.data(), section.payload.size());
             if (!buffer)
                 return JSValue::encode(throwException(exec, throwScope, createOutOfMemoryError(exec)));
@@ -110,8 +110,8 @@ EncodedJSValue JSC_HOST_CALL webAssemblyModuleProtoImports(ExecState* exec)
         for (const Wasm::Import& imp : imports) {
             JSObject* obj = constructEmptyObject(exec);
             RETURN_IF_EXCEPTION(throwScope, { });
-            obj->putDirect(vm, module, jsString(exec, imp.module));
-            obj->putDirect(vm, name, jsString(exec, imp.field));
+            obj->putDirect(vm, module, jsString(exec, String::fromUTF8(imp.module)));
+            obj->putDirect(vm, name, jsString(exec, String::fromUTF8(imp.field)));
             obj->putDirect(vm, kind, jsString(exec, String(makeString(imp.kind))));
             result->push(exec, obj);
             RETURN_IF_EXCEPTION(throwScope, { });
@@ -141,7 +141,7 @@ EncodedJSValue JSC_HOST_CALL webAssemblyModuleProtoExports(ExecState* exec)
         for (const Wasm::Export& exp : exports) {
             JSObject* obj = constructEmptyObject(exec);
             RETURN_IF_EXCEPTION(throwScope, { });
-            obj->putDirect(vm, name, jsString(exec, exp.field));
+            obj->putDirect(vm, name, jsString(exec, String::fromUTF8(exp.field)));
             obj->putDirect(vm, kind, jsString(exec, String(makeString(exp.kind))));
             result->push(exec, obj);
             RETURN_IF_EXCEPTION(throwScope, { });
index 1f41648..0171f2d 100644 (file)
@@ -37,7 +37,6 @@
 #include "JSWebAssemblyLinkError.h"
 #include "JSWebAssemblyModule.h"
 #include "ProtoCallFrame.h"
-#include "WasmFormat.h"
 #include "WasmSignature.h"
 #include "WebAssemblyFunction.h"
 #include <limits>
@@ -129,7 +128,7 @@ void WebAssemblyModuleRecord::link(ExecState* exec, JSWebAssemblyModule* module,
                 Wasm::Callee& wasmEntrypointCallee = codeBlock->wasmEntrypointCalleeFromFunctionIndexSpace(exp.kindIndex);
                 Wasm::SignatureIndex signatureIndex = module->signatureIndexFromFunctionIndexSpace(exp.kindIndex);
                 const Wasm::Signature& signature = Wasm::SignatureInformation::get(signatureIndex);
-                WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature.argumentCount(), exp.field, instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
+                WebAssemblyFunction* function = WebAssemblyFunction::create(vm, globalObject, signature.argumentCount(), String::fromUTF8(exp.field), instance, jsEntrypointCallee, wasmEntrypointCallee, signatureIndex);
                 exportedValue = function;
             }
             break;
index 2b8372e..a08ccbc 100644 (file)
@@ -28,7 +28,7 @@
 #if ENABLE(WEBASSEMBLY)
 
 #include "AbstractModuleRecord.h"
-#include "WasmFormat.h"
+#include "WasmModuleInformation.h"
 
 namespace JSC {
 
index 79f46bf..2dae77b 100644 (file)
@@ -83,20 +83,20 @@ static EncodedJSValue JSC_HOST_CALL webAssemblyCompileFunc(ExecState* exec)
     JSPromiseDeferred* promise = JSPromiseDeferred::create(exec, globalObject);
     RETURN_IF_EXCEPTION(scope, { });
 
-    RefPtr<ArrayBuffer> source = createSourceBufferFromValue(vm, exec, exec->argument(0));
+    Vector<uint8_t> source = createSourceBufferFromValue(vm, exec, exec->argument(0));
     RETURN_IF_EXCEPTION(scope, { });
 
     Vector<Strong<JSCell>> dependencies;
     dependencies.append(Strong<JSCell>(vm, globalObject));
     vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies));
 
-    Ref<Plan> plan = adoptRef(*new Plan(vm, *source, Plan::Validation, [source, promise, globalObject] (Plan& p) mutable {
+    Ref<Plan> plan = adoptRef(*new Plan(vm, WTFMove(source), Plan::Validation, [promise, globalObject] (Plan& p) mutable {
         RefPtr<Plan> plan = makeRef(p);
-        plan->vm().promiseDeferredTimer->scheduleWorkSoon(promise, [source, promise, globalObject, plan = WTFMove(plan)] () mutable {
+        plan->vm().promiseDeferredTimer->scheduleWorkSoon(promise, [promise, globalObject, plan = WTFMove(plan)] () mutable {
             VM& vm = plan->vm();
             auto scope = DECLARE_CATCH_SCOPE(vm);
             ExecState* exec = globalObject->globalExec();
-            JSValue module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(source), WTFMove(plan));
+            JSValue module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(plan));
             if (scope.exception()) {
                 reject(exec, scope, promise);
                 return;
@@ -167,7 +167,7 @@ static void instantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSW
 
     // FIXME: This re-parses the module header, which shouldn't be necessary.
     // https://bugs.webkit.org/show_bug.cgi?id=170205
-    Ref<Plan> plan = adoptRef(*new Plan(vm, module->source(), Plan::FullCompile, [promise, instance, module, entries] (Plan& p) {
+    Ref<Plan> plan = adoptRef(*new Plan(vm, makeRef(const_cast<Wasm::ModuleInformation&>(module->moduleInformation())), Plan::FullCompile, [promise, instance, module, entries] (Plan& p) {
         RefPtr<Plan> plan = makeRef(p);
         plan->vm().promiseDeferredTimer->scheduleWorkSoon(promise, [promise, instance, module, entries, plan = WTFMove(plan)] () {
             VM& vm = plan->vm();
@@ -184,7 +184,7 @@ static void instantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSW
 static void compileAndInstantiate(VM& vm, ExecState* exec, JSPromiseDeferred* promise, JSValue buffer, JSObject* importObject)
 {
     auto scope = DECLARE_THROW_SCOPE(vm);
-    RefPtr<ArrayBuffer> source = createSourceBufferFromValue(vm, exec, buffer);
+    Vector<uint8_t> source = createSourceBufferFromValue(vm, exec, buffer);
     RETURN_IF_EXCEPTION(scope, void());
 
     auto* globalObject = exec->lexicalGlobalObject();
@@ -193,13 +193,13 @@ static void compileAndInstantiate(VM& vm, ExecState* exec, JSPromiseDeferred* pr
     dependencies.append(Strong<JSCell>(vm, importObject));
     vm.promiseDeferredTimer->addPendingPromise(promise, WTFMove(dependencies));
 
-    Ref<Plan> plan = adoptRef(*new Plan(vm, *source, Plan::Validation, [source, promise, importObject, globalObject] (Plan& p) mutable {
+    Ref<Plan> plan = adoptRef(*new Plan(vm, WTFMove(source), Plan::Validation, [promise, importObject, globalObject] (Plan& p) mutable {
         RefPtr<Plan> plan = makeRef(p);
-        plan->vm().promiseDeferredTimer->scheduleWorkSoon(promise, [source, promise, importObject, globalObject, plan = WTFMove(plan)] () mutable {
+        plan->vm().promiseDeferredTimer->scheduleWorkSoon(promise, [promise, importObject, globalObject, plan = WTFMove(plan)] () mutable {
             VM& vm = plan->vm();
             auto scope = DECLARE_CATCH_SCOPE(vm);
             ExecState* exec = globalObject->globalExec();
-            JSWebAssemblyModule* module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), WTFMove(source), plan.copyRef());
+            JSWebAssemblyModule* module = JSWebAssemblyModule::createStub(vm, exec, globalObject->WebAssemblyModuleStructure(), plan.copyRef());
             if (scope.exception()) {
                 reject(exec, scope, promise);
                 return;
index 14d963e..6e9626e 100644 (file)
@@ -1,3 +1,20 @@
+2017-04-04  Keith Miller  <keith_miller@apple.com>
+
+        WebAssembly: ModuleInformation should be a ref counted thing that can be shared across threads.
+        https://bugs.webkit.org/show_bug.cgi?id=170478
+
+        Reviewed by Saam Barati.
+
+        This adds a new String::fromUTF8 that converts a vector of characters to
+        a string.
+
+        Also, it cleans up some style.
+
+        * wtf/text/WTFString.h:
+        (WTF::String::fromUTF8):
+        * wtf/unicode/UTF8.cpp:
+        (WTF::Unicode::convertLatin1ToUTF8):
+
 2017-04-04  Filip Pizlo  <fpizlo@apple.com>
 
         B3::fixSSA() needs a tune-up
index cb4232d..30b375e 100644 (file)
@@ -433,6 +433,7 @@ public:
     static String fromUTF8(const char* s, size_t length) { return fromUTF8(reinterpret_cast<const LChar*>(s), length); };
     static String fromUTF8(const char* s) { return fromUTF8(reinterpret_cast<const LChar*>(s)); };
     WTF_EXPORT_STRING_API static String fromUTF8(const CString&);
+    static String fromUTF8(const Vector<LChar>& characters);
 
     // Tries to convert the passed in string to UTF-8, but will fall back to Latin-1 if the string is not valid UTF-8.
     WTF_EXPORT_STRING_API static String fromUTF8WithLatin1Fallback(const LChar*, size_t);
@@ -694,6 +695,13 @@ private:
 // Shared global empty string.
 WTF_EXPORT_STRING_API const String& emptyString();
 
+inline String String::fromUTF8(const Vector<LChar>& characters)
+{
+    if (characters.isEmpty())
+        return emptyString();
+    return fromUTF8(characters.data(), characters.size());
+}
+
 template<unsigned length> inline bool equalLettersIgnoringASCIICase(const String& string, const char (&lowercaseLetters)[length])
 {
     return equalLettersIgnoringASCIICase(string.impl(), lowercaseLetters);
index 5407401..c0c8d8b 100644 (file)
@@ -126,8 +126,8 @@ int decodeUTF8Sequence(const char* sequence)
 static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
 
 ConversionResult convertLatin1ToUTF8(
-                                     const LChar** sourceStart, const LChar* sourceEnd, 
-                                     char** targetStart, char* targetEnd)
+    const LChar** sourceStart, const LChar* sourceEnd, 
+    char** targetStart, char* targetEnd)
 {
     ConversionResult result = conversionOK;
     const LChar* source = *sourceStart;