Skip to content

Commit 26833ef

Browse files
committed
Always use AsmJsDefault entrypoint instead of a wasm deferred parse entry point
1 parent 2353319 commit 26833ef

20 files changed

+183
-389
lines changed

lib/Backend/NativeCodeGenerator.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,8 +1567,7 @@ NativeCodeGenerator::GetCheckCodeGenFunction(Js::JavascriptMethod codeAddress)
15671567
return nullptr;
15681568
}
15691569

1570-
1571-
Js::Var
1570+
Js::JavascriptMethod
15721571
NativeCodeGenerator::CheckAsmJsCodeGen(Js::ScriptFunction * function)
15731572
{
15741573
Assert(function);
@@ -1579,6 +1578,7 @@ NativeCodeGenerator::CheckAsmJsCodeGen(Js::ScriptFunction * function)
15791578
Assert(scriptContext->GetThreadContext()->IsScriptActive());
15801579
Assert(scriptContext->GetThreadContext()->IsInScript());
15811580

1581+
AssertOrFailFastMsg(!functionBody->IsWasmFunction() || functionBody->GetByteCodeCount() > 0, "Wasm function should be parsed by now");
15821582
// Load the entry point here to validate it got changed afterwards
15831583

15841584
Js::FunctionEntryPointInfo* entryPoint = function->GetFunctionEntryPointInfo();
@@ -1595,16 +1595,17 @@ NativeCodeGenerator::CheckAsmJsCodeGen(Js::ScriptFunction * function)
15951595
{
15961596
Output::Print(_u("Codegen not done yet for function: %s, Entrypoint is CheckAsmJsCodeGenThunk\n"), function->GetFunctionBody()->GetDisplayName());
15971597
}
1598-
return reinterpret_cast<Js::Var>(functionBody->GetOriginalEntryPoint());
1598+
return functionBody->GetOriginalEntryPoint();
15991599
}
16001600
if (PHASE_TRACE1(Js::AsmjsEntryPointInfoPhase))
16011601
{
16021602
Output::Print(_u("CodeGen Done for function: %s, Changing Entrypoint to Full JIT\n"), function->GetFunctionBody()->GetDisplayName());
16031603
}
16041604
// we will need to set the functionbody external and asmjs entrypoint to the fulljit entrypoint
1605-
return reinterpret_cast<Js::Var>(CheckCodeGenDone(functionBody, entryPoint, function));
1605+
return CheckCodeGenDone(functionBody, entryPoint, function);
16061606
}
16071607

1608+
16081609
Js::JavascriptMethod
16091610
NativeCodeGenerator::CheckCodeGen(Js::ScriptFunction * function)
16101611
{

lib/Backend/NativeCodeGenerator.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ void SetProfileMode(BOOL fSet);
5959
static bool IsAsmJsCodeGenThunk(Js::JavascriptMethod codeAddress);
6060
static CheckCodeGenFunction GetCheckCodeGenFunction(Js::JavascriptMethod codeAddress);
6161
static Js::JavascriptMethod CheckCodeGen(Js::ScriptFunction * function);
62-
static Js::Var CheckAsmJsCodeGen(Js::ScriptFunction * function);
62+
static Js::JavascriptMethod CheckAsmJsCodeGen(Js::ScriptFunction * function);
6363

6464
public:
6565
static void Jit_TransitionFromSimpleJit(void *const framePointer);

lib/Backend/amd64/Thunks.asm

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ endif
6161
;; NativeCodeGenerator::CheckAsmJsCodeGenThunk
6262
;;============================================================================================================
6363

64-
extrn ?CheckAsmJsCodeGen@NativeCodeGenerator@@SAPEAXPEAVScriptFunction@Js@@@Z : PROC
64+
extrn ?CheckAsmJsCodeGen@NativeCodeGenerator@@SAP6APEAXPEAVRecyclableObject@Js@@UCallInfo@3@ZZPEAVScriptFunction@3@@Z : PROC
6565
align 16
6666
?CheckAsmJsCodeGenThunk@NativeCodeGenerator@@SAPEAXPEAVRecyclableObject@Js@@UCallInfo@3@ZZ PROC FRAME
6767
;; save volatile registers
@@ -83,14 +83,11 @@ align 16
8383
movups xmmword ptr [rsp + 40h], xmm2
8484
movups xmmword ptr [rsp + 50h], xmm3
8585

86+
call ?CheckAsmJsCodeGen@NativeCodeGenerator@@SAP6APEAXPEAVRecyclableObject@Js@@UCallInfo@3@ZZPEAVScriptFunction@3@@Z
8687
ifdef _CONTROL_FLOW_GUARD
87-
call ?CheckAsmJsCodeGen@NativeCodeGenerator@@SAPEAXPEAVScriptFunction@Js@@@Z
88-
8988
mov rcx, rax ; __guard_check_icall_fptr requires the call target in rcx.
9089
call [__guard_check_icall_fptr] ; verify that the call target is valid
9190
mov rax, rcx ; CFG is guaranteed not to mess up rcx
92-
else
93-
call ?CheckAsmJsCodeGen@NativeCodeGenerator@@SAPEAXPEAVScriptFunction@Js@@@Z
9491
endif
9592

9693
;EPILOGUE starts here

lib/Common/BackendApi.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,7 @@
77

88
#if DYNAMIC_INTERPRETER_THUNK
99
#define DefaultEntryThunk Js::InterpreterStackFrame::DelayDynamicInterpreterThunk
10-
#if _M_X64
1110
#define AsmJsDefaultEntryThunk Js::InterpreterStackFrame::AsmJsDelayDynamicInterpreterThunk
12-
#elif _M_IX86
13-
#define AsmJsDefaultEntryThunk Js::InterpreterStackFrame::DelayDynamicInterpreterThunk
14-
#endif
1511
#else
1612
#define DefaultEntryThunk Js::InterpreterStackFrame::InterpreterThunk
1713
#endif

lib/Runtime/Base/CrossSite.cpp

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -357,16 +357,7 @@ namespace Js
357357
#ifdef ENABLE_WASM
358358
if (WasmScriptFunction::Is(function))
359359
{
360-
AsmJsFunctionInfo* asmInfo = funcInfo->GetFunctionBody()->GetAsmJsFunctionInfo();
361-
Assert(asmInfo);
362-
if (asmInfo->IsWasmDeferredParse())
363-
{
364-
entryPoint = WasmLibrary::WasmDeferredParseExternalThunk;
365-
}
366-
else
367-
{
368-
entryPoint = Js::AsmJsExternalEntryPoint;
369-
}
360+
entryPoint = Js::AsmJsExternalEntryPoint;
370361
} else
371362
#endif
372363
if (funcInfo->HasBody())
@@ -414,17 +405,7 @@ namespace Js
414405
if (funcInfo->GetFunctionProxy()->IsFunctionBody() &&
415406
funcInfo->GetFunctionBody()->GetIsAsmJsFunction())
416407
{
417-
#ifdef ENABLE_WASM
418-
AsmJsFunctionInfo* asmInfo = funcInfo->GetFunctionBody()->GetAsmJsFunctionInfo();
419-
if (asmInfo && asmInfo->IsWasmDeferredParse())
420-
{
421-
entryPoint = WasmLibrary::WasmDeferredParseExternalThunk;
422-
}
423-
else
424-
#endif
425-
{
426-
entryPoint = Js::AsmJsExternalEntryPoint;
427-
}
408+
entryPoint = Js::AsmJsExternalEntryPoint;
428409
}
429410
else
430411
#endif

lib/Runtime/Base/FunctionBody.cpp

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3564,23 +3564,33 @@ namespace Js
35643564
JavascriptMethod directEntryPoint = this->GetDefaultEntryPointInfo()->jsMethod;
35653565
JavascriptMethod originalEntryPoint = this->GetOriginalEntryPoint_Unchecked();
35663566

3567+
FunctionBody* body = this->GetFunctionBody();
3568+
Unused(body); // in some configuration
3569+
#ifdef ASMJS_PLAT
3570+
if (body->GetIsAsmJsFunction())
3571+
{
3572+
#ifdef ENABLE_WASM
3573+
if (body->IsWasmFunction() && body->GetByteCodeCount() == 0)
3574+
{
3575+
// The only valid 2 entrypoints if the function hasn't been parsed
3576+
return directEntryPoint == AsmJsDefaultEntryThunk || directEntryPoint == WasmLibrary::WasmLazyTrapCallback;
3577+
}
3578+
#endif
3579+
// Entrypoints valid only for asm.js/wasm
3580+
if (directEntryPoint == AsmJsDefaultEntryThunk || IsAsmJsCodeGenThunk(directEntryPoint))
3581+
{
3582+
return true;
3583+
}
3584+
}
3585+
#endif
35673586
// Check the direct entry point to see if it is codegen thunk
35683587
// if it is not, the background codegen thread has updated both original entry point and direct entry point
35693588
// and they should still match, same as cases other then code gen
35703589
return IsIntermediateCodeGenThunk(directEntryPoint) || originalEntryPoint == directEntryPoint
35713590
#if ENABLE_PROFILE_INFO
3572-
|| (directEntryPoint == DynamicProfileInfo::EnsureDynamicProfileInfoThunk &&
3573-
this->IsFunctionBody() && this->GetFunctionBody()->IsNativeOriginalEntryPoint())
3574-
#ifdef ENABLE_WASM
3575-
|| (GetFunctionBody()->IsWasmFunction() &&
3576-
(directEntryPoint == WasmLibrary::WasmDeferredParseInternalThunk || directEntryPoint == WasmLibrary::WasmLazyTrapCallback))
3591+
|| (directEntryPoint == DynamicProfileInfo::EnsureDynamicProfileInfoThunk && body->IsNativeOriginalEntryPoint())
35773592
#endif
3578-
#ifdef ASMJS_PLAT
3579-
|| (GetFunctionBody()->GetIsAsmJsFunction() && directEntryPoint == AsmJsDefaultEntryThunk)
3580-
|| IsAsmJsCodeGenThunk(directEntryPoint)
3581-
#endif
3582-
#endif
3583-
;
3593+
;
35843594
}
35853595
#if defined(ENABLE_SCRIPT_PROFILING) || defined(ENABLE_SCRIPT_DEBUGGING)
35863596
bool FunctionProxy::HasValidProfileEntryPoint() const
@@ -3695,6 +3705,8 @@ namespace Js
36953705
#if DYNAMIC_INTERPRETER_THUNK
36963706
void FunctionBody::GenerateDynamicInterpreterThunk()
36973707
{
3708+
AssertOrFailFastMsg(!m_isWasmFunction || GetByteCodeCount() > 0, "The wasm function should have been parsed before generating the dynamic interpreter thunk");
3709+
36983710
if (this->m_dynamicInterpreterThunk == nullptr)
36993711
{
37003712
// NOTE: Etw rundown thread may be reading this->dynamicInterpreterThunk concurrently. We don't need to synchronize
@@ -3746,6 +3758,7 @@ namespace Js
37463758
this->EnsureDynamicProfileInfo();
37473759

37483760
Assert(HasValidEntryPoint());
3761+
AssertMsg(!m_isWasmFunction || GetByteCodeCount() > 0, "Wasm function should be parsed by this point");
37493762
if (InterpreterStackFrame::IsDelayDynamicInterpreterThunk(this->GetEntryPoint(entryPointInfo)))
37503763
{
37513764
// We are not doing code gen on this function, just change the entry point directly

lib/Runtime/Base/ScriptContext.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3970,13 +3970,10 @@ namespace Js
39703970
functionBody->ResetEntryPoint();
39713971
CurrentThunk = realThunk;
39723972

3973-
bool isDeferred = functionBody->GetAsmJsFunctionInfo()->IsWasmDeferredParse();
3973+
Js::WasmLibrary::ResetFunctionBodyDefaultEntryPoint(functionBody);
39743974
// Make sure the function and the function body are using the same entry point
3975-
scriptFunction->ChangeEntryPoint(functionBody->GetDefaultEntryPointInfo(), AsmJsDefaultEntryThunk);
3976-
WasmLibrary::SetWasmEntryPointToInterpreter(scriptFunction, isDeferred);
3977-
// Reset jit status for this function
3978-
functionBody->SetIsAsmJsFullJitScheduled(false);
3979-
Assert(functionBody->HasValidEntryPoint());
3975+
scriptFunction->ChangeEntryPoint(functionBody->GetDefaultEntryPointInfo(), functionBody->GetDefaultEntryPointInfo()->jsMethod);
3976+
Assert(scriptFunction->GetFunctionEntryPointInfo()->GetIsAsmJSFunction());
39803977
}
39813978
else
39823979
#endif

lib/Runtime/Language/AsmJsTypes.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -993,10 +993,9 @@ namespace Js
993993
}
994994

995995
Wasm::WasmReaderInfo* GetWasmReaderInfo() const {return mWasmReaderInfo;}
996-
void SetWasmReaderInfo(Wasm::WasmReaderInfo* reader) {mWasmReaderInfo = reader;}
996+
void SetWasmReaderInfo(Wasm::WasmReaderInfo* reader) { Assert(reader); mWasmReaderInfo = reader; }
997997
WebAssemblyModule* GetWebAssemblyModule() const { return mWasmModule; }
998-
void SetWebAssemblyModule(WebAssemblyModule * module) { mWasmModule= module; }
999-
bool IsWasmDeferredParse() const { return mWasmReaderInfo != nullptr; }
998+
void SetWebAssemblyModule(WebAssemblyModule * module) { mWasmModule = module; }
1000999
#endif
10011000
};
10021001
};

lib/Runtime/Language/InterpreterStackFrame.cpp

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,31 +1592,68 @@ namespace Js
15921592
#endif
15931593
#endif
15941594

1595+
15951596
#if DYNAMIC_INTERPRETER_THUNK
15961597
#ifdef _M_IX86
1598+
__declspec(naked)
1599+
Var InterpreterStackFrame::AsmJsDelayDynamicInterpreterThunk(RecyclableObject* function, CallInfo callInfo, ...)
1600+
{
1601+
__asm
1602+
{
1603+
push ebp;
1604+
mov ebp, esp;
1605+
push[esp + 8]; // push function object
1606+
call WasmLibrary::EnsureWasmEntrypoint;
1607+
test eax, eax;
1608+
jne skipThunk;
1609+
1610+
push[esp + 8]; // push function object
1611+
call InterpreterStackFrame::EnsureDynamicInterpreterThunk;
1612+
skipThunk:
1613+
#ifdef _CONTROL_FLOW_GUARD
1614+
// verify that the call target is valid
1615+
push eax;
1616+
mov ecx, eax;
1617+
call[__guard_check_icall_fptr];
1618+
pop eax;
1619+
#endif
1620+
1621+
pop ebp;
1622+
1623+
jmp eax;
1624+
}
1625+
}
1626+
15971627
__declspec(naked)
15981628
Var InterpreterStackFrame::DelayDynamicInterpreterThunk(RecyclableObject* function, CallInfo callInfo, ...)
15991629
{
16001630
__asm
16011631
{
1602-
push ebp
1603-
mov ebp, esp
1604-
push[esp + 8] // push function object
1632+
push ebp;
1633+
mov ebp, esp;
1634+
push[esp + 8]; // push function object
16051635
call InterpreterStackFrame::EnsureDynamicInterpreterThunk;
16061636

16071637
#ifdef _CONTROL_FLOW_GUARD
16081638
// verify that the call target is valid
1609-
push eax
1610-
mov ecx, eax
1611-
call[__guard_check_icall_fptr]
1612-
pop eax
1639+
push eax;
1640+
mov ecx, eax;
1641+
call[__guard_check_icall_fptr];
1642+
pop eax;
16131643
#endif
16141644

1615-
pop ebp
1645+
pop ebp;
16161646

1617-
jmp eax
1647+
jmp eax;
16181648
}
16191649
}
1650+
#elif !defined(_M_AMD64)
1651+
Var InterpreterStackFrame::AsmJsDelayDynamicInterpreterThunk(RecyclableObject* function, CallInfo callInfo, ...)
1652+
{
1653+
// Asm.js only supported on x64 and x86
1654+
AssertOrFailFast(UNREACHED);
1655+
return nullptr;
1656+
}
16201657
#endif
16211658
#endif
16221659

@@ -1645,15 +1682,14 @@ namespace Js
16451682

16461683
bool InterpreterStackFrame::IsDelayDynamicInterpreterThunk(JavascriptMethod entryPoint)
16471684
{
1648-
return
1685+
return false
16491686
#if DYNAMIC_INTERPRETER_THUNK
1650-
#if _M_X64
1651-
entryPoint == InterpreterStackFrame::AsmJsDelayDynamicInterpreterThunk ||
1687+
|| entryPoint == InterpreterStackFrame::DelayDynamicInterpreterThunk
1688+
#ifdef ASMJS_PLAT
1689+
|| entryPoint == InterpreterStackFrame::AsmJsDelayDynamicInterpreterThunk
16521690
#endif
1653-
entryPoint == InterpreterStackFrame::DelayDynamicInterpreterThunk;
1654-
#else
1655-
false;
16561691
#endif
1692+
;
16571693
}
16581694

16591695
#ifdef ENABLE_DEBUG_CONFIG_OPTIONS
@@ -3648,24 +3684,27 @@ namespace Js
36483684
ScriptContext * scriptContext = function->GetScriptContext();
36493685
Js::FunctionEntryPointInfo* entrypointInfo = (Js::FunctionEntryPointInfo*)function->GetEntryPointInfo();
36503686
PROBE_STACK_CALL(scriptContext, function, alignedArgsSize + Js::Constants::MinStackDefault);
3687+
// Calling the jsMethod might change the entrypoint, adding the variable here
3688+
// will save the method on the stack helping debug what really got called
3689+
JavascriptMethod jsMethod = entrypointInfo->jsMethod;
36513690

36523691
switch (asmInfo->GetReturnType().which())
36533692
{
36543693
case AsmJsRetType::Void:
3655-
JavascriptFunction::CallAsmJsFunction<int>(function, entrypointInfo->jsMethod, m_outParams, alignedArgsSize, reg);
3694+
JavascriptFunction::CallAsmJsFunction<int>(function, jsMethod, m_outParams, alignedArgsSize, reg);
36563695
break;
36573696
case AsmJsRetType::Signed:
36583697

3659-
m_localIntSlots[returnReg] = JavascriptFunction::CallAsmJsFunction<int>(function, entrypointInfo->jsMethod, m_outParams, alignedArgsSize, reg);
3698+
m_localIntSlots[returnReg] = JavascriptFunction::CallAsmJsFunction<int>(function, jsMethod, m_outParams, alignedArgsSize, reg);
36603699
break;
36613700
case AsmJsRetType::Int64:
3662-
m_localInt64Slots[returnReg] = JavascriptFunction::CallAsmJsFunction<int64>(function, entrypointInfo->jsMethod, m_outParams, alignedArgsSize, reg);
3701+
m_localInt64Slots[returnReg] = JavascriptFunction::CallAsmJsFunction<int64>(function, jsMethod, m_outParams, alignedArgsSize, reg);
36633702
break;
36643703
case AsmJsRetType::Double:
3665-
m_localDoubleSlots[returnReg] = JavascriptFunction::CallAsmJsFunction<double>(function, entrypointInfo->jsMethod, m_outParams, alignedArgsSize, reg);
3704+
m_localDoubleSlots[returnReg] = JavascriptFunction::CallAsmJsFunction<double>(function, jsMethod, m_outParams, alignedArgsSize, reg);
36663705
break;
36673706
case AsmJsRetType::Float:
3668-
m_localFloatSlots[returnReg] = JavascriptFunction::CallAsmJsFunction<float>(function, entrypointInfo->jsMethod, m_outParams, alignedArgsSize, reg);
3707+
m_localFloatSlots[returnReg] = JavascriptFunction::CallAsmJsFunction<float>(function, jsMethod, m_outParams, alignedArgsSize, reg);
36693708
break;
36703709
#ifdef ENABLE_WASM_SIMD
36713710
case AsmJsRetType::Float32x4:
@@ -3682,10 +3721,10 @@ namespace Js
36823721
#if _WIN32 //WASM.SIMD ToDo: Enable thunk for Xplat
36833722
#if _M_X64
36843723
X86SIMDValue simdVal;
3685-
simdVal.m128_value = JavascriptFunction::CallAsmJsFunction<__m128>(function, entrypointInfo->jsMethod, m_outParams, alignedArgsSize, reg);
3724+
simdVal.m128_value = JavascriptFunction::CallAsmJsFunction<__m128>(function, jsMethod, m_outParams, alignedArgsSize, reg);
36863725
m_localSimdSlots[returnReg] = X86SIMDValue::ToSIMDValue(simdVal);
36873726
#else
3688-
m_localSimdSlots[returnReg] = JavascriptFunction::CallAsmJsFunction<AsmJsSIMDValue>(function, entrypointInfo->jsMethod, m_outParams, alignedArgsSize, reg);
3727+
m_localSimdSlots[returnReg] = JavascriptFunction::CallAsmJsFunction<AsmJsSIMDValue>(function, jsMethod, m_outParams, alignedArgsSize, reg);
36893728
#endif
36903729
#endif
36913730
break;

lib/Runtime/Language/InterpreterStackFrame.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,11 +344,7 @@ namespace Js
344344
template <typename T>
345345
static T AsmJsInterpreter(AsmJsCallStackLayout* layout);
346346
static void * GetAsmJsInterpreterEntryPoint(AsmJsCallStackLayout* stack);
347-
348-
static Var AsmJsDelayDynamicInterpreterThunk(RecyclableObject* function, CallInfo callInfo, ...);
349-
350347
static __m128 AsmJsInterpreterSimdJs(AsmJsCallStackLayout* func);
351-
352348
#endif
353349

354350
#ifdef ASMJS_PLAT
@@ -357,6 +353,7 @@ namespace Js
357353
#endif
358354

359355
#if DYNAMIC_INTERPRETER_THUNK
356+
static Var AsmJsDelayDynamicInterpreterThunk(RecyclableObject* function, CallInfo callInfo, ...);
360357
static Var DelayDynamicInterpreterThunk(RecyclableObject* function, CallInfo callInfo, ...);
361358
_NOINLINE static Var InterpreterThunk(JavascriptCallStackLayout* layout);
362359
_NOINLINE static Var StaticInterpreterThunk(RecyclableObject* function, CallInfo callInfo, ...);

0 commit comments

Comments
 (0)