2
0
Paul Leathers 5 жил өмнө
parent
commit
f645b2d468

+ 11 - 0
lib/Backend/Func.cpp

@@ -55,6 +55,7 @@ Func::Func(JitArenaAllocator *alloc, JITTimeWorkItem * workItem,
     m_localClosureSym(nullptr),
     m_paramClosureSym(nullptr),
     m_localFrameDisplaySym(nullptr),
+    m_inlineeFrameDisplaySyms(nullptr),
     m_bailoutReturnValueSym(nullptr),
     m_hasBailedOutSym(nullptr),
     m_inlineeFrameStartSym(nullptr),
@@ -1124,6 +1125,16 @@ void Func::InitLocalClosureSyms()
     }
 }
 
+void
+Func::AddInlineeFrameDisplaySym(StackSym *inlineeFrameDisplaySym)
+{
+    if (m_inlineeFrameDisplaySyms == nullptr)
+    {
+        m_inlineeFrameDisplaySyms = JitAnew(this->m_alloc, SList<StackSym*>, this->m_alloc);
+    }
+    m_inlineeFrameDisplaySyms->Prepend(inlineeFrameDisplaySym);
+}
+
 bool
 Func::IsTrackCompoundedIntOverflowDisabled() const
 {

+ 2 - 0
lib/Backend/Func.h

@@ -441,6 +441,7 @@ static const unsigned __int64 c_debugFillPattern8 = 0xcececececececece;
 
     StackSym *GetLocalFrameDisplaySym() const { return m_localFrameDisplaySym; }
     void SetLocalFrameDisplaySym(StackSym *sym) { m_localFrameDisplaySym = sym; }
+    void AddInlineeFrameDisplaySym(StackSym *sym);
 
     intptr_t GetJittedLoopIterationsSinceLastBailoutAddress() const;
     void EnsurePinnedTypeRefs();
@@ -678,6 +679,7 @@ public:
     StackSym *          m_paramClosureSym;
     StackSym *          m_localFrameDisplaySym;
     StackSym *          m_bailoutReturnValueSym;
+    SList<StackSym*> *  m_inlineeFrameDisplaySyms;
     StackSym *          m_hasBailedOutSym;
     uint                m_forInLoopMaxDepth;
     uint                m_forInLoopBaseDepth;

+ 5 - 0
lib/Backend/IRBuilder.cpp

@@ -661,6 +661,11 @@ IRBuilder::Build()
                             dstOpnd, m_func),
                         offset);
                 }
+                else if (m_func->GetTopFunc()->DoStackFrameDisplay())
+                {
+                    Assert(m_func->GetLocalFrameDisplaySym() != nullptr);
+                    m_func->GetTopFunc()->AddInlineeFrameDisplaySym(m_func->GetLocalFrameDisplaySym());
+                }
             }
         }
     }

+ 45 - 2
lib/Backend/Lower.cpp

@@ -49,9 +49,11 @@ Lowerer::Lower()
     {
         EnsureStackFunctionListStackSym();
     }
+    StackSym * symInlineeFrameDisplayEnd = nullptr;
     if (m_func->DoStackFrameDisplay() && !m_func->IsLoopBody())
     {
-        AllocStackClosure();
+        symInlineeFrameDisplayEnd = StackSym::New(m_func);
+        AllocStackClosure(symInlineeFrameDisplayEnd);
     }
 
     AllocStackForInObjectEnumeratorArray();
@@ -140,6 +142,11 @@ Lowerer::Lower()
         EnsureZeroLastStackFunctionNext();
     }
 
+    if (symInlineeFrameDisplayEnd != nullptr)
+    {
+        InitializeInlineeFrameDisplays(symInlineeFrameDisplayEnd);
+    }
+
     if (!m_func->IsSimpleJit())
     {
 #if 0 // TODO michhol oop jit, reenable assert
@@ -6755,10 +6762,40 @@ Lowerer::EnsureStackFunctionListStackSym()
 }
 
 void
-Lowerer::AllocStackClosure()
+Lowerer::AllocStackClosure(StackSym * symInlineeFrameDisplayEnd)
 {
     m_func->StackAllocate(m_func->GetLocalFrameDisplaySym(), sizeof(Js::Var));
     m_func->StackAllocate(m_func->GetLocalClosureSym(), sizeof(Js::Var));
+
+    if (m_func->m_inlineeFrameDisplaySyms != nullptr)
+    {
+        FOREACH_SLIST_ENTRY(StackSym*, sym, m_func->m_inlineeFrameDisplaySyms)
+        {
+            m_func->StackAllocate(sym, sizeof(Js::Var));
+        }
+        NEXT_SLIST_ENTRY;
+    }
+    m_func->StackAllocate(symInlineeFrameDisplayEnd, sizeof(Js::Var));
+}
+
+void
+Lowerer::InitializeInlineeFrameDisplays(StackSym * symInlineeFrameDisplayEnd)
+{
+    if (m_func->m_inlineeFrameDisplaySyms != nullptr)
+    {
+        FOREACH_SLIST_ENTRY(StackSym*, sym, m_func->m_inlineeFrameDisplaySyms)
+        {
+            Assert(sym->IsAllocated());
+            InsertMove(IR::SymOpnd::New(sym, TyMachReg, m_func),
+                       IR::AddrOpnd::New(m_func->GetThreadContextInfo()->GetNullFrameDisplayAddr(), IR::AddrOpndKindDynamicMisc, m_func),
+                       m_func->GetFunctionEntryInsertionPoint());
+        }
+        NEXT_SLIST_ENTRY;
+    }
+    Assert(symInlineeFrameDisplayEnd->IsAllocated());
+    InsertMove(IR::SymOpnd::New(symInlineeFrameDisplayEnd, TyMachReg, m_func),
+               IR::AddrOpnd::New((void*)0, IR::AddrOpndKindDynamicMisc, m_func),
+               m_func->GetFunctionEntryInsertionPoint());
 }
 
 void
@@ -27112,6 +27149,12 @@ void Lowerer::LowerLdFrameDisplay(IR::Instr *instr, bool doStackFrameDisplay)
     else
     {
         GenerateRecyclerAlloc(IR::HelperAllocMemForFrameDisplay, allocSize, dstOpnd, instr);
+        if (instr->m_func != this->m_func && this->m_func->DoStackFrameDisplay())
+        {
+            StackSym * inlineeFrameDisplaySym = instr->m_func->GetLocalFrameDisplaySym();
+            Assert(inlineeFrameDisplaySym->IsAllocated());
+            InsertMove(IR::SymOpnd::New(inlineeFrameDisplaySym, TyMachReg, m_func), dstOpnd, instr);
+        }
     }
 
     // Copy contents of environment

+ 2 - 1
lib/Backend/Lower.h

@@ -196,7 +196,8 @@ private:
 
     void            EnsureStackFunctionListStackSym();
     void            EnsureZeroLastStackFunctionNext();
-    void            AllocStackClosure();
+    void            AllocStackClosure(StackSym * symInlineeFrameDisplayEnd);
+    void            InitializeInlineeFrameDisplays(StackSym * symInlineeFrameDisplayEnd);
     IR::Instr *     GenerateNewStackScFunc(IR::Instr * newScFuncInstr, IR::RegOpnd ** ppEnvOpnd);
     void            GenerateStackScriptFunctionInit(StackSym * stackSym, Js::FunctionInfoPtrPtr nestedInfo);
     void            GenerateScriptFunctionInit(IR::RegOpnd * regOpnd, IR::Opnd * vtableAddressOpnd,

+ 2 - 0
lib/Runtime/Base/Constants.h

@@ -132,10 +132,12 @@ namespace Js
         static const int StackNestedFuncList = 2;
         static const int StackFrameDisplay = 3;
         static const int StackScopeSlots = 4;
+        static const int InlineeFrameDisplays = 5;
 #if _M_IX86 || _M_AMD64
         static const int StackNestedFuncListWithNoArg = 1;
         static const int StackFrameDisplayWithNoArg = 2;
         static const int StackScopeSlotsWithNoArg = 3;
+        static const int InlineeFrameDisplaysWithNoArg = 4;
 #endif
 
         static const DWORD NonWebWorkerContextId = 0;

+ 2 - 0
lib/Runtime/Language/JavascriptFunctionArgIndex.h

@@ -13,10 +13,12 @@ namespace Js
         JavascriptFunctionArgIndex_StackNestedFuncListWithNoArg = JavascriptFunctionArgIndex_Frame - Js::Constants::StackNestedFuncListWithNoArg,
         JavascriptFunctionArgIndex_StackFrameDisplayNoArg = JavascriptFunctionArgIndex_Frame - Js::Constants::StackFrameDisplayWithNoArg,
         JavascriptFunctionArgIndex_StackScopeSlotsNoArg = JavascriptFunctionArgIndex_Frame - Js::Constants::StackScopeSlotsWithNoArg,
+        JavascriptFunctionArgIndex_InlineeFrameDisplaysNoArg = JavascriptFunctionArgIndex_Frame - Js::Constants::InlineeFrameDisplaysWithNoArg,
 #endif
         JavascriptFunctionArgIndex_StackNestedFuncList = JavascriptFunctionArgIndex_Frame - Js::Constants::StackNestedFuncList,
         JavascriptFunctionArgIndex_StackFrameDisplay = JavascriptFunctionArgIndex_Frame - Js::Constants::StackFrameDisplay,
         JavascriptFunctionArgIndex_StackScopeSlots = JavascriptFunctionArgIndex_Frame - Js::Constants::StackScopeSlots,
+        JavascriptFunctionArgIndex_InlineeFrameDisplays = JavascriptFunctionArgIndex_Frame - Js::Constants::InlineeFrameDisplays,
         JavascriptFunctionArgIndex_Function        = 0,
         JavascriptFunctionArgIndex_CallInfo        = 1,
         JavascriptFunctionArgIndex_This            = 2, /* (hidden) first script arg */

+ 64 - 0
lib/Runtime/Library/StackScriptFunction.cpp

@@ -436,6 +436,11 @@ namespace Js
             }
         }
 
+        UpdateFrameDisplay(frameDisplay);
+    }
+
+    void StackScriptFunction::BoxState::UpdateFrameDisplay(FrameDisplay *frameDisplay)
+    {
         for (uint i = 0; i < frameDisplay->GetLength(); i++)
         {
             Var* stackScopeSlots = (Var*)frameDisplay->GetItem(i);
@@ -475,6 +480,20 @@ namespace Js
         }
     }
 
+    uintptr_t StackScriptFunction::BoxState::GetInlineeFrameDisplaysIndex(FunctionBody * functionBody)
+    {
+#if _M_IX86 || _M_AMD64
+        if (functionBody->GetInParamsCount() == 0)
+        {
+            return (uintptr_t)JavascriptFunctionArgIndex_InlineeFrameDisplaysNoArg;
+        }
+        else
+#endif
+        {
+            return (uintptr_t)JavascriptFunctionArgIndex_InlineeFrameDisplays;
+        }
+    }
+
     FrameDisplay * StackScriptFunction::BoxState::GetFrameDisplayFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody)
     {
         uintptr_t frameDisplayIndex = GetNativeFrameDisplayIndex(callerFunctionBody);
@@ -489,6 +508,13 @@ namespace Js
         return (Var*)argv[scopeSlotsIndex];
     }
 
+    FrameDisplay * StackScriptFunction::BoxState::GetInlineeFrameDisplaysFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody)
+    {
+        uintptr_t inlineeFrameDisplaysIndex = GetInlineeFrameDisplaysIndex(callerFunctionBody);
+        void **argv = walker.GetCurrentArgv();
+        return (FrameDisplay*)argv[inlineeFrameDisplaysIndex];
+    }
+
     void StackScriptFunction::BoxState::SetFrameDisplayFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, FrameDisplay * frameDisplay)
     {
         uintptr_t frameDisplayIndex = GetNativeFrameDisplayIndex(callerFunctionBody);
@@ -541,6 +567,13 @@ namespace Js
                 callerFunctionBody->GetScriptContext()->GetThreadContext()->AddImplicitCallFlags(ImplicitCall_Accessor);
             }
         }
+
+        this->ForEachInlineeFrameDisplay(walker, callerFunctionBody, [&](FrameDisplay *frameDisplay)
+        {            
+            // Update all the inlinee frame displays, which are not stack-allocated but may refer to scopes on the stack.
+            // This is only necessary in a native frame that does stack frame displays
+            this->UpdateFrameDisplay(frameDisplay);
+        });
     }
 
     template<class Fn>
@@ -615,6 +648,37 @@ namespace Js
         }
     }
 
+    template<class Fn>
+    void StackScriptFunction::BoxState::ForEachInlineeFrameDisplay(
+        JavascriptStackWalker const& walker,
+        FunctionBody *callerFunctionBody,
+        Fn fn)
+    {
+        if (!callerFunctionBody->DoStackFrameDisplay() || walker.GetCurrentInterpreterFrame() != nullptr || walker.IsInlineFrame())
+        {
+            return;
+        }
+
+#ifdef MD_GROW_LOCALS_AREA_UP
+        // Stack closures not supported for layouts like ARM. We shouldn't get here.
+        AssertOrFailFast(0);
+#endif
+
+        void **argv = walker.GetCurrentArgv();
+        FrameDisplay ** curr = (FrameDisplay**)(
+#if _M_IX86 || _M_AMD64
+            callerFunctionBody->GetInParamsCount() == 0?
+            &argv[JavascriptFunctionArgIndex_InlineeFrameDisplaysNoArg]:
+#endif
+            &argv[JavascriptFunctionArgIndex_InlineeFrameDisplays]);
+
+        while (*curr != nullptr)
+        {
+            fn(*curr);
+            curr--; 
+        }
+    }
+
     void StackScriptFunction::BoxState::Finish()
     {
         frameToBox.Map([](FunctionBody * body)

+ 5 - 0
lib/Runtime/Library/StackScriptFunction.h

@@ -62,11 +62,13 @@ namespace Js
             ScriptFunction * BoxStackFunction(ScriptFunction * scriptFunction);
             FrameDisplay * BoxFrameDisplay(FrameDisplay * frameDisplay);
             FrameDisplay * GetFrameDisplayFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody);
+            FrameDisplay * GetInlineeFrameDisplaysFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody);
             Var * GetScopeSlotsFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody);
             void SetFrameDisplayFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, FrameDisplay * frameDisplay);
             void SetScopeSlotsFromNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, Var * scopeSlots);
             void BoxNativeFrame(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody);
             void UpdateFrameDisplay(ScriptFunction *nestedFunc);
+            void UpdateFrameDisplay(FrameDisplay *frameDisplay);
             void Finish();
 
             template<class Fn>
@@ -75,9 +77,12 @@ namespace Js
             void ForEachStackNestedFunctionInterpreted(InterpreterStackFrame *interpreterFrame, FunctionBody * callerFunctionBody, Fn fn);
             template<class Fn>
             void ForEachStackNestedFunctionNative(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, Fn fn);
+            template<class Fn>
+            void ForEachInlineeFrameDisplay(JavascriptStackWalker const& walker, FunctionBody * callerFunctionBody, Fn fn);
 
             static uintptr_t GetNativeFrameDisplayIndex(FunctionBody * functionBody);
             static uintptr_t GetNativeScopeSlotsIndex(FunctionBody * functionBody);
+            static uintptr_t GetInlineeFrameDisplaysIndex(FunctionBody * functionBody);
         };
 
         ScriptFunction * boxedScriptFunction;