void Plan::run() { if (verbose) dataLogLn("Starting plan."); { ModuleParser moduleParser(m_source, m_sourceLength); if (!moduleParser.parse()) { if (verbose) dataLogLn("Parsing module failed: ", moduleParser.errorMessage()); m_errorMessage = moduleParser.errorMessage(); return; } m_moduleInformation = WTFMove(moduleParser.moduleInformation()); } if (verbose) dataLogLn("Parsed module."); if (!m_compiledFunctions.tryReserveCapacity(m_moduleInformation->functions.size())) { StringBuilder builder; builder.appendLiteral("Failed allocating enough space for "); builder.appendNumber(m_moduleInformation->functions.size()); builder.appendLiteral(" compiled functions"); m_errorMessage = builder.toString(); return; } for (const FunctionInformation& info : m_moduleInformation->functions) { if (verbose) dataLogLn("Processing function starting at: ", info.start, " and ending at: ", info.end); const uint8_t* functionStart = m_source + info.start; size_t functionLength = info.end - info.start; ASSERT(functionLength <= m_sourceLength); String error = validateFunction(functionStart, functionLength, info.signature, m_moduleInformation->functions); if (!error.isNull()) { if (verbose) { for (unsigned i = 0; i < functionLength; ++i) dataLog(RawPointer(reinterpret_cast<void*>(functionStart[i])), ", "); dataLogLn(); } m_errorMessage = error; return; } m_compiledFunctions.uncheckedAppend(parseAndCompile(*m_vm, functionStart, functionLength, m_moduleInformation->memory.get(), info.signature, m_moduleInformation->functions)); } // Patch the call sites for each function. for (std::unique_ptr<FunctionCompilation>& functionPtr : m_compiledFunctions) { FunctionCompilation* function = functionPtr.get(); for (auto& call : function->unlinkedCalls) MacroAssembler::repatchCall(call.callLocation, CodeLocationLabel(m_compiledFunctions[call.functionIndex]->code->code())); } m_failed = false; }
bool Plan::parseAndValidateModule() { MonotonicTime startTime; if (verbose || Options::reportCompileTimes()) startTime = MonotonicTime::now(); { ModuleParser moduleParser(m_vm, m_source, m_sourceLength); auto parseResult = moduleParser.parse(); if (!parseResult) { m_errorMessage = 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) { 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); auto validationResult = validateFunction(m_vm, functionStart, functionLength, signature, *m_moduleInformation, m_moduleSignatureIndicesToUniquedSignatureIndices); if (!validationResult) { if (verbose) { for (unsigned i = 0; i < functionLength; ++i) dataLog(RawPointer(reinterpret_cast<void*>(functionStart[i])), ", "); dataLogLn(); } m_errorMessage = makeString(validationResult.error(), ", in function at index ", String::number(functionIndex)); // FIXME make this an Expected. return false; } } if (verbose || Options::reportCompileTimes()) dataLogLn("Took ", (MonotonicTime::now() - startTime).microseconds(), " us to validate module"); return true; }
JSWASMModule* parseWebAssembly(ExecState* exec, const SourceCode& source, JSObject* imports, JSArrayBuffer* arrayBuffer, String& errorMessage) { WASMModuleParser moduleParser(exec->vm(), exec->lexicalGlobalObject(), source, imports, arrayBuffer); return moduleParser.parse(exec, errorMessage); }