HRESULT ServerFreeAllocation( /* [in] */ handle_t binding, /* [in] */ intptr_t threadContextInfo, /* [in] */ intptr_t address) { AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); ServerThreadContext * context = (ServerThreadContext*)DecodePointer((void*)threadContextInfo); if (context == nullptr) { Assert(false); return RPC_S_INVALID_ARG; } if (!ServerContextManager::IsThreadContextAlive(context)) { Assert(false); return E_ACCESSDENIED; } return ServerCallWrapper(context, [&]()->HRESULT { AutoReleaseContext<ServerThreadContext> autoThreadContext(context); context->SetValidCallTargetForCFG((PVOID)address, false); context->GetCodeGenAllocators()->emitBufferManager.FreeAllocation((void*)address); return S_OK; }); }
HRESULT ServerAddModuleRecordInfo( /* [in] */ handle_t binding, /* [in] */ intptr_t scriptContextInfoAddress, /* [in] */ unsigned int moduleId, /* [in] */ intptr_t localExportSlotsAddr) { AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); ServerScriptContext * serverScriptContext = (ServerScriptContext*)DecodePointer((void*)scriptContextInfoAddress); if (serverScriptContext == nullptr) { Assert(false); return RPC_S_INVALID_ARG; } if (!ServerContextManager::IsScriptContextAlive(serverScriptContext)) { Assert(false); return E_ACCESSDENIED; } AutoReleaseContext<ServerScriptContext> autoScriptContext(serverScriptContext); return ServerCallWrapper(serverScriptContext, [&]()->HRESULT { serverScriptContext->AddModuleRecordInfo(moduleId, localExportSlotsAddr); return S_OK; }); }
HRESULT ServerAddDOMFastPathHelper( /* [in] */ handle_t binding, /* [in] */ intptr_t scriptContextRoot, /* [in] */ intptr_t funcInfoAddr, /* [in] */ int helper) { AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer((void*)scriptContextRoot); if (scriptContextInfo == nullptr) { Assert(false); return RPC_S_INVALID_ARG; } if (!ServerContextManager::IsScriptContextAlive(scriptContextInfo)) { Assert(false); return E_ACCESSDENIED; } AutoReleaseContext<ServerScriptContext> autoScriptContext(scriptContextInfo); return ServerCallWrapper(scriptContextInfo, [&]()->HRESULT { scriptContextInfo->AddToDOMFastPathHelperMap(funcInfoAddr, (IR::JnHelperMethod)helper); return S_OK; }); }
HRESULT ServerInitializeThreadContext( /* [in] */ handle_t binding, /* [in] */ __RPC__in ThreadContextDataIDL * threadContextData, /* [out] */ __RPC__out intptr_t *threadContextRoot, /* [out] */ __RPC__out intptr_t *prereservedRegionAddr) { AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); ServerThreadContext * contextInfo = HeapNewNoThrow(ServerThreadContext, threadContextData); if (contextInfo == nullptr) { return E_OUTOFMEMORY; } AutoReleaseContext<ServerThreadContext> autoThreadContext(contextInfo); return ServerCallWrapper(contextInfo, [&]()->HRESULT { ServerContextManager::RegisterThreadContext(contextInfo); *threadContextRoot = (intptr_t)EncodePointer(contextInfo); *prereservedRegionAddr = (intptr_t)contextInfo->GetPreReservedVirtualAllocator()->EnsurePreReservedRegion(); return S_OK; }); }
HRESULT ServerInitializeScriptContext( /* [in] */ handle_t binding, /* [in] */ __RPC__in ScriptContextDataIDL * scriptContextData, /* [in] */ intptr_t threadContextInfoAddress, /* [out] */ __RPC__out intptr_t * scriptContextInfoAddress) { AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer((void*)threadContextInfoAddress); if (threadContextInfo == nullptr) { Assert(false); *scriptContextInfoAddress = 0; return RPC_S_INVALID_ARG; } if (!ServerContextManager::IsThreadContextAlive(threadContextInfo)) { Assert(false); *scriptContextInfoAddress = 0; return E_ACCESSDENIED; } return ServerCallWrapper(threadContextInfo, [&]()->HRESULT { ServerScriptContext * contextInfo = HeapNew(ServerScriptContext, scriptContextData, threadContextInfo); ServerContextManager::RegisterScriptContext(contextInfo); *scriptContextInfoAddress = (intptr_t)EncodePointer(contextInfo); #if !FLOATVAR // TODO: should move this to ServerInitializeThreadContext, also for the fields in IDL XProcNumberPageSegmentImpl::Initialize(contextInfo->IsRecyclerVerifyEnabled(), contextInfo->GetRecyclerVerifyPad()); #endif return S_OK; }); }
ArenaMemoryData * MemoryProfiler::Begin(LPCWSTR name) { if (!Js::Configuration::Global.flags.IsEnabled(Js::TraceMemoryFlag)) { return nullptr; } Assert(name != nullptr); if (wcscmp(name, _u("MemoryProfiler")) == 0) { // Don't profile memory profiler itself return nullptr; } // This is debug only code, we don't care if we catch the right exception AUTO_NESTED_HANDLED_EXCEPTION_TYPE(ExceptionType_DisableCheck); MemoryProfiler * memoryProfiler = EnsureMemoryProfiler(); ArenaMemoryDataSummary * arenaTotalMemoryData; if (!memoryProfiler->arenaDataMap.TryGetValue((LPWSTR)name, &arenaTotalMemoryData)) { arenaTotalMemoryData = AnewStructZ(&memoryProfiler->alloc, ArenaMemoryDataSummary); memoryProfiler->arenaDataMap.Add((LPWSTR)name, arenaTotalMemoryData); } arenaTotalMemoryData->arenaCount++; ArenaMemoryData * memoryData = AnewStructZ(&memoryProfiler->alloc, ArenaMemoryData); if (arenaTotalMemoryData->data == nullptr) { arenaTotalMemoryData->data = memoryData; } else { memoryData->next = arenaTotalMemoryData->data; arenaTotalMemoryData->data->prev = memoryData; arenaTotalMemoryData->data = memoryData; } memoryData->profiler = memoryProfiler; return memoryData; }
HRESULT ServerCleanupThreadContext( /* [in] */ handle_t binding, /* [in] */ intptr_t threadContextRoot) { AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer((void*)threadContextRoot); if (threadContextInfo == nullptr) { Assert(false); return RPC_S_INVALID_ARG; } if (ServerContextManager::IsThreadContextAlive(threadContextInfo)) { AutoReleaseContext<ServerThreadContext> autoThreadContext(threadContextInfo); threadContextInfo->Close(); ServerContextManager::UnRegisterThreadContext(threadContextInfo); } return S_OK; }
HRESULT ServerUpdatePropertyRecordMap( /* [in] */ handle_t binding, /* [in] */ intptr_t threadContextInfoAddress, /* [in] */ __RPC__in UpdatedPropertysIDL * updatedProps) { AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); ServerThreadContext * threadContextInfo = (ServerThreadContext*)DecodePointer((void*)threadContextInfoAddress); if (threadContextInfo == nullptr) { Assert(false); return RPC_S_INVALID_ARG; } if (!ServerContextManager::IsThreadContextAlive(threadContextInfo)) { Assert(false); return E_ACCESSDENIED; } AutoReleaseContext<ServerThreadContext> autoThreadContext(threadContextInfo); return ServerCallWrapper(threadContextInfo, [&]()->HRESULT { for (uint i = 0; i < updatedProps->reclaimedPropertyCount; ++i) { threadContextInfo->RemoveFromPropertyMap((Js::PropertyId)updatedProps->reclaimedPropertyIdArray[i]); } for (uint i = 0; i < updatedProps->newRecordCount; ++i) { threadContextInfo->AddToPropertyMap((Js::PropertyRecord *)updatedProps->newRecordArray[i]); } return S_OK; }); }
HRESULT ServerRemoteCodeGen( /* [in] */ handle_t binding, /* [in] */ intptr_t scriptContextInfoAddress, /* [in] */ __RPC__in CodeGenWorkItemIDL *workItemData, /* [out] */ __RPC__out JITOutputIDL *jitData) { AUTO_NESTED_HANDLED_EXCEPTION_TYPE(static_cast<ExceptionType>(ExceptionType_OutOfMemory | ExceptionType_StackOverflow)); LARGE_INTEGER start_time = { 0 }; if (PHASE_TRACE1(Js::BackEndPhase)) { QueryPerformanceCounter(&start_time); } memset(jitData, 0, sizeof(JITOutputIDL)); ServerScriptContext * scriptContextInfo = (ServerScriptContext*)DecodePointer((void*)scriptContextInfoAddress); if (scriptContextInfo == nullptr) { Assert(false); return RPC_S_INVALID_ARG; } if (!ServerContextManager::IsScriptContextAlive(scriptContextInfo)) { Assert(false); return E_ACCESSDENIED; } AutoReleaseContext<ServerScriptContext> autoScriptContext(scriptContextInfo); return ServerCallWrapper(scriptContextInfo, [&]() ->HRESULT { scriptContextInfo->UpdateGlobalObjectThisAddr(workItemData->globalThisAddr); ServerThreadContext * threadContextInfo = scriptContextInfo->GetThreadContext(); NoRecoverMemoryJitArenaAllocator jitArena(L"JITArena", threadContextInfo->GetPageAllocator(), Js::Throw::OutOfMemory); JITTimeWorkItem * jitWorkItem = Anew(&jitArena, JITTimeWorkItem, workItemData); if (PHASE_VERBOSE_TRACE_RAW(Js::BackEndPhase, jitWorkItem->GetJITTimeInfo()->GetSourceContextId(), jitWorkItem->GetJITTimeInfo()->GetLocalFunctionId())) { LARGE_INTEGER freq; LARGE_INTEGER end_time; QueryPerformanceCounter(&end_time); QueryPerformanceFrequency(&freq); Output::Print( L"BackendMarshalIn - function: %s time:%8.6f mSec\r\n", jitWorkItem->GetJITFunctionBody()->GetDisplayName(), (((double)((end_time.QuadPart - workItemData->startTime)* (double)1000.0 / (double)freq.QuadPart))) / (1)); Output::Flush(); } auto profiler = scriptContextInfo->GetCodeGenProfiler(); #ifdef PROFILE_EXEC if (profiler && !profiler->IsInitialized()) { profiler->Initialize(threadContextInfo->GetPageAllocator(), nullptr); } #endif if (jitWorkItem->GetWorkItemData()->xProcNumberPageSegment) { jitData->numberPageSegments = (XProcNumberPageSegment*)midl_user_allocate(sizeof(XProcNumberPageSegment)); if (!jitData->numberPageSegments) { return E_OUTOFMEMORY; } __analysis_assume(jitData->numberPageSegments); memcpy_s(jitData->numberPageSegments, sizeof(XProcNumberPageSegment), jitWorkItem->GetWorkItemData()->xProcNumberPageSegment, sizeof(XProcNumberPageSegment)); } Func::Codegen( &jitArena, jitWorkItem, threadContextInfo, scriptContextInfo, jitData, nullptr, nullptr, jitWorkItem->GetPolymorphicInlineCacheInfo(), threadContextInfo->GetCodeGenAllocators(), #if !FLOATVAR nullptr, // number allocator #endif profiler, true); #ifdef PROFILE_EXEC if (profiler && profiler->IsInitialized()) { profiler->ProfilePrint(Js::Configuration::Global.flags.Profile.GetFirstPhase()); } #endif if (PHASE_VERBOSE_TRACE_RAW(Js::BackEndPhase, jitWorkItem->GetJITTimeInfo()->GetSourceContextId(), jitWorkItem->GetJITTimeInfo()->GetLocalFunctionId())) { LARGE_INTEGER freq; LARGE_INTEGER end_time; QueryPerformanceCounter(&end_time); QueryPerformanceFrequency(&freq); Output::Print( L"EndBackEndInner - function: %s time:%8.6f mSec\r\n", jitWorkItem->GetJITFunctionBody()->GetDisplayName(), (((double)((end_time.QuadPart - start_time.QuadPart)* (double)1000.0 / (double)freq.QuadPart))) / (1)); Output::Flush(); } LARGE_INTEGER out_time = { 0 }; if (PHASE_TRACE1(Js::BackEndPhase)) { QueryPerformanceCounter(&out_time); jitData->startTime = out_time.QuadPart; } return S_OK; }); }
void ThreadBoundThreadContextManager::DestroyAllContexts() { #if ENABLE_BACKGROUND_JOB_PROCESSOR JsUtil::BackgroundJobProcessor * jobProcessor = NULL; #endif { AutoCriticalSection lock(ThreadContext::GetCriticalSection()); ThreadContextTLSEntry * currentEntry = ThreadContextTLSEntry::GetEntryForCurrentThread(); if (currentEntry == NULL) { // We need a current thread entry so that we can use it to release any thread contexts // we find below. try { AUTO_NESTED_HANDLED_EXCEPTION_TYPE(ExceptionType_OutOfMemory); currentEntry = ThreadContextTLSEntry::CreateEntryForCurrentThread(); entries.Prepend(currentEntry); } catch (Js::OutOfMemoryException) { return; } } else { // We need to clear out the current thread entry so that we can use it to release any // thread contexts we find below. ThreadContext * threadContext = static_cast<ThreadContext *>(currentEntry->GetThreadContext()); if (threadContext != NULL) { if (threadContext->IsThreadBound()) { ShutdownThreadContext(threadContext); ThreadContextTLSEntry::ClearThreadContext(currentEntry, false); } else { ThreadContextTLSEntry::ClearThreadContext(currentEntry, true); } } } EntryList::Iterator iter(&entries); while (iter.Next()) { ThreadContextTLSEntry * entry = iter.Data(); ThreadContext * threadContext = static_cast<ThreadContext *>(entry->GetThreadContext()); if (threadContext != nullptr) { // Found a thread context. Remove it from the containing entry. ThreadContextTLSEntry::ClearThreadContext(entry, true); // Now set it to our thread's entry. ThreadContextTLSEntry::SetThreadContext(currentEntry, threadContext); // Clear it out. ShutdownThreadContext(threadContext); // Now clear it out of our entry. ThreadContextTLSEntry::ClearThreadContext(currentEntry, false); } } // We can only clean up our own TLS entry, so we're going to go ahead and do that here. entries.Remove(currentEntry); ThreadContextTLSEntry::CleanupThread(); #if ENABLE_BACKGROUND_JOB_PROCESSOR if (s_sharedJobProcessor != NULL) { jobProcessor = s_sharedJobProcessor; s_sharedJobProcessor = NULL; jobProcessor->Close(); } #endif } #if ENABLE_BACKGROUND_JOB_PROCESSOR if (jobProcessor != NULL) { HeapDelete(jobProcessor); } #endif }