@@ -1022,33 +1022,35 @@ namespace Js
1022
1022
uint forInVarCount = bailedOut ? 0 : (this ->executeFunction ->GetForInLoopDepth () * (sizeof (Js::ForInObjectEnumerator) / sizeof (Var)));
1023
1023
this ->varAllocCount = k_stackFrameVarCount + localCount + this ->executeFunction ->GetOutParamMaxDepth () + forInVarCount +
1024
1024
extraVarCount + this ->executeFunction ->GetInnerScopeCount ();
1025
+ this ->stackVarAllocCount = 0 ;
1025
1026
1026
1027
if (this ->executeFunction ->DoStackNestedFunc () && this ->executeFunction ->GetNestedCount () != 0 )
1027
1028
{
1028
1029
// Track stack funcs...
1029
- this ->varAllocCount += (sizeof (StackScriptFunction) * this ->executeFunction ->GetNestedCount ()) / sizeof (Var);
1030
+ this ->stackVarAllocCount += (sizeof (StackScriptFunction) * this ->executeFunction ->GetNestedCount ()) / sizeof (Var);
1030
1031
if (!this ->bailedOutOfInlinee )
1031
1032
{
1032
1033
// Frame display (if environment depth is statically known)...
1033
1034
if (this ->executeFunction ->DoStackFrameDisplay ())
1034
1035
{
1035
1036
uint16 envDepth = this ->executeFunction ->GetEnvDepth ();
1036
1037
Assert (envDepth != (uint16)-1 );
1037
- this ->varAllocCount += sizeof (FrameDisplay) / sizeof (Var) + (envDepth + 1 );
1038
+ this ->stackVarAllocCount += sizeof (FrameDisplay) / sizeof (Var) + (envDepth + 1 );
1038
1039
}
1039
1040
// ...and scope slots (if any)
1040
1041
if (this ->executeFunction ->DoStackScopeSlots ())
1041
1042
{
1042
1043
uint32 scopeSlots = this ->executeFunction ->scopeSlotArraySize ;
1043
1044
Assert (scopeSlots != 0 );
1044
- this ->varAllocCount += scopeSlots + Js::ScopeSlots::FirstSlotIndex;
1045
+ this ->stackVarAllocCount += scopeSlots + Js::ScopeSlots::FirstSlotIndex;
1045
1046
}
1046
1047
}
1047
1048
}
1048
1049
}
1049
1050
1050
1051
InterpreterStackFrame *
1051
- InterpreterStackFrame::Setup::InitializeAllocation (__in_ecount(varAllocCount) Var * allocation, bool initParams, bool profileParams, LoopHeader* loopHeaderArray, DWORD_PTR stackAddr
1052
+ InterpreterStackFrame::Setup::InitializeAllocation (__in_ecount(varAllocCount) Var * allocation, __in_ecount(stackVarAllocCount) Var * stackAllocation
1053
+ , bool initParams, bool profileParams, LoopHeader* loopHeaderArray, DWORD_PTR stackAddr
1052
1054
#if DBG
1053
1055
, Var invalidStackVar
1054
1056
#endif
@@ -1183,29 +1185,35 @@ namespace Js
1183
1185
1184
1186
if (this ->executeFunction ->DoStackNestedFunc () && this ->executeFunction ->GetNestedCount () != 0 )
1185
1187
{
1186
- newInstance->InitializeStackFunctions ((StackScriptFunction *)nextAllocBytes);
1187
- nextAllocBytes = nextAllocBytes + sizeof (StackScriptFunction) * this ->executeFunction ->GetNestedCount ();
1188
+ char * stackAllocBytes = (stackAllocation != nullptr ) ? (char *)stackAllocation : nextAllocBytes;
1189
+
1190
+ newInstance->InitializeStackFunctions ((StackScriptFunction *)stackAllocBytes);
1191
+ stackAllocBytes += sizeof (StackScriptFunction) * this ->executeFunction ->GetNestedCount ();
1188
1192
1189
1193
if (!this ->bailedOutOfInlinee )
1190
1194
{
1191
1195
if (this ->executeFunction ->DoStackFrameDisplay ())
1192
1196
{
1193
1197
uint16 envDepth = this ->executeFunction ->GetEnvDepth ();
1194
1198
Assert (envDepth != (uint16)-1 );
1195
- newInstance->localFrameDisplay = (FrameDisplay*)nextAllocBytes ;
1199
+ newInstance->localFrameDisplay = (FrameDisplay*)stackAllocBytes ;
1196
1200
newInstance->localFrameDisplay ->SetLength (0 ); // Start with no scopes. It will get set in NewFrameDisplay
1197
- nextAllocBytes += sizeof (FrameDisplay) + (envDepth + 1 ) * sizeof (Var);
1201
+ stackAllocBytes += sizeof (FrameDisplay) + (envDepth + 1 ) * sizeof (Var);
1198
1202
}
1199
1203
1200
1204
if (this ->executeFunction ->DoStackScopeSlots ())
1201
1205
{
1202
1206
uint32 scopeSlots = this ->executeFunction ->scopeSlotArraySize ;
1203
1207
Assert (scopeSlots != 0 );
1204
- ScopeSlots ((Field (Var)*)nextAllocBytes ).SetCount (0 ); // Start with count as 0. It will get set in NewScopeSlots
1205
- newInstance->localClosure = nextAllocBytes ;
1206
- nextAllocBytes += (scopeSlots + ScopeSlots::FirstSlotIndex) * sizeof (Var);
1208
+ ScopeSlots ((Field (Var)*)stackAllocBytes ).SetCount (0 ); // Start with count as 0. It will get set in NewScopeSlots
1209
+ newInstance->localClosure = stackAllocBytes ;
1210
+ stackAllocBytes += (scopeSlots + ScopeSlots::FirstSlotIndex) * sizeof (Var);
1207
1211
}
1208
1212
}
1213
+ if (stackAllocation == nullptr )
1214
+ {
1215
+ nextAllocBytes = stackAllocBytes;
1216
+ }
1209
1217
}
1210
1218
#if ENABLE_PROFILE_INFO
1211
1219
if (Js::DynamicProfileInfo::EnableImplicitCallFlags (this ->executeFunction ))
@@ -1755,6 +1763,7 @@ namespace Js
1755
1763
ScriptContext* functionScriptContext = function->GetScriptContext ();
1756
1764
Arguments generatorArgs = generator->GetArguments ();
1757
1765
InterpreterStackFrame::Setup setup (function, generatorArgs);
1766
+ Assert (setup.GetStackAllocationVarCount () == 0 );
1758
1767
size_t varAllocCount = setup.GetAllocationVarCount ();
1759
1768
size_t varSizeInBytes = varAllocCount * sizeof (Var);
1760
1769
DWORD_PTR stackAddr = reinterpret_cast <DWORD_PTR>(&generator); // use any stack address from this frame to ensure correct debugging functionality
@@ -1768,11 +1777,14 @@ namespace Js
1768
1777
Js::RecyclableObject* invalidVar = (Js::RecyclableObject*)RecyclerNewPlusLeaf (functionScriptContext->GetRecycler (), sizeof (Js::RecyclableObject), Var);
1769
1778
AnalysisAssert (invalidVar);
1770
1779
memset (reinterpret_cast <void *>(invalidVar), 0xFE , sizeof (Js::RecyclableObject));
1771
- newInstance = setup.InitializeAllocation (allocation, executeFunction->GetHasImplicitArgIns (), doProfile, loopHeaderArray, stackAddr, invalidVar);
1772
- #else
1773
- newInstance = setup.InitializeAllocation (allocation, executeFunction->GetHasImplicitArgIns (), doProfile, loopHeaderArray, stackAddr);
1774
1780
#endif
1775
1781
1782
+ newInstance = setup.InitializeAllocation (allocation, nullptr , executeFunction->GetHasImplicitArgIns (), doProfile, loopHeaderArray, stackAddr
1783
+ #if DBG
1784
+ , invalidVar
1785
+ #endif
1786
+ );
1787
+
1776
1788
newInstance->m_reader .Create (executeFunction);
1777
1789
1778
1790
generator->SetFrame (newInstance, varSizeInBytes);
@@ -1914,26 +1926,36 @@ namespace Js
1914
1926
{
1915
1927
InterpreterStackFrame::Setup setup (function, args);
1916
1928
size_t varAllocCount = setup.GetAllocationVarCount ();
1917
- size_t varSizeInBytes = varAllocCount * sizeof (Var);
1929
+ size_t stackVarAllocCount = setup.GetStackAllocationVarCount ();
1930
+ size_t varSizeInBytes;
1918
1931
1919
1932
//
1920
1933
// Allocate a new InterpreterStackFrame instance on the interpreter's virtual stack.
1921
1934
//
1922
1935
DWORD_PTR stackAddr;
1923
1936
1924
1937
Var* allocation;
1938
+ Var* stackAllocation = nullptr ;
1925
1939
1926
1940
// If the locals area exceeds a certain limit, allocate it from a private arena rather than
1927
1941
// this frame. The current limit is based on an old assert on the number of locals we would allow here.
1928
- if (varAllocCount > InterpreterStackFrame::LocalsThreshold)
1942
+ if (( varAllocCount + stackVarAllocCount) > InterpreterStackFrame::LocalsThreshold)
1929
1943
{
1930
1944
ArenaAllocator *tmpAlloc = nullptr ;
1931
1945
fReleaseAlloc = functionScriptContext->EnsureInterpreterArena (&tmpAlloc);
1946
+ varSizeInBytes = varAllocCount * sizeof (Var);
1932
1947
allocation = (Var*)tmpAlloc->Alloc (varSizeInBytes);
1933
1948
stackAddr = reinterpret_cast <DWORD_PTR>(&allocation); // use a stack address so the debugger stepping logic works (step-out, for example, compares stack depths to determine when to complete the step)
1949
+ if (stackVarAllocCount != 0 )
1950
+ {
1951
+ size_t stackVarSizeInBytes = stackVarAllocCount * sizeof (Var);
1952
+ PROBE_STACK_PARTIAL_INITIALIZED_INTERPRETER_FRAME (functionScriptContext, Js::Constants::MinStackInterpreter + stackVarSizeInBytes);
1953
+ stackAllocation = (Var*)_alloca (stackVarSizeInBytes);
1954
+ }
1934
1955
}
1935
1956
else
1936
1957
{
1958
+ varSizeInBytes = (varAllocCount + stackVarAllocCount) * sizeof (Var);
1937
1959
PROBE_STACK_PARTIAL_INITIALIZED_INTERPRETER_FRAME (functionScriptContext, Js::Constants::MinStackInterpreter + varSizeInBytes);
1938
1960
allocation = (Var*)_alloca (varSizeInBytes);
1939
1961
#if DBG
@@ -1966,11 +1988,14 @@ namespace Js
1966
1988
#if DBG
1967
1989
Js::RecyclableObject * invalidStackVar = (Js::RecyclableObject*)_alloca (sizeof (Js::RecyclableObject));
1968
1990
memset (reinterpret_cast <void *>(invalidStackVar), 0xFE , sizeof (Js::RecyclableObject));
1969
- newInstance = setup.InitializeAllocation (allocation, executeFunction->GetHasImplicitArgIns () && !isAsmJs, doProfile, loopHeaderArray, stackAddr, invalidStackVar);
1970
- #else
1971
- newInstance = setup.InitializeAllocation (allocation, executeFunction->GetHasImplicitArgIns () && !isAsmJs, doProfile, loopHeaderArray, stackAddr);
1972
1991
#endif
1973
1992
1993
+ newInstance = setup.InitializeAllocation (allocation, stackAllocation, executeFunction->GetHasImplicitArgIns () && !isAsmJs, doProfile, loopHeaderArray, stackAddr
1994
+ #if DBG
1995
+ , invalidStackVar
1996
+ #endif
1997
+ );
1998
+
1974
1999
newInstance->m_reader .Create (executeFunction);
1975
2000
}
1976
2001
//
@@ -2784,22 +2809,32 @@ namespace Js
2784
2809
// after reparsing, we want to also use a new interpreter stack frame, as it will have different characteristics than the asm.js version
2785
2810
InterpreterStackFrame::Setup setup (funcObj, m_inParams, m_inSlotsCount);
2786
2811
size_t varAllocCount = setup.GetAllocationVarCount ();
2787
- size_t varSizeInBytes = varAllocCount * sizeof (Var);
2812
+ size_t stackVarAllocCount = setup.GetStackAllocationVarCount ();
2813
+ size_t varSizeInBytes;
2788
2814
2789
2815
Var* allocation = nullptr ;
2816
+ Var* stackAllocation = nullptr ;
2790
2817
DWORD_PTR stackAddr;
2791
2818
bool fReleaseAlloc = false ;
2792
- if (varAllocCount > InterpreterStackFrame::LocalsThreshold)
2819
+ if (( varAllocCount + stackVarAllocCount) > InterpreterStackFrame::LocalsThreshold)
2793
2820
{
2794
2821
ArenaAllocator *tmpAlloc = nullptr ;
2795
2822
fReleaseAlloc = GetScriptContext ()->EnsureInterpreterArena (&tmpAlloc);
2823
+ varSizeInBytes = varAllocCount * sizeof (Var);
2796
2824
allocation = (Var*)tmpAlloc->Alloc (varSizeInBytes);
2825
+ if (stackVarAllocCount != 0 )
2826
+ {
2827
+ size_t stackVarSizeInBytes = stackVarAllocCount * sizeof (Var);
2828
+ PROBE_STACK_PARTIAL_INITIALIZED_INTERPRETER_FRAME (GetScriptContext (), Js::Constants::MinStackInterpreter + stackVarSizeInBytes);
2829
+ stackAllocation = (Var*)_alloca (stackVarSizeInBytes);
2830
+ }
2797
2831
// use a stack address so the debugger stepping logic works (step-out, for example, compares stack depths to determine when to complete the step)
2798
2832
// debugger stepping does not matter here, but it's worth being consistent with normal stack frame
2799
2833
stackAddr = reinterpret_cast <DWORD_PTR>(&allocation);
2800
2834
}
2801
2835
else
2802
2836
{
2837
+ varSizeInBytes = (varAllocCount + stackVarAllocCount) * sizeof (Var);
2803
2838
PROBE_STACK_PARTIAL_INITIALIZED_INTERPRETER_FRAME (GetScriptContext (), Js::Constants::MinStackInterpreter + varSizeInBytes);
2804
2839
allocation = (Var*)_alloca (varSizeInBytes);
2805
2840
stackAddr = reinterpret_cast <DWORD_PTR>(allocation);
@@ -2808,10 +2843,14 @@ namespace Js
2808
2843
#if DBG
2809
2844
Var invalidStackVar = (Js::RecyclableObject*)_alloca (sizeof (Js::RecyclableObject));
2810
2845
memset (invalidStackVar, 0xFE , sizeof (Js::RecyclableObject));
2811
- InterpreterStackFrame * newInstance = newInstance = setup.InitializeAllocation (allocation, funcObj->GetFunctionBody ()->GetHasImplicitArgIns (), doProfile, nullptr , stackAddr, invalidStackVar);
2812
- #else
2813
- InterpreterStackFrame * newInstance = newInstance = setup.InitializeAllocation (allocation, funcObj->GetFunctionBody ()->GetHasImplicitArgIns (), doProfile, nullptr , stackAddr);
2814
2846
#endif
2847
+
2848
+ InterpreterStackFrame * newInstance = setup.InitializeAllocation (allocation, stackAllocation, funcObj->GetFunctionBody ()->GetHasImplicitArgIns (), doProfile, nullptr , stackAddr
2849
+ #if DBG
2850
+ , invalidStackVar
2851
+ #endif
2852
+ );
2853
+
2815
2854
newInstance->m_reader .Create (funcObj->GetFunctionBody ());
2816
2855
// now that we have set up the new frame, let's interpret it!
2817
2856
funcObj->GetFunctionBody ()->BeginExecution ();
0 commit comments