@@ -1022,33 +1022,35 @@ namespace Js
10221022 uint forInVarCount = bailedOut ? 0 : (this ->executeFunction ->GetForInLoopDepth () * (sizeof (Js::ForInObjectEnumerator) / sizeof (Var)));
10231023 this ->varAllocCount = k_stackFrameVarCount + localCount + this ->executeFunction ->GetOutParamMaxDepth () + forInVarCount +
10241024 extraVarCount + this ->executeFunction ->GetInnerScopeCount ();
1025+ this ->stackVarAllocCount = 0 ;
10251026
10261027 if (this ->executeFunction ->DoStackNestedFunc () && this ->executeFunction ->GetNestedCount () != 0 )
10271028 {
10281029 // Track stack funcs...
1029- this ->varAllocCount += (sizeof (StackScriptFunction) * this ->executeFunction ->GetNestedCount ()) / sizeof (Var);
1030+ this ->stackVarAllocCount += (sizeof (StackScriptFunction) * this ->executeFunction ->GetNestedCount ()) / sizeof (Var);
10301031 if (!this ->bailedOutOfInlinee )
10311032 {
10321033 // Frame display (if environment depth is statically known)...
10331034 if (this ->executeFunction ->DoStackFrameDisplay ())
10341035 {
10351036 uint16 envDepth = this ->executeFunction ->GetEnvDepth ();
10361037 Assert (envDepth != (uint16)-1 );
1037- this ->varAllocCount += sizeof (FrameDisplay) / sizeof (Var) + (envDepth + 1 );
1038+ this ->stackVarAllocCount += sizeof (FrameDisplay) / sizeof (Var) + (envDepth + 1 );
10381039 }
10391040 // ...and scope slots (if any)
10401041 if (this ->executeFunction ->DoStackScopeSlots ())
10411042 {
10421043 uint32 scopeSlots = this ->executeFunction ->scopeSlotArraySize ;
10431044 Assert (scopeSlots != 0 );
1044- this ->varAllocCount += scopeSlots + Js::ScopeSlots::FirstSlotIndex;
1045+ this ->stackVarAllocCount += scopeSlots + Js::ScopeSlots::FirstSlotIndex;
10451046 }
10461047 }
10471048 }
10481049 }
10491050
10501051 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
10521054#if DBG
10531055 , Var invalidStackVar
10541056#endif
@@ -1183,29 +1185,35 @@ namespace Js
11831185
11841186 if (this ->executeFunction ->DoStackNestedFunc () && this ->executeFunction ->GetNestedCount () != 0 )
11851187 {
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 ();
11881192
11891193 if (!this ->bailedOutOfInlinee )
11901194 {
11911195 if (this ->executeFunction ->DoStackFrameDisplay ())
11921196 {
11931197 uint16 envDepth = this ->executeFunction ->GetEnvDepth ();
11941198 Assert (envDepth != (uint16)-1 );
1195- newInstance->localFrameDisplay = (FrameDisplay*)nextAllocBytes ;
1199+ newInstance->localFrameDisplay = (FrameDisplay*)stackAllocBytes ;
11961200 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);
11981202 }
11991203
12001204 if (this ->executeFunction ->DoStackScopeSlots ())
12011205 {
12021206 uint32 scopeSlots = this ->executeFunction ->scopeSlotArraySize ;
12031207 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);
12071211 }
12081212 }
1213+ if (stackAllocation == nullptr )
1214+ {
1215+ nextAllocBytes = stackAllocBytes;
1216+ }
12091217 }
12101218#if ENABLE_PROFILE_INFO
12111219 if (Js::DynamicProfileInfo::EnableImplicitCallFlags (this ->executeFunction ))
@@ -1755,6 +1763,7 @@ namespace Js
17551763 ScriptContext* functionScriptContext = function->GetScriptContext ();
17561764 Arguments generatorArgs = generator->GetArguments ();
17571765 InterpreterStackFrame::Setup setup (function, generatorArgs);
1766+ Assert (setup.GetStackAllocationVarCount () == 0 );
17581767 size_t varAllocCount = setup.GetAllocationVarCount ();
17591768 size_t varSizeInBytes = varAllocCount * sizeof (Var);
17601769 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
17681777 Js::RecyclableObject* invalidVar = (Js::RecyclableObject*)RecyclerNewPlusLeaf (functionScriptContext->GetRecycler (), sizeof (Js::RecyclableObject), Var);
17691778 AnalysisAssert (invalidVar);
17701779 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);
17741780#endif
17751781
1782+ newInstance = setup.InitializeAllocation (allocation, nullptr , executeFunction->GetHasImplicitArgIns (), doProfile, loopHeaderArray, stackAddr
1783+ #if DBG
1784+ , invalidVar
1785+ #endif
1786+ );
1787+
17761788 newInstance->m_reader .Create (executeFunction);
17771789
17781790 generator->SetFrame (newInstance, varSizeInBytes);
@@ -1914,26 +1926,36 @@ namespace Js
19141926 {
19151927 InterpreterStackFrame::Setup setup (function, args);
19161928 size_t varAllocCount = setup.GetAllocationVarCount ();
1917- size_t varSizeInBytes = varAllocCount * sizeof (Var);
1929+ size_t stackVarAllocCount = setup.GetStackAllocationVarCount ();
1930+ size_t varSizeInBytes;
19181931
19191932 //
19201933 // Allocate a new InterpreterStackFrame instance on the interpreter's virtual stack.
19211934 //
19221935 DWORD_PTR stackAddr;
19231936
19241937 Var* allocation;
1938+ Var* stackAllocation = nullptr ;
19251939
19261940 // If the locals area exceeds a certain limit, allocate it from a private arena rather than
19271941 // 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)
19291943 {
19301944 ArenaAllocator *tmpAlloc = nullptr ;
19311945 fReleaseAlloc = functionScriptContext->EnsureInterpreterArena (&tmpAlloc);
1946+ varSizeInBytes = varAllocCount * sizeof (Var);
19321947 allocation = (Var*)tmpAlloc->Alloc (varSizeInBytes);
19331948 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+ }
19341955 }
19351956 else
19361957 {
1958+ varSizeInBytes = (varAllocCount + stackVarAllocCount) * sizeof (Var);
19371959 PROBE_STACK_PARTIAL_INITIALIZED_INTERPRETER_FRAME (functionScriptContext, Js::Constants::MinStackInterpreter + varSizeInBytes);
19381960 allocation = (Var*)_alloca (varSizeInBytes);
19391961#if DBG
@@ -1966,11 +1988,14 @@ namespace Js
19661988#if DBG
19671989 Js::RecyclableObject * invalidStackVar = (Js::RecyclableObject*)_alloca (sizeof (Js::RecyclableObject));
19681990 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);
19721991#endif
19731992
1993+ newInstance = setup.InitializeAllocation (allocation, stackAllocation, executeFunction->GetHasImplicitArgIns () && !isAsmJs, doProfile, loopHeaderArray, stackAddr
1994+ #if DBG
1995+ , invalidStackVar
1996+ #endif
1997+ );
1998+
19741999 newInstance->m_reader .Create (executeFunction);
19752000 }
19762001 //
@@ -2784,22 +2809,32 @@ namespace Js
27842809 // after reparsing, we want to also use a new interpreter stack frame, as it will have different characteristics than the asm.js version
27852810 InterpreterStackFrame::Setup setup (funcObj, m_inParams, m_inSlotsCount);
27862811 size_t varAllocCount = setup.GetAllocationVarCount ();
2787- size_t varSizeInBytes = varAllocCount * sizeof (Var);
2812+ size_t stackVarAllocCount = setup.GetStackAllocationVarCount ();
2813+ size_t varSizeInBytes;
27882814
27892815 Var* allocation = nullptr ;
2816+ Var* stackAllocation = nullptr ;
27902817 DWORD_PTR stackAddr;
27912818 bool fReleaseAlloc = false ;
2792- if (varAllocCount > InterpreterStackFrame::LocalsThreshold)
2819+ if (( varAllocCount + stackVarAllocCount) > InterpreterStackFrame::LocalsThreshold)
27932820 {
27942821 ArenaAllocator *tmpAlloc = nullptr ;
27952822 fReleaseAlloc = GetScriptContext ()->EnsureInterpreterArena (&tmpAlloc);
2823+ varSizeInBytes = varAllocCount * sizeof (Var);
27962824 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+ }
27972831 // use a stack address so the debugger stepping logic works (step-out, for example, compares stack depths to determine when to complete the step)
27982832 // debugger stepping does not matter here, but it's worth being consistent with normal stack frame
27992833 stackAddr = reinterpret_cast <DWORD_PTR>(&allocation);
28002834 }
28012835 else
28022836 {
2837+ varSizeInBytes = (varAllocCount + stackVarAllocCount) * sizeof (Var);
28032838 PROBE_STACK_PARTIAL_INITIALIZED_INTERPRETER_FRAME (GetScriptContext (), Js::Constants::MinStackInterpreter + varSizeInBytes);
28042839 allocation = (Var*)_alloca (varSizeInBytes);
28052840 stackAddr = reinterpret_cast <DWORD_PTR>(allocation);
@@ -2808,10 +2843,14 @@ namespace Js
28082843#if DBG
28092844 Var invalidStackVar = (Js::RecyclableObject*)_alloca (sizeof (Js::RecyclableObject));
28102845 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);
28142846#endif
2847+
2848+ InterpreterStackFrame * newInstance = setup.InitializeAllocation (allocation, stackAllocation, funcObj->GetFunctionBody ()->GetHasImplicitArgIns (), doProfile, nullptr , stackAddr
2849+ #if DBG
2850+ , invalidStackVar
2851+ #endif
2852+ );
2853+
28152854 newInstance->m_reader .Create (funcObj->GetFunctionBody ());
28162855 // now that we have set up the new frame, let's interpret it!
28172856 funcObj->GetFunctionBody ()->BeginExecution ();
0 commit comments