Prechádzať zdrojové kódy

change OOP interpreter thunk emitter back to using EmitBufferManager

Michael Holman 9 rokov pred
rodič
commit
79b9dfef06

+ 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();
     }
@@ -727,11 +727,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
@@ -754,15 +758,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
@@ -770,8 +777,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

@@ -36,7 +36,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; }
@@ -67,7 +68,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

@@ -70,6 +70,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,
@@ -86,4 +91,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

@@ -365,6 +365,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,
@@ -383,56 +404,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,
@@ -440,9 +455,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))
         {
@@ -460,6 +473,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,