[WebAssembly] Use StreamingParser in existing Wasm::BBQPlan
authorysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Sep 2019 09:42:15 +0000 (09:42 +0000)
committerysuzuki@apple.com <ysuzuki@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 10 Sep 2019 09:42:15 +0000 (09:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=189043

Reviewed by Keith Miller.

JSTests:

The offset performing the validation becomes a bit different.
The offset 0 is nice since it is the starting offset of the Module header signature compared to the offset 8.

* wasm/js-api/version.js:

Source/JavaScriptCore:

This patch integrates Wasm::StreamingParser into the existing Wasm::BBQPlan.
And remove Wasm::ModuleParser. This patch paves the way to implementing Wasm streaming features by
using Wasm::StreamingParser.

Currently, we are not using streaming feature of StreamingParser. In a subsequent patch, we will
create a mechanism to pipe a chunk of data to streaming parser to enable WebAssembly.compileStreaming
and instantiateStreaming.

* JavaScriptCore.xcodeproj/project.pbxproj:
* Sources.txt:
* tools/JSDollarVM.cpp:
(JSC::WasmStreamingParser::WasmStreamingParser):
* wasm/WasmAirIRGenerator.cpp:
(JSC::Wasm::parseAndCompileAir):
* wasm/WasmAirIRGenerator.h:
* wasm/WasmB3IRGenerator.cpp:
(JSC::Wasm::parseAndCompile): Use FunctionData, it is good since it is more strongly typed.
* wasm/WasmB3IRGenerator.h:
* wasm/WasmBBQPlan.cpp:
(JSC::Wasm::BBQPlan::BBQPlan):
(JSC::Wasm::BBQPlan::didReceiveFunctionData): Add a callback, which invokes validation.
(JSC::Wasm::BBQPlan::parseAndValidateModule): Use StreamingParser instead of old ModuleParser.
(JSC::Wasm::BBQPlan::compileFunctions):
(JSC::Wasm::BBQPlan::complete):
* wasm/WasmBBQPlan.h:
* wasm/WasmModuleParser.cpp: Removed.
* wasm/WasmModuleParser.h: Removed.
* wasm/WasmOMGForOSREntryPlan.cpp:
(JSC::Wasm::OMGForOSREntryPlan::work):
* wasm/WasmOMGPlan.cpp:
(JSC::Wasm::OMGPlan::work):
* wasm/WasmPlan.cpp:
(JSC::Wasm::Plan::fail): Make fail function callable multiple times. The first error will be used.
* wasm/WasmSectionParser.cpp:
(JSC::Wasm::SectionParser::parseCode): Since the Code section is specially handled in StreamingParser, this code is never used.
* wasm/WasmStreamingParser.cpp:
(JSC::Wasm::StreamingParser::StreamingParser):
(JSC::Wasm::StreamingParser::parseCodeSectionSize):
(JSC::Wasm::StreamingParser::parseFunctionPayload):
(JSC::Wasm::StreamingParser::parseSectionPayload):
(JSC::Wasm::StreamingParser::finalize): Call client's callbacks at appropriate timings.
* wasm/WasmStreamingParser.h:
(JSC::Wasm::StreamingParserClient::didReceiveSectionData):
(JSC::Wasm::StreamingParserClient::didReceiveFunctionData):
(JSC::Wasm::StreamingParserClient::didFinishParsing): Add StreamingParserClient,
which has 3 callbacks right now. StreamingParser gets this client and call these callbacks
at appropriate timings.
* wasm/WasmValidate.cpp:
(JSC::Wasm::validateFunction):
* wasm/WasmValidate.h: Use FunctionData, it is good since it is more strongly typed.

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

22 files changed:
JSTests/ChangeLog
JSTests/wasm/js-api/version.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Sources.txt
Source/JavaScriptCore/tools/JSDollarVM.cpp
Source/JavaScriptCore/wasm/WasmAirIRGenerator.cpp
Source/JavaScriptCore/wasm/WasmAirIRGenerator.h
Source/JavaScriptCore/wasm/WasmB3IRGenerator.cpp
Source/JavaScriptCore/wasm/WasmB3IRGenerator.h
Source/JavaScriptCore/wasm/WasmBBQPlan.cpp
Source/JavaScriptCore/wasm/WasmBBQPlan.h
Source/JavaScriptCore/wasm/WasmModuleParser.cpp [deleted file]
Source/JavaScriptCore/wasm/WasmModuleParser.h [deleted file]
Source/JavaScriptCore/wasm/WasmOMGForOSREntryPlan.cpp
Source/JavaScriptCore/wasm/WasmOMGPlan.cpp
Source/JavaScriptCore/wasm/WasmPlan.cpp
Source/JavaScriptCore/wasm/WasmSectionParser.cpp
Source/JavaScriptCore/wasm/WasmStreamingParser.cpp
Source/JavaScriptCore/wasm/WasmStreamingParser.h
Source/JavaScriptCore/wasm/WasmValidate.cpp
Source/JavaScriptCore/wasm/WasmValidate.h

index 10cc460..32c0b7a 100644 (file)
@@ -1,3 +1,15 @@
+2019-09-10  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [WebAssembly] Use StreamingParser in existing Wasm::BBQPlan
+        https://bugs.webkit.org/show_bug.cgi?id=189043
+
+        Reviewed by Keith Miller.
+
+        The offset performing the validation becomes a bit different.
+        The offset 0 is nice since it is the starting offset of the Module header signature compared to the offset 8.
+
+        * wasm/js-api/version.js:
+
 2019-09-07  Keith Miller  <keith_miller@apple.com>
 
         OSR entry into wasm misses some contexts
index 0486fcf..4d10e8c 100644 (file)
@@ -5,5 +5,5 @@ for (let version = 0; version < 256; ++version) {
     if (version === 1)
         continue;
     const emptyModuleArray = Uint8Array.of(0x0, 0x61, 0x73, 0x6d, version, 0x00, 0x00, 0x00);
-    assert.throws(() => new WebAssembly.Module(emptyModuleArray), WebAssembly.CompileError, `WebAssembly.Module doesn't parse at byte 8: unexpected version number ${version} expected 1`);
+    assert.throws(() => new WebAssembly.Module(emptyModuleArray), WebAssembly.CompileError, `WebAssembly.Module doesn't parse at byte 0: unexpected version number ${version} expected 1`);
 }
index db4a3a0..18912cc 100644 (file)
@@ -1,3 +1,61 @@
+2019-09-10  Yusuke Suzuki  <ysuzuki@apple.com>
+
+        [WebAssembly] Use StreamingParser in existing Wasm::BBQPlan
+        https://bugs.webkit.org/show_bug.cgi?id=189043
+
+        Reviewed by Keith Miller.
+
+        This patch integrates Wasm::StreamingParser into the existing Wasm::BBQPlan.
+        And remove Wasm::ModuleParser. This patch paves the way to implementing Wasm streaming features by
+        using Wasm::StreamingParser.
+
+        Currently, we are not using streaming feature of StreamingParser. In a subsequent patch, we will
+        create a mechanism to pipe a chunk of data to streaming parser to enable WebAssembly.compileStreaming
+        and instantiateStreaming.
+
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * tools/JSDollarVM.cpp:
+        (JSC::WasmStreamingParser::WasmStreamingParser):
+        * wasm/WasmAirIRGenerator.cpp:
+        (JSC::Wasm::parseAndCompileAir):
+        * wasm/WasmAirIRGenerator.h:
+        * wasm/WasmB3IRGenerator.cpp:
+        (JSC::Wasm::parseAndCompile): Use FunctionData, it is good since it is more strongly typed.
+        * wasm/WasmB3IRGenerator.h:
+        * wasm/WasmBBQPlan.cpp:
+        (JSC::Wasm::BBQPlan::BBQPlan):
+        (JSC::Wasm::BBQPlan::didReceiveFunctionData): Add a callback, which invokes validation.
+        (JSC::Wasm::BBQPlan::parseAndValidateModule): Use StreamingParser instead of old ModuleParser.
+        (JSC::Wasm::BBQPlan::compileFunctions):
+        (JSC::Wasm::BBQPlan::complete):
+        * wasm/WasmBBQPlan.h:
+        * wasm/WasmModuleParser.cpp: Removed.
+        * wasm/WasmModuleParser.h: Removed.
+        * wasm/WasmOMGForOSREntryPlan.cpp:
+        (JSC::Wasm::OMGForOSREntryPlan::work):
+        * wasm/WasmOMGPlan.cpp:
+        (JSC::Wasm::OMGPlan::work):
+        * wasm/WasmPlan.cpp:
+        (JSC::Wasm::Plan::fail): Make fail function callable multiple times. The first error will be used.
+        * wasm/WasmSectionParser.cpp:
+        (JSC::Wasm::SectionParser::parseCode): Since the Code section is specially handled in StreamingParser, this code is never used.
+        * wasm/WasmStreamingParser.cpp:
+        (JSC::Wasm::StreamingParser::StreamingParser):
+        (JSC::Wasm::StreamingParser::parseCodeSectionSize):
+        (JSC::Wasm::StreamingParser::parseFunctionPayload):
+        (JSC::Wasm::StreamingParser::parseSectionPayload):
+        (JSC::Wasm::StreamingParser::finalize): Call client's callbacks at appropriate timings.
+        * wasm/WasmStreamingParser.h:
+        (JSC::Wasm::StreamingParserClient::didReceiveSectionData):
+        (JSC::Wasm::StreamingParserClient::didReceiveFunctionData):
+        (JSC::Wasm::StreamingParserClient::didFinishParsing): Add StreamingParserClient,
+        which has 3 callbacks right now. StreamingParser gets this client and call these callbacks
+        at appropriate timings.
+        * wasm/WasmValidate.cpp:
+        (JSC::Wasm::validateFunction):
+        * wasm/WasmValidate.h: Use FunctionData, it is good since it is more strongly typed.
+
 2019-09-09  Yusuke Suzuki  <ysuzuki@apple.com>
 
         [JSC] CodeBlock::m_constantRegisters should be guarded by ConcurrentJSLock when Vector reallocate memory
index 0d88b54..ae0eeb7 100644 (file)
                53F40E8B1D5901BB0099A1B6 /* WasmFunctionParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8A1D5901BB0099A1B6 /* WasmFunctionParser.h */; };
                53F40E8D1D5901F20099A1B6 /* WasmParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E8C1D5901F20099A1B6 /* WasmParser.h */; };
                53F40E931D5A4AB30099A1B6 /* WasmB3IRGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E921D5A4AB30099A1B6 /* WasmB3IRGenerator.h */; };
-               53F40E951D5A7AEF0099A1B6 /* WasmModuleParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */; };
                53F6BF6D1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
                53F8D2001E8387D400D21116 /* WasmBBQPlanInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 53F8D1FF1E8387D400D21116 /* WasmBBQPlanInlines.h */; };
                53FA2AE11CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
                53F40E8C1D5901F20099A1B6 /* WasmParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmParser.h; sourceTree = "<group>"; };
                53F40E8E1D5902820099A1B6 /* WasmB3IRGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmB3IRGenerator.cpp; sourceTree = "<group>"; };
                53F40E921D5A4AB30099A1B6 /* WasmB3IRGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmB3IRGenerator.h; sourceTree = "<group>"; };
-               53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmModuleParser.h; sourceTree = "<group>"; };
-               53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WasmModuleParser.cpp; sourceTree = "<group>"; };
                53F6BF6C1C3F060A00F41E5D /* InternalFunctionAllocationProfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InternalFunctionAllocationProfile.h; sourceTree = "<group>"; };
                53F8D1FF1E8387D400D21116 /* WasmBBQPlanInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmBBQPlanInlines.h; sourceTree = "<group>"; };
                53FA2AE01CF37F3F0022711D /* LLIntPrototypeLoadAdaptiveStructureWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LLIntPrototypeLoadAdaptiveStructureWatchpoint.h; sourceTree = "<group>"; };
                                790081371E95A8EC0052D7CD /* WasmModule.h */,
                                53E777E11E92E265007CBEC4 /* WasmModuleInformation.cpp */,
                                53E777E21E92E265007CBEC4 /* WasmModuleInformation.h */,
-                               53F40E961D5A7BEC0099A1B6 /* WasmModuleParser.cpp */,
-                               53F40E941D5A7AEF0099A1B6 /* WasmModuleParser.h */,
                                AD5B416E1EBAFB65008EFA43 /* WasmName.h */,
                                AD7B4B2D1FA3E28600C9DF79 /* WasmNameSection.h */,
                                ADD8FA441EB3077100DF542F /* WasmNameSectionParser.cpp */,
                                AD5C36EF1F7A263A000BCAAF /* WasmMemoryMode.h in Headers */,
                                790081391E95A8EC0052D7CD /* WasmModule.h in Headers */,
                                53E777E41E92E265007CBEC4 /* WasmModuleInformation.h in Headers */,
-                               53F40E951D5A7AEF0099A1B6 /* WasmModuleParser.h in Headers */,
                                AD5B416F1EBAFB77008EFA43 /* WasmName.h in Headers */,
                                AD7B4B2E1FA3E29800C9DF79 /* WasmNameSection.h in Headers */,
                                ADD8FA461EB3079700DF542F /* WasmNameSectionParser.h in Headers */,
index 262193b..cd7d992 100644 (file)
@@ -1013,7 +1013,6 @@ wasm/WasmMemoryInformation.cpp
 wasm/WasmMemoryMode.cpp
 wasm/WasmModule.cpp
 wasm/WasmModuleInformation.cpp
-wasm/WasmModuleParser.cpp
 wasm/WasmNameSectionParser.cpp
 wasm/WasmOMGForOSREntryPlan.cpp
 wasm/WasmOMGPlan.cpp
index 481763f..4d62fb5 100644 (file)
@@ -1110,10 +1110,25 @@ static EncodedJSValue JSC_HOST_CALL functionWasmStreamingParserFinalize(ExecStat
 
 class WasmStreamingParser : public JSDestructibleObject {
 public:
+    class Client final : public Wasm::StreamingParserClient {
+    public:
+        explicit Client(WasmStreamingParser* parser)
+            : m_parser(parser)
+        {
+        }
+
+        void didReceiveSectionData(Wasm::Section) override { }
+        void didReceiveFunctionData(unsigned, const Wasm::FunctionData&) override { }
+        void didFinishParsing() override { }
+
+        WasmStreamingParser* m_parser;
+    };
+
     WasmStreamingParser(VM& vm, Structure* structure)
         : Base(vm, structure)
         , m_info(Wasm::ModuleInformation::create())
-        , m_streamingParser(m_info.get())
+        , m_client(this)
+        , m_streamingParser(m_info.get(), m_client)
     {
     }
 
@@ -1146,6 +1161,7 @@ public:
     DECLARE_INFO;
 
     Ref<Wasm::ModuleInformation> m_info;
+    Client m_client;
     Wasm::StreamingParser m_streamingParser;
 };
 
index c8664fa..37eeff4 100644 (file)
@@ -2229,7 +2229,7 @@ auto AirIRGenerator::origin() -> B3::Origin
     return B3::Origin();
 }
 
-Expected<std::unique_ptr<InternalFunction>, String> parseAndCompileAir(CompilationContext& compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature& signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ModuleInformation& info, MemoryMode mode, uint32_t functionIndex, TierUpCount* tierUp, ThrowWasmException throwWasmException)
+Expected<std::unique_ptr<InternalFunction>, String> parseAndCompileAir(CompilationContext& compilationContext, const FunctionData& function, const Signature& signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ModuleInformation& info, MemoryMode mode, uint32_t functionIndex, TierUpCount* tierUp, ThrowWasmException throwWasmException)
 {
     auto result = makeUnique<InternalFunction>();
 
@@ -2253,7 +2253,7 @@ Expected<std::unique_ptr<InternalFunction>, String> parseAndCompileAir(Compilati
     procedure.setOptLevel(Options::webAssemblyBBQAirOptimizationLevel());
 
     AirIRGenerator irGenerator(info, procedure, result.get(), unlinkedWasmToWasmCalls, mode, functionIndex, tierUp, throwWasmException, signature);
-    FunctionParser<AirIRGenerator> parser(irGenerator, functionStart, functionLength, signature, info);
+    FunctionParser<AirIRGenerator> parser(irGenerator, function.data.data(), function.data.size(), signature, info);
     WASM_FAIL_IF_HELPER_FAILS(parser.parse());
 
 
index 36a73dd..331b4b0 100644 (file)
@@ -31,7 +31,7 @@
 
 namespace JSC { namespace Wasm {
 
-Expected<std::unique_ptr<InternalFunction>, String> parseAndCompileAir(CompilationContext&, const uint8_t*, size_t, const Signature&, Vector<UnlinkedWasmToWasmCall>&, const ModuleInformation&, MemoryMode, uint32_t functionIndex, TierUpCount* = nullptr, ThrowWasmException = nullptr);
+Expected<std::unique_ptr<InternalFunction>, String> parseAndCompileAir(CompilationContext&, const FunctionData&, const Signature&, Vector<UnlinkedWasmToWasmCall>&, const ModuleInformation&, MemoryMode, uint32_t functionIndex, TierUpCount* = nullptr, ThrowWasmException = nullptr);
 
 } } // namespace JSC::Wasm
 
index b167df5..3d8df8e 100644 (file)
@@ -1697,7 +1697,7 @@ auto B3IRGenerator::origin() -> Origin
     return bitwise_cast<Origin>(origin);
 }
 
-Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationContext& compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature& signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, unsigned& osrEntryScratchBufferSize, const ModuleInformation& info, MemoryMode mode, CompilationMode compilationMode, uint32_t functionIndex, uint32_t loopIndexForOSREntry, TierUpCount* tierUp, ThrowWasmException throwWasmException)
+Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationContext& compilationContext, const FunctionData& function, const Signature& signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, unsigned& osrEntryScratchBufferSize, const ModuleInformation& info, MemoryMode mode, CompilationMode compilationMode, uint32_t functionIndex, uint32_t loopIndexForOSREntry, TierUpCount* tierUp, ThrowWasmException throwWasmException)
 {
     auto result = makeUnique<InternalFunction>();
 
@@ -1722,7 +1722,7 @@ Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationC
         : Options::webAssemblyOMGOptimizationLevel());
 
     B3IRGenerator irGenerator(info, procedure, result.get(), unlinkedWasmToWasmCalls, osrEntryScratchBufferSize, mode, compilationMode, functionIndex, loopIndexForOSREntry, tierUp, throwWasmException);
-    FunctionParser<B3IRGenerator> parser(irGenerator, functionStart, functionLength, signature, info);
+    FunctionParser<B3IRGenerator> parser(irGenerator, function.data.data(), function.data.size(), signature, info);
     WASM_FAIL_IF_HELPER_FAILS(parser.parse());
 
     irGenerator.insertConstants();
index 5ecc51a..ea55024 100644 (file)
@@ -51,7 +51,7 @@ struct CompilationContext {
     std::unique_ptr<B3::OpaqueByproducts> wasmEntrypointByproducts;
 };
 
-Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationContext&, const uint8_t*, size_t, const Signature&, Vector<UnlinkedWasmToWasmCall>&, unsigned& osrEntryScratchBufferSize, const ModuleInformation&, MemoryMode, CompilationMode, uint32_t functionIndex, uint32_t loopIndexForOSREntry, TierUpCount* = nullptr, ThrowWasmException = nullptr);
+Expected<std::unique_ptr<InternalFunction>, String> parseAndCompile(CompilationContext&, const FunctionData&, const Signature&, Vector<UnlinkedWasmToWasmCall>&, unsigned& osrEntryScratchBufferSize, const ModuleInformation&, MemoryMode, CompilationMode, uint32_t functionIndex, uint32_t loopIndexForOSREntry, TierUpCount* = nullptr, ThrowWasmException = nullptr);
 
 } } // namespace JSC::Wasm
 
index fabc003..0e83d53 100644 (file)
@@ -36,7 +36,6 @@
 #include "WasmCallingConvention.h"
 #include "WasmFaultSignalHandler.h"
 #include "WasmMemory.h"
-#include "WasmModuleParser.h"
 #include "WasmSignatureInlines.h"
 #include "WasmTierUpCount.h"
 #include "WasmValidate.h"
@@ -55,6 +54,7 @@ static const bool verbose = false;
 
 BBQPlan::BBQPlan(Context* context, Ref<ModuleInformation> info, AsyncWork work, CompletionTask&& task, CreateEmbedderWrapper&& createEmbedderWrapper, ThrowWasmException throwWasmException)
     : Base(context, WTFMove(info), WTFMove(task), WTFMove(createEmbedderWrapper), throwWasmException)
+    , m_streamingParser(m_moduleInformation.get(), *this)
     , m_state(State::Validated)
     , m_asyncWork(work)
 {
@@ -63,6 +63,7 @@ BBQPlan::BBQPlan(Context* context, Ref<ModuleInformation> info, AsyncWork work,
 BBQPlan::BBQPlan(Context* context, Vector<uint8_t>&& source, AsyncWork work, CompletionTask&& task, CreateEmbedderWrapper&& createEmbedderWrapper, ThrowWasmException throwWasmException)
     : Base(context, ModuleInformation::create(), WTFMove(task), WTFMove(createEmbedderWrapper), throwWasmException)
     , m_source(WTFMove(source))
+    , m_streamingParser(m_moduleInformation.get(), *this)
     , m_state(State::Initial)
     , m_asyncWork(work)
 {
@@ -70,6 +71,7 @@ BBQPlan::BBQPlan(Context* context, Vector<uint8_t>&& source, AsyncWork work, Com
 
 BBQPlan::BBQPlan(Context* context, AsyncWork work, CompletionTask&& task)
     : Base(context, WTFMove(task))
+    , m_streamingParser(m_moduleInformation.get(), *this)
     , m_state(State::Initial)
     , m_asyncWork(work)
 {
@@ -94,6 +96,25 @@ void BBQPlan::moveToState(State state)
     m_state = state;
 }
 
+void BBQPlan::didReceiveFunctionData(unsigned functionIndex, const FunctionData& function)
+{
+    dataLogLnIf(WasmBBQPlanInternal::verbose, "Processing function starting at: ", function.start, " and ending at: ", function.end);
+    size_t functionLength = function.end - function.start;
+    ASSERT(functionLength == function.data.size());
+    SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex];
+    const Signature& signature = SignatureInformation::get(signatureIndex);
+
+    auto validationResult = validateFunction(function, signature, m_moduleInformation.get());
+    if (!validationResult) {
+        if (WasmBBQPlanInternal::verbose) {
+            for (unsigned i = 0; i < functionLength; ++i)
+                dataLog(RawPointer(reinterpret_cast<void*>(function.data[i])), ", ");
+            dataLogLn();
+        }
+        fail(holdLock(m_lock), makeString(validationResult.error(), ", in function at index ", String::number(functionIndex))); // FIXME make this an Expected.
+    }
+}
+
 bool BBQPlan::parseAndValidateModule(const uint8_t* source, size_t sourceLength)
 {
     if (m_state != State::Initial)
@@ -104,37 +125,16 @@ bool BBQPlan::parseAndValidateModule(const uint8_t* source, size_t sourceLength)
     if (WasmBBQPlanInternal::verbose || Options::reportCompileTimes())
         startTime = MonotonicTime::now();
 
-    {
-        ModuleParser moduleParser(source, sourceLength, m_moduleInformation);
-        auto parseResult = moduleParser.parse();
-        if (!parseResult) {
-            Base::fail(holdLock(m_lock), WTFMove(parseResult.error()));
-            return false;
-        }
+    m_streamingParser.addBytes(source, sourceLength);
+    if (m_streamingParser.finalize() != StreamingParser::State::Finished) {
+        fail(holdLock(m_lock), String(m_streamingParser.errorMessage()));
+        return false;
     }
-
-    const auto& functions = m_moduleInformation->functions;
-    for (unsigned functionIndex = 0; functionIndex < functions.size(); ++functionIndex) {
-        const auto& function = functions[functionIndex];
-        dataLogLnIf(WasmBBQPlanInternal::verbose, "Processing function starting at: ", function.start, " and ending at: ", function.end);
-        size_t functionLength = function.end - function.start;
-        ASSERT(functionLength <= sourceLength);
-        ASSERT(functionLength == function.data.size());
-        SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex];
-        const Signature& signature = SignatureInformation::get(signatureIndex);
-
-        auto validationResult = validateFunction(function.data.data(), function.data.size(), signature, m_moduleInformation.get());
-        if (!validationResult) {
-            if (WasmBBQPlanInternal::verbose) {
-                for (unsigned i = 0; i < functionLength; ++i)
-                    dataLog(RawPointer(reinterpret_cast<void*>(function.data[i])), ", ");
-                dataLogLn();
-            }
-            Base::fail(holdLock(m_lock), makeString(validationResult.error(), ", in function at index ", String::number(functionIndex))); // FIXME make this an Expected.
+    {
+        auto locker = holdLock(m_lock);
+        if (failed())
             return false;
-        }
     }
-
     if (WasmBBQPlanInternal::verbose || Options::reportCompileTimes())
         dataLogLn("Took ", (MonotonicTime::now() - startTime).microseconds(), " us to validate module");
 
@@ -264,7 +264,7 @@ void BBQPlan::compileFunctions(CompilationEffort effort)
         const Signature& signature = SignatureInformation::get(signatureIndex);
         unsigned functionIndexSpace = m_wasmToWasmExitStubs.size() + functionIndex;
         ASSERT_UNUSED(functionIndexSpace, m_moduleInformation->signatureIndexFromFunctionIndexSpace(functionIndexSpace) == signatureIndex);
-        ASSERT(validateFunction(function.data.data(), function.data.size(), signature, m_moduleInformation.get()));
+        ASSERT(validateFunction(function, signature, m_moduleInformation.get()));
 
         m_unlinkedWasmToWasmCalls[functionIndex] = Vector<UnlinkedWasmToWasmCall>();
         if (Options::useBBQTierUpChecks())
@@ -283,16 +283,13 @@ void BBQPlan::compileFunctions(CompilationEffort effort)
             forceUsingB3 = true;
 
         if (!forceUsingB3 && Options::wasmBBQUsesAir())
-            parseAndCompileResult = parseAndCompileAir(m_compilationContexts[functionIndex], function.data.data(), function.data.size(), signature, m_unlinkedWasmToWasmCalls[functionIndex], m_moduleInformation.get(), m_mode, functionIndex, tierUp, m_throwWasmException);
+            parseAndCompileResult = parseAndCompileAir(m_compilationContexts[functionIndex], function, signature, m_unlinkedWasmToWasmCalls[functionIndex], m_moduleInformation.get(), m_mode, functionIndex, tierUp, m_throwWasmException);
         else
-            parseAndCompileResult = parseAndCompile(m_compilationContexts[functionIndex], function.data.data(), function.data.size(), signature, m_unlinkedWasmToWasmCalls[functionIndex], osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::BBQMode, functionIndex, UINT32_MAX, tierUp, m_throwWasmException);
+            parseAndCompileResult = parseAndCompile(m_compilationContexts[functionIndex], function, signature, m_unlinkedWasmToWasmCalls[functionIndex], osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::BBQMode, functionIndex, UINT32_MAX, tierUp, m_throwWasmException);
 
         if (UNLIKELY(!parseAndCompileResult)) {
             auto locker = holdLock(m_lock);
-            if (!m_errorMessage) {
-                // 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.
-            }
+            fail(locker, makeString(parseAndCompileResult.error(), ", in function at index ", String::number(functionIndex))); // FIXME make this an Expected.
             m_currentIndex = functions.size();
             return;
         }
@@ -324,7 +321,7 @@ void BBQPlan::complete(const AbstractLocker& locker)
             {
                 LinkBuffer linkBuffer(*context.wasmEntrypointJIT, nullptr, JITCompilationCanFail);
                 if (UNLIKELY(linkBuffer.didFailToAllocate())) {
-                    Base::fail(locker, makeString("Out of executable memory in function at index ", String::number(functionIndex)));
+                    fail(locker, makeString("Out of executable memory in function at index ", String::number(functionIndex)));
                     return;
                 }
 
@@ -336,7 +333,7 @@ void BBQPlan::complete(const AbstractLocker& locker)
             if (auto embedderToWasmInternalFunction = m_embedderToWasmInternalFunctions.get(functionIndex)) {
                 LinkBuffer linkBuffer(*context.embedderEntrypointJIT, nullptr, JITCompilationCanFail);
                 if (UNLIKELY(linkBuffer.didFailToAllocate())) {
-                    Base::fail(locker, makeString("Out of executable memory in function entrypoint at index ", String::number(functionIndex)));
+                    fail(locker, makeString("Out of executable memory in function entrypoint at index ", String::number(functionIndex)));
                     return;
                 }
 
index a2604e5..883617f 100644 (file)
@@ -31,6 +31,7 @@
 #include "WasmB3IRGenerator.h"
 #include "WasmModuleInformation.h"
 #include "WasmPlan.h"
+#include "WasmStreamingParser.h"
 #include "WasmTierUpCount.h"
 #include <wtf/Bag.h>
 #include <wtf/Function.h>
@@ -44,7 +45,7 @@ class CallLinkInfo;
 
 namespace Wasm {
 
-class BBQPlan final : public Plan {
+class BBQPlan final : public Plan, public StreamingParserClient {
 public:
     using Base = Plan;
     enum AsyncWork : uint8_t { FullCompile, Validation };
@@ -121,6 +122,8 @@ public:
     bool hasBeenPrepared() const { return m_state >= State::Prepared; }
     bool multiThreaded() const override { return hasBeenPrepared(); }
 
+    void didReceiveFunctionData(unsigned, const FunctionData&) override;
+
 private:
     class ThreadCountHolder;
     friend class ThreadCountHolder;
@@ -143,6 +146,7 @@ private:
     Vector<std::unique_ptr<TierUpCount>> m_tierUpCounts;
 
     Vector<Vector<UnlinkedWasmToWasmCall>> m_unlinkedWasmToWasmCalls;
+    StreamingParser m_streamingParser;
     State m_state;
 
     const AsyncWork m_asyncWork;
diff --git a/Source/JavaScriptCore/wasm/WasmModuleParser.cpp b/Source/JavaScriptCore/wasm/WasmModuleParser.cpp
deleted file mode 100644 (file)
index 7bc8ead..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2016-2018 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 "WasmModuleParser.h"
-
-#if ENABLE(WEBASSEMBLY)
-
-#include "IdentifierInlines.h"
-#include "WasmMemoryInformation.h"
-#include "WasmNameSectionParser.h"
-#include "WasmOps.h"
-#include "WasmSectionParser.h"
-#include "WasmSections.h"
-#include <wtf/SHA1.h>
-
-namespace JSC { namespace Wasm {
-
-auto ModuleParser::parse() -> Result
-{
-    const size_t minSize = 8;
-    uint32_t versionNumber;
-
-    WASM_PARSER_FAIL_IF(length() < minSize, "expected a module of at least ", minSize, " bytes");
-    WASM_PARSER_FAIL_IF(length() > maxModuleSize, "module size ", length(), " is too large, maximum ", maxModuleSize);
-    WASM_PARSER_FAIL_IF(!consumeCharacter(0) || !consumeString("asm"), "modules doesn't start with '\\0asm'");
-    WASM_PARSER_FAIL_IF(!parseUInt32(versionNumber), "can't parse version number");
-    WASM_PARSER_FAIL_IF(versionNumber != expectedVersionNumber, "unexpected version number ", versionNumber, " expected ", expectedVersionNumber);
-
-    // This is not really a known section.
-    Section previousKnownSection = Section::Begin;
-    while (m_offset < length()) {
-        uint8_t sectionByte;
-
-        WASM_PARSER_FAIL_IF(!parseUInt7(sectionByte), "can't get section byte");
-
-        Section section = Section::Custom;
-        WASM_PARSER_FAIL_IF(!decodeSection(sectionByte, section));
-        ASSERT(section != Section::Begin);
-
-        uint32_t sectionLength;
-        WASM_PARSER_FAIL_IF(!validateOrder(previousKnownSection, section), "invalid section order, ", previousKnownSection, " followed by ", section);
-        WASM_PARSER_FAIL_IF(!parseVarUInt32(sectionLength), "can't get ", section, " section's length");
-        WASM_PARSER_FAIL_IF(sectionLength > length() - m_offset, section, " section of size ", sectionLength, " would overflow Module's size");
-
-        SectionParser parser(source() + m_offset, sectionLength, m_offset, m_info.get());
-
-        switch (section) {
-#define WASM_SECTION_PARSE(NAME, ID, DESCRIPTION)                   \
-        case Section::NAME: {                                       \
-            WASM_FAIL_IF_HELPER_FAILS(parser.parse ## NAME());             \
-            break;                                                  \
-        }
-        FOR_EACH_KNOWN_WASM_SECTION(WASM_SECTION_PARSE)
-#undef WASM_SECTION_PARSE
-
-        case Section::Custom: {
-            WASM_FAIL_IF_HELPER_FAILS(parser.parseCustom());
-            break;
-        }
-
-        case Section::Begin: {
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
-        }
-
-        WASM_PARSER_FAIL_IF(parser.length() != parser.offset(), "parsing ended before the end of ", section, " section");
-
-        m_offset += sectionLength;
-
-
-        if (isKnownSection(section))
-            previousKnownSection = section;
-    }
-
-    if (UNLIKELY(Options::useEagerWebAssemblyModuleHashing())) {
-        SHA1 hasher;
-        hasher.addBytes(source(), length());
-        m_info->nameSection->setHash(hasher.computeHexDigest());
-    }
-
-    return { };
-}
-
-} } // namespace JSC::Wasm
-
-#endif // ENABLE(WEBASSEMBLY)
diff --git a/Source/JavaScriptCore/wasm/WasmModuleParser.h b/Source/JavaScriptCore/wasm/WasmModuleParser.h
deleted file mode 100644 (file)
index b39e4b3..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#pragma once
-
-#if ENABLE(WEBASSEMBLY)
-
-#include "WasmFormat.h"
-#include "WasmOps.h"
-#include "WasmParser.h"
-
-namespace JSC { namespace Wasm {
-
-class ModuleParser : public Parser<void> {
-public:
-    ModuleParser(const uint8_t* sourceBuffer, size_t sourceLength, ModuleInformation& info)
-        : Parser(sourceBuffer, sourceLength)
-        , m_info(info)
-    {
-    }
-
-    Result WARN_UNUSED_RETURN parse();
-
-private:
-    Ref<ModuleInformation> m_info;
-};
-
-} } // namespace JSC::Wasm
-
-#endif // ENABLE(WEBASSEMBLY)
index 8671242..a0bb6cf 100644 (file)
@@ -79,12 +79,12 @@ void OMGForOSREntryPlan::work(CompilationEffort)
 
     SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[m_functionIndex];
     const Signature& signature = SignatureInformation::get(signatureIndex);
-    ASSERT(validateFunction(function.data.data(), function.data.size(), signature, m_moduleInformation.get()));
+    ASSERT(validateFunction(function, signature, m_moduleInformation.get()));
 
     Vector<UnlinkedWasmToWasmCall> unlinkedCalls;
     CompilationContext context;
     unsigned osrEntryScratchBufferSize = 0;
-    auto parseAndCompileResult = parseAndCompile(context, function.data.data(), function.data.size(), signature, unlinkedCalls, osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::OMGForOSREntryMode, m_functionIndex, m_loopIndex);
+    auto parseAndCompileResult = parseAndCompile(context, function, signature, unlinkedCalls, osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::OMGForOSREntryMode, m_functionIndex, m_loopIndex);
 
     if (UNLIKELY(!parseAndCompileResult)) {
         fail(holdLock(m_lock), makeString(parseAndCompileResult.error(), "when trying to tier up ", String::number(m_functionIndex)));
index e5613ee..a805d01 100644 (file)
@@ -77,12 +77,12 @@ void OMGPlan::work(CompilationEffort)
 
     SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[m_functionIndex];
     const Signature& signature = SignatureInformation::get(signatureIndex);
-    ASSERT(validateFunction(function.data.data(), function.data.size(), signature, m_moduleInformation.get()));
+    ASSERT(validateFunction(function, signature, m_moduleInformation.get()));
 
     Vector<UnlinkedWasmToWasmCall> unlinkedCalls;
     unsigned osrEntryScratchBufferSize;
     CompilationContext context;
-    auto parseAndCompileResult = parseAndCompile(context, function.data.data(), function.data.size(), signature, unlinkedCalls, osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::OMGMode, m_functionIndex, UINT32_MAX);
+    auto parseAndCompileResult = parseAndCompile(context, function, signature, unlinkedCalls, osrEntryScratchBufferSize, m_moduleInformation.get(), m_mode, CompilationMode::OMGMode, m_functionIndex, UINT32_MAX);
 
     if (UNLIKELY(!parseAndCompileResult)) {
         fail(holdLock(m_lock), makeString(parseAndCompileResult.error(), "when trying to tier up ", String::number(m_functionIndex)));
index 9974ecf..e65f707 100644 (file)
@@ -35,7 +35,6 @@
 #include "WasmCallingConvention.h"
 #include "WasmFaultSignalHandler.h"
 #include "WasmMemory.h"
-#include "WasmModuleParser.h"
 #include "WasmValidate.h"
 #include <wtf/DataLog.h>
 #include <wtf/Locker.h>
@@ -131,6 +130,9 @@ bool Plan::tryRemoveContextAndCancelIfLast(Context& context)
 
 void Plan::fail(const AbstractLocker& locker, String&& errorMessage)
 {
+    ASSERT(errorMessage);
+    if (failed())
+        return;
     dataLogLnIf(WasmPlanInternal::verbose, "failing with message: ", errorMessage);
     m_errorMessage = WTFMove(errorMessage);
     complete(locker);
index d577947..9881f9a 100644 (file)
@@ -411,30 +411,10 @@ auto SectionParser::parseElement() -> PartialResult
     return { };
 }
 
-// This function will be changed to be RELEASE_ASSERT_NOT_REACHED once we switch our parsing infrastructure to the streaming parser.
 auto SectionParser::parseCode() -> PartialResult
 {
-    m_info->codeSectionSize = length();
-    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_info->functions.size(), "Code section count ", count, " exceeds the declared number of functions ", m_info->functions.size());
-
-    for (uint32_t i = 0; i < count; ++i) {
-        uint32_t functionSize;
-        WASM_PARSER_FAIL_IF(!parseVarUInt32(functionSize), "can't get ", i, "th Code function's size");
-        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);
-        WASM_PARSER_FAIL_IF(functionSize > maxFunctionSize, "Code function's size ", functionSize, " is too big");
-
-        Vector<uint8_t> data(functionSize);
-        std::memcpy(data.data(), source() + m_offset, functionSize);
-        m_info->functions[i].start = m_offsetInSource + m_offset;
-        m_info->functions[i].end = m_offsetInSource + m_offset + functionSize;
-        m_info->functions[i].data = WTFMove(data);
-        m_offset += functionSize;
-    }
-
+    // The Code section is handled specially in StreamingParser.
+    RELEASE_ASSERT_NOT_REACHED();
     return { };
 }
 
index c546923..ddbf6db 100644 (file)
@@ -28,7 +28,6 @@
 
 #if ENABLE(WEBASSEMBLY)
 
-#include "WasmModuleParser.h"
 #include "WasmSectionParser.h"
 #include <wtf/Optional.h>
 #include <wtf/UnalignedAccess.h>
@@ -67,8 +66,9 @@ NEVER_INLINE auto WARN_UNUSED_RETURN StreamingParser::fail(Args... args) -> Stat
     return State::FatalError;
 }
 
-StreamingParser::StreamingParser(ModuleInformation& info)
+StreamingParser::StreamingParser(ModuleInformation& info, StreamingParserClient& client)
     : m_info(info)
+    , m_client(client)
 {
     dataLogLnIf(WasmStreamingParserInternal::verbose, "starting validation");
 }
@@ -120,6 +120,7 @@ auto StreamingParser::parseCodeSectionSize(uint32_t functionCount) -> State
 
     if (m_functionIndex == m_functionCount) {
         WASM_PARSER_FAIL_IF((m_codeOffset + m_sectionLength) != m_nextOffset, "parsing ended before the end of ", m_section, " section");
+        m_client.didReceiveSectionData(m_section);
         return State::SectionID;
     }
     return State::FunctionSize;
@@ -139,9 +140,12 @@ auto StreamingParser::parseFunctionPayload(Vector<uint8_t>&& data) -> State
     function.end = m_offset + m_functionSize;
     function.data = WTFMove(data);
     dataLogLnIf(WasmStreamingParserInternal::verbose, "Processing function starting at: ", function.start, " and ending at: ", function.end);
+    m_client.didReceiveFunctionData(m_functionIndex, function);
     ++m_functionIndex;
+
     if (m_functionIndex == m_functionCount) {
         WASM_PARSER_FAIL_IF((m_codeOffset + m_sectionLength) != (m_offset + m_functionSize), "parsing ended before the end of ", m_section, " section");
+        m_client.didReceiveSectionData(m_section);
         return State::SectionID;
     }
     return State::FunctionSize;
@@ -172,6 +176,7 @@ auto StreamingParser::parseSectionPayload(Vector<uint8_t>&& data) -> State
 
     WASM_PARSER_FAIL_IF(parser.length() != parser.offset(), "parsing ended before the end of ", m_section, " section");
 
+    m_client.didReceiveSectionData(m_section);
     return State::SectionID;
 }
 
@@ -382,6 +387,7 @@ auto StreamingParser::finalize() -> State
             if (UNLIKELY(Options::useEagerWebAssemblyModuleHashing()))
                 m_info->nameSection->setHash(m_hasher.computeHexDigest());
             m_state = State::Finished;
+            m_client.didFinishParsing();
         } else
             m_state = failOnState(State::SectionID);
         break;
index 7b6b637..d5dd3f2 100644 (file)
 namespace JSC { namespace Wasm {
 
 class StreamingParserClient {
+public:
+    virtual ~StreamingParserClient() = default;
+    virtual void didReceiveSectionData(Section) { }
+    virtual void didReceiveFunctionData(unsigned, const FunctionData&) { }
+    virtual void didFinishParsing() { }
 };
 
 class StreamingParser {
@@ -67,7 +72,7 @@ public:
 
     enum class IsEndOfStream { Yes, No };
 
-    StreamingParser(ModuleInformation&);
+    StreamingParser(ModuleInformation&, StreamingParserClient&);
 
     State addBytes(const uint8_t* bytes, size_t length) { return addBytes(bytes, length, IsEndOfStream::No); }
     State finalize();
@@ -97,6 +102,7 @@ private:
     State failOnState(State);
 
     Ref<ModuleInformation> m_info;
+    StreamingParserClient& m_client;
     Vector<uint8_t> m_remaining;
     String m_errorMessage;
 
index 2e8e0a0..62e8c21 100644 (file)
@@ -461,10 +461,10 @@ void Validate::dump(const Vector<ControlEntry>& controlStack, const Stack* expre
     dataLogLn();
 }
 
-Expected<void, String> validateFunction(const uint8_t* source, size_t length, const Signature& signature, const ModuleInformation& module)
+Expected<void, String> validateFunction(const FunctionData& function, const Signature& signature, const ModuleInformation& module)
 {
     Validate context(module);
-    FunctionParser<Validate> validator(context, source, length, signature, module);
+    FunctionParser<Validate> validator(context, function.data.data(), function.data.size(), signature, module);
     WASM_FAIL_IF_HELPER_FAILS(validator.parse());
     return { };
 }
index 28283cf..a952aac 100644 (file)
@@ -34,7 +34,7 @@ namespace JSC {
 
 namespace Wasm {
 
-Expected<void, String> validateFunction(const uint8_t*, size_t, const Signature&, const ModuleInformation&);
+Expected<void, String> validateFunction(const FunctionData&, const Signature&, const ModuleInformation&);
 
 } } // namespace JSC::Wasm