Просмотр исходного кода

[1.4>master] [MERGE #2523 @MikeHolman] change OOP interpreter thunk emitter back to using EmitBufferManager

Merge pull request #2523 from MikeHolman:oopthunkrefactor

With Section API change, I moved away from this, but it turns out to have some advantages with lifetime management, keeps the logic of section management consolidated, and also keeps OOP JIT consistent with what in-proc does
Michael Holman 9 лет назад
Родитель
Сommit
9b76afb84b

+ 3 - 2
lib/Backend/EmitBuffer.cpp

@@ -357,7 +357,7 @@ bool EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::ProtectBufferWith
 // Returns true if we successfully commit the buffer
 // Returns false if we OOM
 template <typename TAlloc, typename TPreReservedAlloc, class SyncObject>
-bool EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::CommitReadWriteBufferForInterpreter(TEmitBufferAllocation* allocation, _In_reads_bytes_(bufferSize) BYTE* pBuffer, _In_ size_t bufferSize)
+bool EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::CommitBufferForInterpreter(TEmitBufferAllocation* allocation, _In_reads_bytes_(bufferSize) BYTE* pBuffer, _In_ size_t bufferSize)
 {
     Assert(this->criticalSection.IsLocked());
 
@@ -376,7 +376,7 @@ bool EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::CommitReadWriteBu
     }
 #endif
 
-    if (!this->allocationHeap.ProtectAllocationWithExecuteReadOnly(allocation->allocation))
+    if (!JITManager::GetJITManager()->IsJITServer() && !this->allocationHeap.ProtectAllocationWithExecuteReadOnly(allocation->allocation))
     {
         return false;
     }
@@ -573,5 +573,6 @@ EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::DumpAndResetStats(char
 template class EmitBufferManager<VirtualAllocWrapper, PreReservedVirtualAllocWrapper, FakeCriticalSection>;
 template class EmitBufferManager<VirtualAllocWrapper, PreReservedVirtualAllocWrapper, CriticalSection>;
 #if ENABLE_OOP_NATIVE_CODEGEN
+template class EmitBufferManager<SectionAllocWrapper, PreReservedSectionAllocWrapper, FakeCriticalSection>;
 template class EmitBufferManager<SectionAllocWrapper, PreReservedSectionAllocWrapper, CriticalSection>;
 #endif

+ 3 - 2
lib/Backend/EmitBuffer.h

@@ -44,7 +44,7 @@ public:
     TEmitBufferAllocation* AllocateBuffer(DECLSPEC_GUARD_OVERFLOW __in size_t bytes, __deref_bcount(bytes) BYTE** ppBuffer, ushort pdataCount = 0, ushort xdataSize = 0, bool canAllocInPreReservedHeapPageSegment = false, bool isAnyJittedCode = false);
     bool CommitBuffer(TEmitBufferAllocation* allocation, __out_bcount(bytes) BYTE* destBuffer, __in size_t bytes, __in_bcount(bytes) const BYTE* sourceBuffer, __in DWORD alignPad = 0);
     bool ProtectBufferWithExecuteReadWriteForInterpreter(TEmitBufferAllocation* allocation);
-    bool CommitReadWriteBufferForInterpreter(TEmitBufferAllocation* allocation, _In_reads_bytes_(bufferSize) BYTE* pBuffer, _In_ size_t bufferSize);
+    bool CommitBufferForInterpreter(TEmitBufferAllocation* allocation, _In_reads_bytes_(bufferSize) BYTE* pBuffer, _In_ size_t bufferSize);
     void CompletePreviousAllocation(TEmitBufferAllocation* allocation);
     bool FreeAllocation(void* address);
     //Ends here
@@ -99,5 +99,6 @@ public:
 typedef EmitBufferManager<VirtualAllocWrapper, PreReservedVirtualAllocWrapper, CriticalSection> InProcEmitBufferManagerWithlock;
 typedef EmitBufferManager<VirtualAllocWrapper, PreReservedVirtualAllocWrapper, FakeCriticalSection> InProcEmitBufferManager;
 #if ENABLE_OOP_NATIVE_CODEGEN
-typedef EmitBufferManager<SectionAllocWrapper, PreReservedSectionAllocWrapper, CriticalSection> OOPEmitBufferManager;
+typedef EmitBufferManager<SectionAllocWrapper, PreReservedSectionAllocWrapper, CriticalSection> OOPEmitBufferManagerWithLock;
+typedef EmitBufferManager<SectionAllocWrapper, PreReservedSectionAllocWrapper, FakeCriticalSection> OOPEmitBufferManager;
 #endif

+ 17 - 12
lib/Backend/InterpreterThunkEmitter.cpp

@@ -332,7 +332,7 @@ void InterpreterThunkEmitter::NewThunkBlock()
         &count
     );
 
-    if (!emitBufferManager.CommitReadWriteBufferForInterpreter(allocation, buffer, BlockSize))
+    if (!emitBufferManager.CommitBufferForInterpreter(allocation, buffer, BlockSize))
     {
         Js::Throw::OutOfMemory();
     }
@@ -723,11 +723,15 @@ InterpreterThunkEmitter::IsInHeap(void* address)
 #ifdef ENABLE_OOP_NATIVE_CODEGEN
     if (JITManager::GetJITManager()->IsOOPJITEnabled())
     {
-        auto findAddr = ([&](const ThunkBlock& block)
+        PSCRIPTCONTEXT_HANDLE remoteScript = this->scriptContext->GetRemoteScriptAddr(false);
+        if (!remoteScript)
         {
-            return block.Contains((BYTE*)address);
-        });
-        return thunkBlocks.Find(findAddr) != nullptr || freeListedThunkBlocks.Find(findAddr) != nullptr;
+            return false;
+        }
+        boolean result;
+        HRESULT hr = JITManager::GetJITManager()->IsInterpreterThunkAddr(remoteScript, (intptr_t)address, this->isAsmInterpreterThunk, &result);
+        JITManager::HandleServerCallResult(hr, RemoteCallType::HeapQuery);
+        return result != FALSE;
     }
     else
 #endif
@@ -750,15 +754,18 @@ void InterpreterThunkEmitter::Close()
     thunkBlocks.Iterate(unregisterPdata);
     freeListedThunkBlocks.Iterate(unregisterPdata);
 #endif
+
+    this->thunkBlocks.Clear(allocator);
+    this->freeListedThunkBlocks.Clear(allocator);
+
 #ifdef ENABLE_OOP_NATIVE_CODEGEN
     if (JITManager::GetJITManager()->IsOOPJITEnabled())
     {
-        auto unmapBlock = ([&](const ThunkBlock& block)
+        PSCRIPTCONTEXT_HANDLE remoteScript = this->scriptContext->GetRemoteScriptAddr(false);
+        if (remoteScript)
         {
-            NtdllLibrary::Instance->UnmapViewOfSection(GetCurrentProcess(), block.GetStart());
-        });
-        thunkBlocks.Iterate(unmapBlock);
-        freeListedThunkBlocks.Iterate(unmapBlock);
+            JITManager::GetJITManager()->DecommitInterpreterBufferManager(remoteScript, this->isAsmInterpreterThunk);
+        }
     }
     else
 #endif
@@ -766,8 +773,6 @@ void InterpreterThunkEmitter::Close()
         emitBufferManager.Decommit();
     }
 
-    this->thunkBlocks.Clear(allocator);
-    this->freeListedThunkBlocks.Clear(allocator);
 
     this->thunkBuffer = nullptr;
     this->thunkCount = 0;

+ 21 - 0
lib/Backend/ServerScriptContext.cpp

@@ -22,6 +22,8 @@ ServerScriptContext::ServerScriptContext(ScriptContextDataIDL * contextData, Ser
     threadContextHolder(threadContextInfo),
     m_isPRNGSeeded(false),
     m_sourceCodeArena(_u("JITSourceCodeArena"), threadContextInfo->GetForegroundPageAllocator(), Js::Throw::OutOfMemory, nullptr),
+    m_interpreterThunkBufferManager(&m_sourceCodeArena, threadContextInfo->GetThunkPageAllocators(), nullptr, _u("Interpreter thunk buffer"), GetThreadContext()->GetProcessHandle()),
+    m_asmJsInterpreterThunkBufferManager(&m_sourceCodeArena, threadContextInfo->GetThunkPageAllocators(), nullptr, _u("Asm.js interpreter thunk buffer"), GetThreadContext()->GetProcessHandle()),
     m_domFastPathHelperMap(nullptr),
     m_moduleRecords(&HeapAllocator::Instance),
     m_globalThisAddr(0),
@@ -309,6 +311,25 @@ ServerScriptContext::GetSourceCodeArena()
     return &m_sourceCodeArena;
 }
 
+void
+ServerScriptContext::DecommitEmitBufferManager(bool asmJsManager)
+{
+    GetEmitBufferManager(asmJsManager)->Decommit();
+}
+
+OOPEmitBufferManager *
+ServerScriptContext::GetEmitBufferManager(bool asmJsManager)
+{
+    if (asmJsManager)
+    {
+        return &m_asmJsInterpreterThunkBufferManager;
+    }
+    else
+    {
+        return &m_interpreterThunkBufferManager;
+    }
+}
+
 IR::JnHelperMethod
 ServerScriptContext::GetDOMFastPathHelper(intptr_t funcInfoAddr)
 {

+ 5 - 0
lib/Backend/ServerScriptContext.h

@@ -76,6 +76,8 @@ public:
     void SetIsPRNGSeeded(bool value);
     void AddModuleRecordInfo(unsigned int moduleId, __int64 localExportSlotsAddr);
     void UpdateGlobalObjectThisAddr(intptr_t globalThis);
+    OOPEmitBufferManager * GetEmitBufferManager(bool asmJsManager);
+    void DecommitEmitBufferManager(bool asmJsManager);
     Js::ScriptContextProfiler *  GetCodeGenProfiler() const;
     ServerThreadContext* GetThreadContext() { return threadContextHolder.threadContextInfo; }
 
@@ -91,6 +93,9 @@ private:
 #endif
     ArenaAllocator m_sourceCodeArena;
 
+    OOPEmitBufferManager m_interpreterThunkBufferManager;
+    OOPEmitBufferManager m_asmJsInterpreterThunkBufferManager;
+
     ScriptContextDataIDL m_contextData;
     intptr_t m_globalThisAddr;
 

+ 9 - 2
lib/Backend/ServerThreadContext.cpp

@@ -15,6 +15,7 @@ ServerThreadContext::ServerThreadContext(ThreadContextDataIDL * data) :
     m_numericPropertyBV(nullptr),
     m_preReservedSectionAllocator((HANDLE)data->processHandle),
     m_sectionAllocator((HANDLE)data->processHandle),
+    m_thunkPageAllocators(nullptr, /* allocXData */ false, &m_sectionAllocator, nullptr, (HANDLE)data->processHandle),
     m_codePageAllocators(nullptr, ALLOC_XDATA, &m_sectionAllocator, &m_preReservedSectionAllocator, (HANDLE)data->processHandle),
     m_codeGenAlloc(nullptr, nullptr, &m_codePageAllocators, (HANDLE)data->processHandle),
     m_pageAlloc(nullptr, Js::Configuration::Global.flags, PageAllocatorType_BGJIT,
@@ -111,7 +112,13 @@ ServerThreadContext::GetProcessHandle() const
     return reinterpret_cast<HANDLE>(m_threadContextData.processHandle);
 }
 
-CustomHeap::CodePageAllocators<SectionAllocWrapper, PreReservedSectionAllocWrapper>  *
+CustomHeap::OOPCodePageAllocators *
+ServerThreadContext::GetThunkPageAllocators()
+{
+    return &m_thunkPageAllocators;
+}
+
+CustomHeap::OOPCodePageAllocators *
 ServerThreadContext::GetCodePageAllocators()
 {
     return &m_codePageAllocators;
@@ -123,7 +130,7 @@ ServerThreadContext::GetSectionAllocator()
     return &m_sectionAllocator;
 }
 
-CodeGenAllocators<SectionAllocWrapper, PreReservedSectionAllocWrapper>  *
+OOPCodeGenAllocators *
 ServerThreadContext::GetCodeGenAllocators()
 {
     return &m_codeGenAlloc;

+ 4 - 2
lib/Backend/ServerThreadContext.h

@@ -38,7 +38,8 @@ public:
     ptrdiff_t GetCRTBaseAddressDifference() const;
 
     OOPCodeGenAllocators * GetCodeGenAllocators();
-    CustomHeap::CodePageAllocators<SectionAllocWrapper, PreReservedSectionAllocWrapper>  * GetCodePageAllocators();
+    CustomHeap::OOPCodePageAllocators * GetThunkPageAllocators();
+    CustomHeap::OOPCodePageAllocators  * GetCodePageAllocators();
     SectionAllocWrapper * GetSectionAllocator();
     void UpdateNumericPropertyBV(BVSparseNode * newProps);
     void SetWellKnownHostTypeId(Js::TypeId typeId) { this->wellKnownHostTypeHTMLAllCollectionTypeId = typeId; }
@@ -69,7 +70,8 @@ private:
 
     PreReservedSectionAllocWrapper m_preReservedSectionAllocator;
     SectionAllocWrapper m_sectionAllocator;
-    CustomHeap::CodePageAllocators<SectionAllocWrapper, PreReservedSectionAllocWrapper>  m_codePageAllocators;
+    CustomHeap::OOPCodePageAllocators m_thunkPageAllocators;
+    CustomHeap::OOPCodePageAllocators  m_codePageAllocators;
     OOPCodeGenAllocators m_codeGenAlloc;
     // only allocate with this from foreground calls (never from CodeGen calls)
     PageAllocator m_pageAlloc;

+ 46 - 0
lib/JITClient/JITManager.cpp

@@ -362,6 +362,27 @@ JITManager::SetIsPRNGSeeded(
 
 }
 
+HRESULT
+JITManager::DecommitInterpreterBufferManager(
+    __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
+    __in boolean asmJsThunk)
+{
+    Assert(IsOOPJITEnabled());
+
+    HRESULT hr = E_FAIL;
+    RpcTryExcept
+    {
+        hr = ClientDecommitInterpreterBufferManager(m_rpcBindingHandle, scriptContextInfoAddress, asmJsThunk);
+    }
+        RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
+    {
+        hr = HRESULT_FROM_WIN32(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return hr;
+}
+
 HRESULT
 JITManager::NewInterpreterThunkBlock(
     __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
@@ -577,3 +598,28 @@ JITManager::RemoteCodeGenCall(
 
     return hr;
 }
+
+#if DBG
+HRESULT
+JITManager::IsInterpreterThunkAddr(
+    __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
+    __in intptr_t address,
+    __in boolean asmjsThunk,
+    __out boolean * result)
+{
+    Assert(IsOOPJITEnabled());
+
+    HRESULT hr = E_FAIL;
+    RpcTryExcept
+    {
+        hr = ClientIsInterpreterThunkAddr(m_rpcBindingHandle, scriptContextInfoAddress, address, asmjsThunk, result);
+    }
+        RpcExcept(RpcExceptionFilter(RpcExceptionCode()))
+    {
+        hr = HRESULT_FROM_WIN32(RpcExceptionCode());
+    }
+    RpcEndExcept;
+
+    return hr;
+}
+#endif

+ 26 - 0
lib/JITClient/JITManager.h

@@ -42,6 +42,10 @@ public:
         __in PTHREADCONTEXT_HANDLE threadContextInfoAddress,
         __in_opt BVSparseNodeIDL * updatedPropsBVHead);
 
+    HRESULT DecommitInterpreterBufferManager(
+        __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
+        __in boolean asmJsThunk);
+
     HRESULT NewInterpreterThunkBlock(
         __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
         __in InterpreterThunkInputIDL * thunkInput,
@@ -90,6 +94,14 @@ public:
         __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
         __out JITOutputIDL *jitData);
 
+#if DBG
+    HRESULT IsInterpreterThunkAddr(
+        __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
+        __in intptr_t address,
+        __in boolean asmjsThunk,
+        __out boolean * result);
+#endif
+
     HRESULT Shutdown();
 
 
@@ -139,6 +151,11 @@ public:
         __out intptr_t *prereservedRegionAddr)
         { Assert(false); return E_FAIL; }
 
+    HRESULT DecommitInterpreterBufferManager(
+        __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
+        __in boolean asmJsThunk)
+        { Assert(false); return E_FAIL; }
+
     HRESULT CleanupThreadContext(
         __inout PPTHREADCONTEXT_HANDLE threadContextInfoAddress)
         { Assert(false); return E_FAIL; }
@@ -201,6 +218,15 @@ public:
         __out JITOutputIDL *jitData)
         { Assert(false); return E_FAIL; }
 
+#if DBG
+    HRESULT IsInterpreterThunkAddr(
+        __in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
+        __in intptr_t address,
+        __in boolean asmjsThunk,
+        __out boolean * result)
+        { Assert(false); return E_FAIL; }
+#endif
+
     HRESULT Shutdown()
         { Assert(false); return E_FAIL; }
 

+ 14 - 0
lib/JITIDL/ChakraJIT.idl

@@ -75,6 +75,11 @@ interface IChakraJIT
         [in] InterpreterThunkInputIDL * thunkInput,
         [out] InterpreterThunkOutputIDL * thunkOutput);
 
+    HRESULT DecommitInterpreterBufferManager(
+        [in] handle_t binding,
+        [in] PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
+        [in] boolean asmJsManager);
+
     HRESULT IsNativeAddr(
         [in] handle_t binding,
         [in] PTHREADCONTEXT_HANDLE threadContextInfoAddress,
@@ -91,4 +96,13 @@ interface IChakraJIT
         [in] PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
         [in] CodeGenWorkItemIDL * workItemData,
         [out] JITOutputIDL * jitData);
+
+#if DBG
+    HRESULT IsInterpreterThunkAddr(
+        [in] handle_t binding,
+        [in] PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
+        [in] CHAKRA_PTR address,
+        [in] boolean asmjsThunk,
+        [out] boolean * result);
+#endif
 }

+ 81 - 39
lib/JITServer/JITServer.cpp

@@ -366,6 +366,27 @@ ServerCloseScriptContext(
     });
 }
 
+HRESULT
+ServerDecommitInterpreterBufferManager(
+    /* [in] */ handle_t binding,
+    /* [in] */ __RPC__in PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
+    /* [in] */ boolean asmJsManager)
+{
+    ServerScriptContext * scriptContext = (ServerScriptContext *)DecodePointer((void*)scriptContextInfoAddress);
+
+    if (scriptContext == nullptr)
+    {
+        Assert(false);
+        return RPC_S_INVALID_ARG;
+    }
+
+    return ServerCallWrapper(scriptContext, [&]()->HRESULT
+    {
+        scriptContext->DecommitEmitBufferManager(asmJsManager != FALSE);
+        return S_OK;
+    });
+}
+
 HRESULT
 ServerNewInterpreterThunkBlock(
     /* [in] */ handle_t binding,
@@ -384,56 +405,50 @@ ServerNewInterpreterThunkBlock(
 
     return ServerCallWrapper(scriptContext, [&]()->HRESULT
     {
-        NtdllLibrary::OBJECT_ATTRIBUTES attr;
-        NtdllLibrary::Instance->InitializeObjectAttributes(&attr, NULL, NtdllLibrary::OBJ_KERNEL_HANDLE, NULL, NULL);
-        LARGE_INTEGER size = { 0 };
-#if TARGET_32
-        size.LowPart = InterpreterThunkEmitter::BlockSize;
-#elif TARGET_64
-        size.QuadPart = InterpreterThunkEmitter::BlockSize;
-#endif
-        HANDLE sectionHandle = nullptr;
-        int status = NtdllLibrary::Instance->CreateSection(&sectionHandle, SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY | SECTION_MAP_EXECUTE, &attr, &size, PAGE_EXECUTE_READWRITE, SEC_COMMIT, NULL);
-        if (status != 0)
-        {
-            Js::Throw::OutOfMemory();
-        }
-
-        DWORD thunkCount = 0;
-
-#if PDATA_ENABLED
-        PRUNTIME_FUNCTION pdataStart = {0};
-        intptr_t epilogEnd = 0;
-#endif
         ServerThreadContext * threadContext = scriptContext->GetThreadContext();
 
-        SIZE_T viewSize = 0;
-        LPVOID localBuffer = nullptr;
-        status = NtdllLibrary::Instance->MapViewOfSection(sectionHandle, GetCurrentProcess(), &localBuffer, NULL, NULL, NULL, &viewSize, NtdllLibrary::ViewUnmap, NULL, PAGE_READWRITE);
-        if (status != 0 || localBuffer == nullptr)
+        class AutoLocalAlloc
         {
-            NtdllLibrary::Instance->Close(sectionHandle);
-            Js::Throw::OutOfMemory();
-        }
+        public:
+            AutoLocalAlloc(ServerThreadContext * threadContext) : localAddress(nullptr), threadContext(threadContext) { }
+            ~AutoLocalAlloc()
+            {
+                if (localAddress)
+                {
+                    threadContext->GetCodePageAllocators()->FreeLocal(this->localAddress, this->segment);
+                }
+            }
+            char * localAddress;
+            void * segment;
+            ServerThreadContext * threadContext;
+        } localAlloc(threadContext);
+
+        OOPEmitBufferManager * emitBufferManager = scriptContext->GetEmitBufferManager(thunkInput->asmJsThunk != FALSE);
 
-        const DWORD allocProtectFlags = AutoSystemInfo::Data.IsCFGEnabled() ? PAGE_EXECUTE_RO_TARGETS_INVALID : PAGE_EXECUTE;
-        viewSize = 0;
-        LPVOID runtimeAddress = nullptr;
-        status = NtdllLibrary::Instance->MapViewOfSection(sectionHandle, threadContext->GetProcessHandle(), &runtimeAddress, NULL, NULL, NULL, &viewSize, NtdllLibrary::ViewUnmap, NULL, allocProtectFlags);
+        BYTE* runtimeAddress;
+        EmitBufferAllocation<SectionAllocWrapper, PreReservedSectionAllocWrapper> * alloc = emitBufferManager->AllocateBuffer(InterpreterThunkEmitter::BlockSize, &runtimeAddress);
 
-        NtdllLibrary::Instance->Close(sectionHandle);
-        if (status != 0 || runtimeAddress == nullptr)
+        CompileAssert(InterpreterThunkEmitter::BlockSize <= CustomHeap::Page::MaxAllocationSize);
+        localAlloc.segment = alloc->allocation->page->segment;
+
+        localAlloc.localAddress = threadContext->GetCodePageAllocators()->AllocLocal((char*)runtimeAddress, InterpreterThunkEmitter::BlockSize, localAlloc.segment);
+        if (!localAlloc.localAddress)
         {
-            NtdllLibrary::Instance->UnmapViewOfSection(GetCurrentProcess(), localBuffer);
             Js::Throw::OutOfMemory();
         }
 
+#if PDATA_ENABLED
+        PRUNTIME_FUNCTION pdataStart = {0};
+        intptr_t epilogEnd = 0;
+#endif
+        DWORD thunkCount = 0;
+
         InterpreterThunkEmitter::FillBuffer(
             threadContext,
             thunkInput->asmJsThunk != FALSE,
             (intptr_t)runtimeAddress,
             InterpreterThunkEmitter::BlockSize,
-            (BYTE*)localBuffer,
+            (BYTE*)localAlloc.localAddress,
 #if PDATA_ENABLED
             &pdataStart,
             &epilogEnd,
@@ -441,9 +456,7 @@ ServerNewInterpreterThunkBlock(
             &thunkCount
         );
 
-        NtdllLibrary::Instance->UnmapViewOfSection(GetCurrentProcess(), localBuffer);
-
-        FlushInstructionCache(threadContext->GetProcessHandle(), runtimeAddress, InterpreterThunkEmitter::BlockSize);
+        emitBufferManager->CommitBufferForInterpreter(alloc, runtimeAddress, InterpreterThunkEmitter::BlockSize);
         // Call to set VALID flag for CFG check
         if (CONFIG_FLAG(OOPCFGRegistration))
         {
@@ -461,6 +474,35 @@ ServerNewInterpreterThunkBlock(
     });
 }
 
+#if DBG
+HRESULT
+ServerIsInterpreterThunkAddr(
+    /* [in] */ handle_t binding,
+    /* [in] */ PSCRIPTCONTEXT_HANDLE scriptContextInfoAddress,
+    /* [in] */ intptr_t address,
+    /* [in] */ boolean asmjsThunk,
+    /* [out] */ __RPC__out boolean * result)
+{
+    ServerScriptContext * context = (ServerScriptContext*)DecodePointer((void*)scriptContextInfoAddress);
+
+    if (context == nullptr)
+    {
+        *result = false;
+        return RPC_S_INVALID_ARG;
+    }
+    OOPEmitBufferManager * manager = context->GetEmitBufferManager(asmjsThunk != FALSE);
+    if (manager == nullptr)
+    {
+        *result = false;
+        return S_OK;
+    }
+
+    *result = manager->IsInHeap((void*)address);
+
+    return S_OK;
+}
+#endif
+
 HRESULT
 ServerFreeAllocation(
     /* [in] */ handle_t binding,