Forráskód Böngészése

[1.10>master] [MERGE #5441 @atulkatti] Revert "MSFT:18139538 Remove the use of Guest Arena from parser code to avoid ScriptContext leak."

Merge pull request #5441 from atulkatti:Revert.ParserGuestArenaRemoval.1

This reverts commit 3fb7fddd0e8b5ddaf869988dd0b98fa098b9792e.

This introduced a leak in the modules that will need non-trivial work to get rid of.
Atul Katti 7 éve
szülő
commit
ccc6a8bf6a

+ 1 - 1
lib/Common/Memory/RecyclerRootPtr.h

@@ -51,7 +51,7 @@ public:
     }
     void Unroot()
     {
-        if (this->ptr != nullptr)
+        if (ptr != nullptr)
         {
             __super::Unroot(recycler);
         }

+ 6 - 6
lib/Parser/Parse.cpp

@@ -83,9 +83,8 @@ Parser::Parser(Js::ScriptContext* scriptContext, BOOL strictMode, PageAllocator
     m_doingFastScan(false),
 #endif
     m_nextBlockId(0),
-    m_tempGuestArena(scriptContext->GetTemporaryGuestAllocator(_u("ParserRegex")), scriptContext->GetRecycler()),
     // use the GuestArena directly for keeping the RegexPattern* alive during byte code generation
-    m_registeredRegexPatterns(m_tempGuestArena->GetAllocator()),
+    m_registeredRegexPatterns(scriptContext->GetGuestArena()),
 
     m_scriptContext(scriptContext),
     m_token(), // should initialize to 0/nullptrs
@@ -156,10 +155,11 @@ Parser::Parser(Js::ScriptContext* scriptContext, BOOL strictMode, PageAllocator
 
 Parser::~Parser(void)
 {
-    m_registeredRegexPatterns.Reset();
-    if (m_scriptContext != nullptr)
+    if (m_scriptContext == nullptr || m_scriptContext->GetGuestArena() == nullptr)
     {
-        m_scriptContext->ReleaseTemporaryGuestAllocator(m_tempGuestArena);
+        // If the scriptContext or guestArena have gone away, there is no point clearing each item of this list.
+        // Just reset it so that destructor of the SList will be no-op
+        m_registeredRegexPatterns.Reset();
     }
 
 #if ENABLE_BACKGROUND_PARSING
@@ -1926,7 +1926,7 @@ void Parser::RegisterRegexPattern(UnifiedRegex::RegexPattern *const regexPattern
     Assert(regexPattern);
 
     // ensure a no-throw add behavior here, to catch out of memory exceptions, using the guest arena allocator
-    if (!m_registeredRegexPatterns.PrependNoThrow(m_tempGuestArena->GetAllocator(), regexPattern))
+    if (!m_registeredRegexPatterns.PrependNoThrow(m_scriptContext->GetGuestArena(), regexPattern))
     {
         Parser::Error(ERRnoMemory);
     }

+ 1 - 4
lib/Parser/Parse.h

@@ -177,8 +177,6 @@ namespace Js
 {
     class ParseableFunctionInfo;
     class FunctionBody;
-    template <bool isGuestArena>
-    class TempArenaAllocatorWrapper;
 };
 
 class Parser
@@ -275,9 +273,8 @@ private:
 #endif
     int                 m_nextBlockId;
 
-    AutoRecyclerRootPtr<Js::TempArenaAllocatorWrapper<true>> m_tempGuestArena;
     // RegexPattern objects created for literal regexes are recycler-allocated and need to be kept alive until the function body
-    // is created during byte code generation. The RegexPattern pointer is stored in a temporary guest
+    // is created during byte code generation. The RegexPattern pointer is stored in the script context's guest
     // arena for that purpose. This list is then unregistered from the guest arena at the end of parsing/scanning.
     SList<UnifiedRegex::RegexPattern *, ArenaAllocator> m_registeredRegexPatterns;
 

+ 22 - 0
lib/Runtime/Base/ScriptContext.cpp

@@ -89,6 +89,7 @@ namespace Js
         integerStringMapCacheMissCount(0),
         integerStringMapCacheUseCount(0),
 #endif
+        guestArena(nullptr),
 #ifdef ENABLE_SCRIPT_DEBUGGING
         diagnosticArena(nullptr),
         raiseMessageToDebuggerFunctionType(nullptr),
@@ -798,6 +799,12 @@ namespace Js
             interpreterArena = nullptr;
         }
 
+        if (this->guestArena)
+        {
+            ReleaseGuestArena();
+            guestArena = nullptr;
+        }
+
         builtInLibraryFunctions = nullptr;
 
         pActiveScriptDirect = nullptr;
@@ -1298,6 +1305,8 @@ namespace Js
 
     void ScriptContext::InitializePreGlobal()
     {
+        this->guestArena = this->GetRecycler()->CreateGuestArena(_u("Guest"), Throw::OutOfMemory);
+
 #if ENABLE_BACKGROUND_PARSING
         if (PHASE_ON1(Js::ParallelParsePhase))
         {
@@ -2751,6 +2760,17 @@ ExitTempAllocator:
         }
     }
 
+
+    void ScriptContext::ReleaseGuestArena()
+    {
+        AssertMsg(this->guestArena, "No guest arena to release");
+        if (this->guestArena)
+        {
+            this->GetRecycler()->DeleteGuestArena(this->guestArena);
+            this->guestArena = nullptr;
+        }
+    }
+
     void ScriptContext::SetScriptStartEventHandler(ScriptContext::EventHandler eventHandler)
     {
         AssertMsg(this->scriptStartEventHandler == nullptr, "Do not support multi-cast yet");
@@ -4955,6 +4975,7 @@ ExitTempAllocator:
     void ScriptContext::BindReference(void * addr)
     {
         Assert(!this->isClosed);
+        Assert(this->guestArena);
         Assert(recycler->IsValidObject(addr));
 #if DBG
         Assert(!bindRef.ContainsKey(addr));     // Make sure we don't bind the same pointer twice
@@ -5121,6 +5142,7 @@ ExitTempAllocator:
         {
             return;
         }
+        Assert(this->guestArena);
 
         if (EnableEvalMapCleanup())
         {

+ 8 - 0
lib/Runtime/Base/ScriptContext.h

@@ -578,6 +578,7 @@ namespace Js
         CacheAllocator enumeratorCacheAllocator;
 
         ArenaAllocator* interpreterArena;
+        ArenaAllocator* guestArena;
 
 #ifdef ENABLE_SCRIPT_DEBUGGING
         ArenaAllocator* diagnosticArena;
@@ -1377,6 +1378,13 @@ private:
         bool EnsureInterpreterArena(ArenaAllocator **);
         void ReleaseInterpreterArena();
 
+        ArenaAllocator* GetGuestArena() const
+        {
+            return guestArena;
+        }
+
+        void ReleaseGuestArena();
+
         Recycler* GetRecycler() const { return recycler; }
         RecyclerJavascriptNumberAllocator * GetNumberAllocator() { return &numberAllocator; }
 #if ENABLE_NATIVE_CODEGEN