Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (210046 => 210047)
--- trunk/Source/_javascript_Core/ChangeLog 2016-12-21 00:15:53 UTC (rev 210046)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-12-21 00:29:36 UTC (rev 210047)
@@ -1,3 +1,32 @@
+2016-12-20 Saam Barati <sbar...@apple.com>
+
+ WebAssembly: We should compile wasm functions in parallel
+ https://bugs.webkit.org/show_bug.cgi?id=165993
+
+ Reviewed by Keith Miller.
+
+ This patch adds a very simple parallel compiler for Wasm code.
+ This patch speeds up compiling the Unity headless benchmark by
+ slightly more than 4x on my MBP. To make this safe, I perform
+ all linking on the main thread. I also had to change some code
+ inside Wasmb3IRGenerator to be thread safe.
+
+ * b3/air/AirCustom.h:
+ (JSC::B3::Air::WasmBoundsCheckCustom::generate):
+ * b3/air/AirGenerationContext.h:
+ * wasm/WasmB3IRGenerator.cpp:
+ (JSC::Wasm::B3IRGenerator::B3IRGenerator):
+ (JSC::Wasm::B3IRGenerator::emitExceptionCheck):
+ (JSC::Wasm::createJSToWasmWrapper):
+ (JSC::Wasm::parseAndCompile):
+ * wasm/WasmB3IRGenerator.h:
+ * wasm/WasmCallingConvention.h:
+ (JSC::Wasm::CallingConvention::setupFrameInPrologue):
+ * wasm/WasmPlan.cpp:
+ (JSC::Wasm::Plan::parseAndValidateModule):
+ (JSC::Wasm::Plan::run):
+ * wasm/WasmPlan.h:
+
2016-12-20 Brent Fulgham <bfulg...@apple.com>
Address some style problems found by static analysis
Modified: trunk/Source/_javascript_Core/b3/air/AirCustom.h (210046 => 210047)
--- trunk/Source/_javascript_Core/b3/air/AirCustom.h 2016-12-21 00:15:53 UTC (rev 210046)
+++ trunk/Source/_javascript_Core/b3/air/AirCustom.h 2016-12-21 00:29:36 UTC (rev 210047)
@@ -313,7 +313,7 @@
CCallHelpers::Jump outOfBounds = Inst(Air::Branch64, value, Arg::relCond(CCallHelpers::AboveOrEqual), inst.args[0], inst.args[1]).generate(jit, context);
context.latePaths.append(createSharedTask<GenerationContext::LatePathFunction>(
- [=] (CCallHelpers& jit, Air::GenerationContext&) {
+ [outOfBounds, value] (CCallHelpers& jit, Air::GenerationContext& context) {
outOfBounds.link(&jit);
context.code->wasmBoundsCheckGenerator()->run(jit, value->pinnedGPR(), value->offset());
}));
Modified: trunk/Source/_javascript_Core/b3/air/AirGenerationContext.h (210046 => 210047)
--- trunk/Source/_javascript_Core/b3/air/AirGenerationContext.h 2016-12-21 00:15:53 UTC (rev 210046)
+++ trunk/Source/_javascript_Core/b3/air/AirGenerationContext.h 2016-12-21 00:29:36 UTC (rev 210047)
@@ -39,6 +39,11 @@
class Code;
struct GenerationContext {
+ WTF_MAKE_NONCOPYABLE(GenerationContext);
+public:
+
+ GenerationContext() = default;
+
typedef void LatePathFunction(CCallHelpers&, GenerationContext&);
typedef SharedTask<LatePathFunction> LatePath;
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp (210046 => 210047)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2016-12-21 00:15:53 UTC (rev 210046)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.cpp 2016-12-21 00:29:36 UTC (rev 210047)
@@ -257,12 +257,6 @@
ASSERT_UNUSED(pinnedGPR, m_memorySizeGPR == pinnedGPR);
this->emitExceptionCheck(jit, ExceptionType::OutOfBoundsMemoryAccess);
});
-
- B3::PatchpointValue* foo = m_currentBlock->appendNew<B3::PatchpointValue>(m_proc, B3::Void, Origin());
- foo->setGenerator(
- [=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
- AllowMacroScratchRegisterUsage allowScratch(jit);
- });
}
wasmCallingConvention().setupFrameInPrologue(&compilation->wasmCalleeMoveLocation, m_proc, Origin(), m_currentBlock);
@@ -277,7 +271,7 @@
auto jumpToExceptionStub = jit.jump();
VM* vm = &m_vm;
- jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
+ jit.addLinkTask([vm, jumpToExceptionStub] (LinkBuffer& linkBuffer) {
linkBuffer.link(jumpToExceptionStub, CodeLocationLabel(vm->getCTIStub(throwExceptionFromWasmThunkGenerator).code()));
});
}
@@ -691,13 +685,14 @@
patchpoint->effects.writesPinned = true;
patchpoint->effects.readsPinned = true;
- patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+ Vector<UnlinkedWasmToWasmCall>* unlinkedWasmToWasmCalls = &m_unlinkedWasmToWasmCalls;
+ patchpoint->setGenerator([unlinkedWasmToWasmCalls, functionIndex] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
AllowMacroScratchRegisterUsage allowScratch(jit);
CCallHelpers::Call call = jit.call();
- jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
- m_unlinkedWasmToWasmCalls.append({ linkBuffer.locationOf(call), functionIndex });
+ jit.addLinkTask([unlinkedWasmToWasmCalls, call, functionIndex] (LinkBuffer& linkBuffer) {
+ unlinkedWasmToWasmCalls->append({ linkBuffer.locationOf(call), functionIndex });
});
});
});
@@ -819,7 +814,7 @@
dataLogLn("\n");
}
-static std::unique_ptr<B3::Compilation> createJSToWasmWrapper(VM& vm, WasmInternalFunction& function, const Signature* signature, MacroAssemblerCodePtr mainFunction, const MemoryInformation& memory)
+static void createJSToWasmWrapper(VM& vm, CompilationContext& compilationContext, WasmInternalFunction& function, const Signature* signature, const MemoryInformation& memory)
{
Procedure proc;
BasicBlock* block = proc.addBlock();
@@ -876,13 +871,12 @@
patchpoint->append(ConstrainedValue(sizes[i], ValueRep::reg(memory.pinnedRegisters().sizeRegisters[i].sizeRegister)));
}
- patchpoint->setGenerator([=] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
+ CompilationContext* context = &compilationContext;
+ patchpoint->setGenerator([context] (CCallHelpers& jit, const B3::StackmapGenerationParams&) {
AllowMacroScratchRegisterUsage allowScratch(jit);
CCallHelpers::Call call = jit.call();
- jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
- linkBuffer.link(call, FunctionPtr(mainFunction.executableAddress()));
- });
+ context->jsEntrypointToWasmEntrypointCall = call;
});
});
@@ -904,15 +898,19 @@
RELEASE_ASSERT_NOT_REACHED();
}
- auto jsEntrypoint = std::make_unique<Compilation>(B3::compile(vm, proc));
+ B3::prepareForGeneration(proc);
+ B3::generate(proc, *compilationContext.jsEntrypointJIT);
+ compilationContext.jsEntrypointByproducts = proc.releaseByproducts();
function.jsToWasmEntrypoint.calleeSaveRegisters = proc.calleeSaveRegisters();
- return jsEntrypoint;
}
-Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(VM& vm, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& info, unsigned optLevel)
+Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(VM& vm, CompilationContext& compilationContext, const uint8_t* functionStart, size_t functionLength, const Signature* signature, Vector<UnlinkedWasmToWasmCall>& unlinkedWasmToWasmCalls, const ImmutableFunctionIndexSpace& functionIndexSpace, const ModuleInformation& info, unsigned optLevel)
{
auto result = std::make_unique<WasmInternalFunction>();
+ compilationContext.jsEntrypointJIT = std::make_unique<CCallHelpers>(&vm);
+ compilationContext.wasmEntrypointJIT = std::make_unique<CCallHelpers>(&vm);
+
Procedure procedure;
B3IRGenerator context(vm, info, procedure, result.get(), unlinkedWasmToWasmCalls, functionIndexSpace);
FunctionParser<B3IRGenerator> parser(&vm, context, functionStart, functionLength, signature, functionIndexSpace, info);
@@ -927,10 +925,14 @@
if (verbose)
dataLog("Post SSA: ", procedure);
- result->wasmEntrypoint.compilation = std::make_unique<B3::Compilation>(B3::compile(vm, procedure, optLevel));
- result->wasmEntrypoint.calleeSaveRegisters = procedure.calleeSaveRegisters();
+ {
+ B3::prepareForGeneration(procedure, optLevel);
+ B3::generate(procedure, *compilationContext.wasmEntrypointJIT);
+ compilationContext.wasmEntrypointByproducts = procedure.releaseByproducts();
+ result->wasmEntrypoint.calleeSaveRegisters = procedure.calleeSaveRegisters();
+ }
- result->jsToWasmEntrypoint.compilation = createJSToWasmWrapper(vm, *result, signature, result->wasmEntrypoint.compilation->code(), info.memory);
+ createJSToWasmWrapper(vm, compilationContext, *result, signature, info.memory);
return WTFMove(result);
}
Modified: trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.h (210046 => 210047)
--- trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.h 2016-12-21 00:15:53 UTC (rev 210046)
+++ trunk/Source/_javascript_Core/wasm/WasmB3IRGenerator.h 2016-12-21 00:29:36 UTC (rev 210047)
@@ -28,6 +28,7 @@
#if ENABLE(WEBASSEMBLY)
#include "B3Compilation.h"
+#include "CCallHelpers.h"
#include "VM.h"
#include "WasmFormat.h"
#include <wtf/Expected.h>
@@ -38,8 +39,16 @@
class MemoryInformation;
-Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(VM&, const uint8_t*, size_t, const Signature*, Vector<UnlinkedWasmToWasmCall>&, const ImmutableFunctionIndexSpace&, const ModuleInformation&, unsigned optLevel = 1);
+struct CompilationContext {
+ std::unique_ptr<CCallHelpers> jsEntrypointJIT;
+ std::unique_ptr<B3::OpaqueByproducts> jsEntrypointByproducts;
+ std::unique_ptr<CCallHelpers> wasmEntrypointJIT;
+ std::unique_ptr<B3::OpaqueByproducts> wasmEntrypointByproducts;
+ CCallHelpers::Call jsEntrypointToWasmEntrypointCall;
+};
+Expected<std::unique_ptr<WasmInternalFunction>, String> parseAndCompile(VM&, CompilationContext&, const uint8_t*, size_t, const Signature*, Vector<UnlinkedWasmToWasmCall>&, const ImmutableFunctionIndexSpace&, const ModuleInformation&, unsigned optLevel = 1);
+
} } // namespace JSC::Wasm
#endif // ENABLE(WEBASSEMBLY)
Modified: trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h (210046 => 210047)
--- trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h 2016-12-21 00:15:53 UTC (rev 210046)
+++ trunk/Source/_javascript_Core/wasm/WasmCallingConvention.h 2016-12-21 00:29:36 UTC (rev 210047)
@@ -95,7 +95,7 @@
[=] (CCallHelpers& jit, const B3::StackmapGenerationParams& params) {
GPRReg result = params[0].gpr();
MacroAssembler::DataLabelPtr moveLocation = jit.moveWithPatch(MacroAssembler::TrustedImmPtr(nullptr), result);
- jit.addLinkTask([=] (LinkBuffer& linkBuffer) {
+ jit.addLinkTask([calleeMoveLocation, moveLocation] (LinkBuffer& linkBuffer) {
*calleeMoveLocation = linkBuffer.locationOf(moveLocation);
});
});
Modified: trunk/Source/_javascript_Core/wasm/WasmPlan.cpp (210046 => 210047)
--- trunk/Source/_javascript_Core/wasm/WasmPlan.cpp 2016-12-21 00:15:53 UTC (rev 210046)
+++ trunk/Source/_javascript_Core/wasm/WasmPlan.cpp 2016-12-21 00:29:36 UTC (rev 210047)
@@ -39,6 +39,9 @@
#include "WasmModuleParser.h"
#include "WasmValidate.h"
#include <wtf/DataLog.h>
+#include <wtf/Locker.h>
+#include <wtf/MonotonicTime.h>
+#include <wtf/NumberOfCores.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/StringBuilder.h>
@@ -60,6 +63,10 @@
bool Plan::parseAndValidateModule()
{
+ MonotonicTime startTime;
+ if (verbose || Options::reportCompileTimes())
+ startTime = MonotonicTime::now();
+
{
ModuleParser moduleParser(m_vm, m_source, m_sourceLength);
auto parseResult = moduleParser.parse();
@@ -78,7 +85,7 @@
dataLogLn("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;
- ASSERT(Checked<uintptr_t>(bitwise_cast<uintptr_t>(functionStart)) + functionLength <= Checked<uintptr_t>(bitwise_cast<uintptr_t>(m_source)) + m_sourceLength);
+ ASSERT(functionLength <= m_sourceLength);
SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex];
const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
@@ -94,9 +101,15 @@
}
}
+ if (verbose || Options::reportCompileTimes())
+ dataLogLn("Took ", (MonotonicTime::now() - startTime).microseconds(), " us to validate module");
return true;
}
+// We are creating a bunch of threads that touch the main thread's stack. This will make ASAN unhappy.
+// The reason this is OK is that we guarantee that the main thread doesn't continue until all threads
+// that could touch its stack are done executing.
+SUPPRESS_ASAN
void Plan::run()
{
if (!parseAndValidateModule())
@@ -114,12 +127,16 @@
return true;
};
- Vector<Vector<UnlinkedWasmToWasmCall>> unlinkedWasmToWasmCalls;
if (!tryReserveCapacity(m_wasmToJSStubs, m_moduleInformation->importFunctionSignatureIndices.size(), " WebAssembly to _javascript_ stubs")
- || !tryReserveCapacity(unlinkedWasmToWasmCalls, m_functionLocationInBinary.size(), " unlinked WebAssembly to WebAssembly calls")
- || !tryReserveCapacity(m_wasmInternalFunctions, m_functionLocationInBinary.size(), " WebAssembly functions"))
+ || !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"))
return;
+ m_unlinkedWasmToWasmCalls.resize(m_functionLocationInBinary.size());
+ m_wasmInternalFunctions.resize(m_functionLocationInBinary.size());
+ m_compilationContexts.resize(m_functionLocationInBinary.size());
+
for (unsigned importIndex = 0; importIndex < m_moduleInformation->imports.size(); ++importIndex) {
Import* import = &m_moduleInformation->imports[importIndex];
if (import->kind != ExternalKind::Function)
@@ -132,31 +149,92 @@
m_functionIndexSpace.buffer.get()[importFunctionIndex].code = m_wasmToJSStubs[importFunctionIndex].code().executableAddress();
}
- for (unsigned functionIndex = 0; functionIndex < m_functionLocationInBinary.size(); ++functionIndex) {
- if (verbose)
- dataLogLn("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;
- ASSERT(functionLength <= m_sourceLength);
- SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex];
- const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
- unsigned functionIndexSpace = m_wasmToJSStubs.size() + functionIndex;
- ASSERT(m_functionIndexSpace.buffer.get()[functionIndexSpace].signatureIndex == signatureIndex);
+ m_currentIndex = 0;
- ASSERT(validateFunction(m_vm, functionStart, functionLength, signature, m_functionIndexSpace, *m_moduleInformation));
+ auto doWork = [this] {
+ while (true) {
+ uint32_t functionIndex;
+ {
+ auto locker = holdLock(m_lock);
+ if (m_currentIndex >= m_functionLocationInBinary.size())
+ return;
+ functionIndex = m_currentIndex;
+ ++m_currentIndex;
+ }
- unlinkedWasmToWasmCalls.uncheckedAppend(Vector<UnlinkedWasmToWasmCall>());
- auto parseAndCompileResult = parseAndCompile(*m_vm, functionStart, functionLength, signature, unlinkedWasmToWasmCalls.at(functionIndex), m_functionIndexSpace, *m_moduleInformation);
- if (UNLIKELY(!parseAndCompileResult)) {
- m_errorMessage = parseAndCompileResult.error();
- return; // FIXME make this an Expected.
+ const uint8_t* functionStart = m_source + m_functionLocationInBinary[functionIndex].start;
+ size_t functionLength = m_functionLocationInBinary[functionIndex].end - m_functionLocationInBinary[functionIndex].start;
+ ASSERT(functionLength <= m_sourceLength);
+ SignatureIndex signatureIndex = m_moduleInformation->internalFunctionSignatureIndices[functionIndex];
+ const Signature* signature = SignatureInformation::get(m_vm, signatureIndex);
+ unsigned functionIndexSpace = m_wasmToJSStubs.size() + functionIndex;
+ ASSERT_UNUSED(functionIndexSpace, m_functionIndexSpace.buffer.get()[functionIndexSpace].signatureIndex == signatureIndex);
+ ASSERT(validateFunction(m_vm, functionStart, functionLength, signature, m_functionIndexSpace, *m_moduleInformation));
+
+ m_unlinkedWasmToWasmCalls[functionIndex] = Vector<UnlinkedWasmToWasmCall>();
+ auto parseAndCompileResult = parseAndCompile(*m_vm, m_compilationContexts[functionIndex], functionStart, functionLength, signature, m_unlinkedWasmToWasmCalls[functionIndex], m_functionIndexSpace, *m_moduleInformation);
+
+ if (UNLIKELY(!parseAndCompileResult)) {
+ auto locker = holdLock(m_lock);
+ if (!m_errorMessage) {
+ // Multiple compiles could fail simultaneously. We arbitrarily choose the first.
+ m_errorMessage = parseAndCompileResult.error(); // FIXME make this an Expected.
+ }
+ m_currentIndex = m_functionLocationInBinary.size();
+
+ // We will terminate on the next execution.
+ continue;
+ }
+
+ m_wasmInternalFunctions[functionIndex] = WTFMove(*parseAndCompileResult);
}
- m_wasmInternalFunctions.uncheckedAppend(WTFMove(*parseAndCompileResult));
+ };
+
+ MonotonicTime startTime;
+ if (verbose || Options::reportCompileTimes())
+ startTime = MonotonicTime::now();
+
+ uint32_t threadCount = WTF::numberOfProcessorCores();
+ uint32_t numWorkerThreads = threadCount - 1;
+ Vector<ThreadIdentifier> threads;
+ threads.reserveCapacity(numWorkerThreads);
+ for (uint32_t i = 0; i < numWorkerThreads; i++)
+ threads.uncheckedAppend(createThread("jsc.wasm-b3-compilation.thread", doWork));
+
+ doWork(); // Let the main thread do some work too.
+
+ for (uint32_t i = 0; i < numWorkerThreads; i++)
+ waitForThreadCompletion(threads[i]);
+
+ for (uint32_t functionIndex = 0; functionIndex < m_functionLocationInBinary.size(); functionIndex++) {
+ {
+ CompilationContext& context = m_compilationContexts[functionIndex];
+ {
+ LinkBuffer linkBuffer(*m_vm, *context.wasmEntrypointJIT, nullptr);
+ m_wasmInternalFunctions[functionIndex]->wasmEntrypoint.compilation =
+ std::make_unique<B3::Compilation>(FINALIZE_CODE(linkBuffer, ("Wasm function")), WTFMove(context.wasmEntrypointByproducts));
+ }
+
+ {
+ LinkBuffer linkBuffer(*m_vm, *context.jsEntrypointJIT, nullptr);
+ linkBuffer.link(context.jsEntrypointToWasmEntrypointCall, FunctionPtr(m_wasmInternalFunctions[functionIndex]->wasmEntrypoint.compilation->code().executableAddress()));
+
+ m_wasmInternalFunctions[functionIndex]->jsToWasmEntrypoint.compilation =
+ std::make_unique<B3::Compilation>(FINALIZE_CODE(linkBuffer, ("Wasm JS entrypoint")), WTFMove(context.jsEntrypointByproducts));
+ }
+ }
+
+ unsigned functionIndexSpace = m_wasmToJSStubs.size() + functionIndex;
m_functionIndexSpace.buffer.get()[functionIndexSpace].code = m_wasmInternalFunctions[functionIndex]->wasmEntrypoint.compilation->code().executableAddress();
}
+ if (verbose || Options::reportCompileTimes()) {
+ dataLogLn("Took ", (MonotonicTime::now() - startTime).microseconds(),
+ " us to compile and link the module");
+ }
+
// Patch the call sites for each WebAssembly function.
- for (auto& unlinked : unlinkedWasmToWasmCalls) {
+ for (auto& unlinked : m_unlinkedWasmToWasmCalls) {
for (auto& call : unlinked)
MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_functionIndexSpace.buffer.get()[call.functionIndex].code));
}
Modified: trunk/Source/_javascript_Core/wasm/WasmPlan.h (210046 => 210047)
--- trunk/Source/_javascript_Core/wasm/WasmPlan.h 2016-12-21 00:15:53 UTC (rev 210046)
+++ trunk/Source/_javascript_Core/wasm/WasmPlan.h 2016-12-21 00:29:36 UTC (rev 210047)
@@ -29,6 +29,7 @@
#include "CompilationResult.h"
#include "VM.h"
+#include "WasmB3IRGenerator.h"
#include "WasmFormat.h"
#include <wtf/Bag.h>
#include <wtf/ThreadSafeRefCounted.h>
@@ -103,13 +104,17 @@
Bag<CallLinkInfo> m_callLinkInfos;
Vector<WasmToJSStub> m_wasmToJSStubs;
Vector<std::unique_ptr<WasmInternalFunction>> m_wasmInternalFunctions;
+ Vector<CompilationContext> m_compilationContexts;
ImmutableFunctionIndexSpace m_functionIndexSpace;
VM* m_vm;
+ Vector<Vector<UnlinkedWasmToWasmCall>> m_unlinkedWasmToWasmCalls;
const uint8_t* m_source;
const size_t m_sourceLength;
bool m_failed { true };
String m_errorMessage;
+ uint32_t m_currentIndex;
+ Lock m_lock;
};
} } // namespace JSC::Wasm