|
@@ -11,7 +11,6 @@
|
|
|
|
|
|
|
|
namespace Js
|
|
namespace Js
|
|
|
{
|
|
{
|
|
|
-
|
|
|
|
|
Var WasmLibrary::WasmLazyTrapCallback(RecyclableObject *callee, CallInfo, ...)
|
|
Var WasmLibrary::WasmLazyTrapCallback(RecyclableObject *callee, CallInfo, ...)
|
|
|
{
|
|
{
|
|
|
WasmScriptFunction* asmFunction = static_cast<WasmScriptFunction*>(callee);
|
|
WasmScriptFunction* asmFunction = static_cast<WasmScriptFunction*>(callee);
|
|
@@ -22,128 +21,73 @@ namespace Js
|
|
|
JavascriptExceptionOperators::Throw(error, scriptContext);
|
|
JavascriptExceptionOperators::Throw(error, scriptContext);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- void WasmLibrary::SetWasmEntryPointToInterpreter(Js::ScriptFunction* func, bool deferParse)
|
|
|
|
|
- {
|
|
|
|
|
- Assert(WasmScriptFunction::Is(func));
|
|
|
|
|
- FunctionEntryPointInfo* entrypointInfo = (FunctionEntryPointInfo*)func->GetEntryPointInfo();
|
|
|
|
|
- entrypointInfo->SetIsAsmJSFunction(true);
|
|
|
|
|
-
|
|
|
|
|
- if (deferParse)
|
|
|
|
|
- {
|
|
|
|
|
- func->SetEntryPoint(WasmLibrary::WasmDeferredParseExternalThunk);
|
|
|
|
|
- entrypointInfo->jsMethod = WasmLibrary::WasmDeferredParseInternalThunk;
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- func->SetEntryPoint(Js::AsmJsExternalEntryPoint);
|
|
|
|
|
- entrypointInfo->jsMethod = AsmJsDefaultEntryThunk;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-#if _M_IX86
|
|
|
|
|
- __declspec(naked)
|
|
|
|
|
- Var WasmLibrary::WasmDeferredParseExternalThunk(RecyclableObject* function, CallInfo callInfo, ...)
|
|
|
|
|
- {
|
|
|
|
|
- __asm
|
|
|
|
|
- {
|
|
|
|
|
- push 0;
|
|
|
|
|
- push [esp + 8];
|
|
|
|
|
- call WasmLibrary::WasmDeferredParseEntryPoint
|
|
|
|
|
-#ifdef _CONTROL_FLOW_GUARD
|
|
|
|
|
- // verify that the call target is valid
|
|
|
|
|
- mov ecx, eax
|
|
|
|
|
- call[__guard_check_icall_fptr]
|
|
|
|
|
- mov eax, ecx
|
|
|
|
|
-#endif
|
|
|
|
|
- // Although we don't restore ESP here on WinCE, this is fine because script profiler is not shipped for WinCE.
|
|
|
|
|
- jmp eax
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- __declspec(naked)
|
|
|
|
|
- Var WasmLibrary::WasmDeferredParseInternalThunk(RecyclableObject* function, CallInfo callInfo, ...)
|
|
|
|
|
|
|
+ void WasmLibrary::ResetFunctionBodyDefaultEntryPoint(FunctionBody* body)
|
|
|
{
|
|
{
|
|
|
- __asm
|
|
|
|
|
- {
|
|
|
|
|
- push 1;
|
|
|
|
|
- push [esp + 8];
|
|
|
|
|
- call WasmLibrary::WasmDeferredParseEntryPoint
|
|
|
|
|
-#ifdef _CONTROL_FLOW_GUARD
|
|
|
|
|
- // verify that the call target is valid
|
|
|
|
|
- mov ecx, eax
|
|
|
|
|
- call[__guard_check_icall_fptr]
|
|
|
|
|
- mov eax, ecx
|
|
|
|
|
-#endif
|
|
|
|
|
- // Although we don't restore ESP here on WinCE, this is fine because script profiler is not shipped for WinCE.
|
|
|
|
|
- jmp eax
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ body->GetDefaultFunctionEntryPointInfo()->SetIsAsmJSFunction(true);
|
|
|
|
|
+ body->GetDefaultFunctionEntryPointInfo()->jsMethod = AsmJsDefaultEntryThunk;
|
|
|
|
|
+ body->SetOriginalEntryPoint(AsmJsDefaultEntryThunk);
|
|
|
|
|
+ // Reset jit status for this function
|
|
|
|
|
+ body->SetIsAsmJsFullJitScheduled(false);
|
|
|
|
|
+ Assert(body->HasValidEntryPoint());
|
|
|
}
|
|
}
|
|
|
-#elif defined(_M_X64)
|
|
|
|
|
- // Do nothing: the implementation of WasmLibrary::WasmDeferredParseExternalThunk is declared (appropriately decorated) in
|
|
|
|
|
- // Language\amd64\amd64_Thunks.asm.
|
|
|
|
|
-#endif // _M_IX86
|
|
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#endif // ENABLE_WASM
|
|
#endif // ENABLE_WASM
|
|
|
|
|
|
|
|
-Js::JavascriptMethod Js::WasmLibrary::WasmDeferredParseEntryPoint(Js::AsmJsScriptFunction* func, int internalCall)
|
|
|
|
|
|
|
+Js::JavascriptMethod Js::WasmLibrary::EnsureWasmEntrypoint(Js::ScriptFunction* func)
|
|
|
{
|
|
{
|
|
|
#ifdef ENABLE_WASM
|
|
#ifdef ENABLE_WASM
|
|
|
- FunctionBody* body = func->GetFunctionBody();
|
|
|
|
|
- AsmJsFunctionInfo* info = body->GetAsmJsFunctionInfo();
|
|
|
|
|
- ScriptContext* scriptContext = func->GetScriptContext();
|
|
|
|
|
-
|
|
|
|
|
- Js::FunctionEntryPointInfo * entrypointInfo = (Js::FunctionEntryPointInfo*)func->GetEntryPointInfo();
|
|
|
|
|
- Wasm::WasmReaderInfo* readerInfo = info->GetWasmReaderInfo();
|
|
|
|
|
- if (readerInfo)
|
|
|
|
|
|
|
+ if (func->GetFunctionBody()->IsWasmFunction())
|
|
|
{
|
|
{
|
|
|
- try
|
|
|
|
|
|
|
+ FunctionBody* body = func->GetFunctionBody();
|
|
|
|
|
+ AsmJsFunctionInfo* info = body->GetAsmJsFunctionInfo();
|
|
|
|
|
+ ScriptContext* scriptContext = func->GetScriptContext();
|
|
|
|
|
+
|
|
|
|
|
+ Js::FunctionEntryPointInfo * entrypointInfo = (Js::FunctionEntryPointInfo*)func->GetEntryPointInfo();
|
|
|
|
|
+ if (info->GetLazyError())
|
|
|
{
|
|
{
|
|
|
- Wasm::WasmBytecodeGenerator::GenerateFunctionBytecode(scriptContext, readerInfo);
|
|
|
|
|
- func->GetDynamicType()->SetEntryPoint(Js::AsmJsExternalEntryPoint);
|
|
|
|
|
- entrypointInfo->jsMethod = AsmJsDefaultEntryThunk;
|
|
|
|
|
- WAsmJs::JitFunctionIfReady(func);
|
|
|
|
|
|
|
+ // We might have parsed this in the past and there was an error
|
|
|
|
|
+ entrypointInfo->jsMethod = WasmLibrary::WasmLazyTrapCallback;
|
|
|
}
|
|
}
|
|
|
- catch (Wasm::WasmCompilationException& ex)
|
|
|
|
|
|
|
+ else if (body->GetByteCodeCount() == 0)
|
|
|
{
|
|
{
|
|
|
- AutoFreeExceptionMessage autoCleanExceptionMessage;
|
|
|
|
|
- char16* exceptionMessage = WebAssemblyModule::FormatExceptionMessage(&ex, &autoCleanExceptionMessage, readerInfo->m_module, body);
|
|
|
|
|
|
|
+ Wasm::WasmReaderInfo* readerInfo = info->GetWasmReaderInfo();
|
|
|
|
|
+ AssertOrFailFast(readerInfo);
|
|
|
|
|
+ try
|
|
|
|
|
+ {
|
|
|
|
|
+ Wasm::WasmBytecodeGenerator::GenerateFunctionBytecode(scriptContext, readerInfo);
|
|
|
|
|
+ entrypointInfo->jsMethod = AsmJsDefaultEntryThunk;
|
|
|
|
|
+ WAsmJs::JitFunctionIfReady(func);
|
|
|
|
|
+ }
|
|
|
|
|
+ catch (Wasm::WasmCompilationException& ex)
|
|
|
|
|
+ {
|
|
|
|
|
+ AutoFreeExceptionMessage autoCleanExceptionMessage;
|
|
|
|
|
+ char16* exceptionMessage = WebAssemblyModule::FormatExceptionMessage(&ex, &autoCleanExceptionMessage, readerInfo->m_module, body);
|
|
|
|
|
|
|
|
- JavascriptLibrary *library = scriptContext->GetLibrary();
|
|
|
|
|
- JavascriptError *pError = library->CreateWebAssemblyCompileError();
|
|
|
|
|
- JavascriptError::SetErrorMessage(pError, WASMERR_WasmCompileError, exceptionMessage, scriptContext);
|
|
|
|
|
|
|
+ JavascriptLibrary *library = scriptContext->GetLibrary();
|
|
|
|
|
+ JavascriptError *pError = library->CreateWebAssemblyCompileError();
|
|
|
|
|
+ JavascriptError::SetErrorMessage(pError, WASMERR_WasmCompileError, exceptionMessage, scriptContext);
|
|
|
|
|
|
|
|
- func->GetDynamicType()->SetEntryPoint(WasmLazyTrapCallback);
|
|
|
|
|
- entrypointInfo->jsMethod = WasmLazyTrapCallback;
|
|
|
|
|
- info->SetLazyError(pError);
|
|
|
|
|
|
|
+ entrypointInfo->jsMethod = WasmLibrary::WasmLazyTrapCallback;
|
|
|
|
|
+ info->SetLazyError(pError);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- info->SetWasmReaderInfo(nullptr);
|
|
|
|
|
- }
|
|
|
|
|
- else
|
|
|
|
|
- {
|
|
|
|
|
- // This can happen if another function had its type changed and then was parsed
|
|
|
|
|
- // They still share the function body, so just change the entry point
|
|
|
|
|
- Assert(body->GetByteCodeCount() > 0);
|
|
|
|
|
- Js::JavascriptMethod externalEntryPoint = info->GetLazyError() ? WasmLazyTrapCallback : Js::AsmJsExternalEntryPoint;
|
|
|
|
|
- func->GetDynamicType()->SetEntryPoint(externalEntryPoint);
|
|
|
|
|
- if (body->GetIsAsmJsFullJitScheduled())
|
|
|
|
|
|
|
+ // The function has already been parsed, just fix up the entry point
|
|
|
|
|
+ else if (body->GetIsAsmJsFullJitScheduled())
|
|
|
{
|
|
{
|
|
|
Js::FunctionEntryPointInfo* defaultEntryPoint = (Js::FunctionEntryPointInfo*)body->GetDefaultEntryPointInfo();
|
|
Js::FunctionEntryPointInfo* defaultEntryPoint = (Js::FunctionEntryPointInfo*)body->GetDefaultEntryPointInfo();
|
|
|
func->ChangeEntryPoint(defaultEntryPoint, defaultEntryPoint->jsMethod);
|
|
func->ChangeEntryPoint(defaultEntryPoint, defaultEntryPoint->jsMethod);
|
|
|
}
|
|
}
|
|
|
- else if (entrypointInfo->jsMethod == WasmLibrary::WasmDeferredParseInternalThunk)
|
|
|
|
|
|
|
+ else
|
|
|
{
|
|
{
|
|
|
- // The entrypointInfo is still shared even if the type has been changed
|
|
|
|
|
- // However, no sibling functions changed this entry point yet, so fix it
|
|
|
|
|
- entrypointInfo->jsMethod = info->GetLazyError() ? WasmLazyTrapCallback : AsmJsDefaultEntryThunk;
|
|
|
|
|
|
|
+ entrypointInfo->jsMethod = AsmJsDefaultEntryThunk;
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
|
|
|
|
|
- Assert(body->HasValidEntryPoint());
|
|
|
|
|
- Js::JavascriptMethod entryPoint = internalCall ? entrypointInfo->jsMethod : func->GetDynamicType()->GetEntryPoint();
|
|
|
|
|
- return entryPoint;
|
|
|
|
|
-#else
|
|
|
|
|
- Js::Throw::InternalError();
|
|
|
|
|
|
|
+ Assert(body->HasValidEntryPoint());
|
|
|
|
|
+ Js::JavascriptMethod jsMethod = func->GetEntryPointInfo()->jsMethod;
|
|
|
|
|
+ // We are already in AsmJsDefaultEntryThunk so return null so it just keeps going
|
|
|
|
|
+ return jsMethod == AsmJsDefaultEntryThunk ? nullptr : jsMethod;
|
|
|
|
|
+ }
|
|
|
#endif
|
|
#endif
|
|
|
|
|
+ return nullptr;
|
|
|
}
|
|
}
|