SourceDynamicProfileManager * SourceDynamicProfileManager::Deserialize(T * reader, Recycler* recycler) { uint functionCount; if (!reader->Peek(&functionCount)) { return nullptr; } BVFixed * startupFunctions = BVFixed::New(functionCount, recycler); if (!reader->ReadArray(((char *)startupFunctions), BVFixed::GetAllocSize(functionCount))) { return nullptr; } uint profileCount; if (!reader->Read(&profileCount)) { return nullptr; } ThreadContext* threadContext = ThreadContext::GetContextForCurrentThread(); SourceDynamicProfileManager * sourceDynamicProfileManager = RecyclerNew(threadContext->GetRecycler(), SourceDynamicProfileManager, recycler); sourceDynamicProfileManager->cachedStartupFunctions = startupFunctions; #if DBG_DUMP if(Configuration::Global.flags.Dump.IsEnabled(DynamicProfilePhase)) { Output::Print(L"Loaded: Startup functions bit vector:"); startupFunctions->Dump(); } #endif for (uint i = 0; i < profileCount; i++) { Js::LocalFunctionId functionId; DynamicProfileInfo * dynamicProfileInfo = DynamicProfileInfo::Deserialize(reader, recycler, &functionId); if (dynamicProfileInfo == nullptr || functionId >= functionCount) { return nullptr; } sourceDynamicProfileManager->dynamicProfileInfoMap.Add(functionId, dynamicProfileInfo); } return sourceDynamicProfileManager; }
// Recover/Release unused memory and give it back to OS. // The function doesn't throw if the attempt to recover memory fails, in which case it simply does nothing. // Useful when running out of memory e.g. for Arena but there is some recycler memory which has been committed but is unused. void Exception::RecoverUnusedMemory() { ThreadContext* threadContext = ThreadContext::GetContextForCurrentThread(); if (threadContext) { Recycler* threadRecycler = threadContext->GetRecycler(); if (threadRecycler) { try { threadRecycler->CollectNow<CollectOnRecoverFromOutOfMemory>(); } catch (...) { // Technically, exception is a valid scenario: we asked to recover mem, and it couldn't. // Do not let the exception leak out. } } } }
void Utf8SourceInfo::EnsureInitialized(int initialFunctionCount) { ThreadContext* threadContext = ThreadContext::GetContextForCurrentThread(); Recycler* recycler = threadContext->GetRecycler(); if (this->functionBodyDictionary == nullptr) { // This collection is allocated with leaf allocation policy. The references to the function body // here does not keep the function alive. However, the functions remove themselves at finalize // so if a function actually is in this map, it means that it is alive. this->functionBodyDictionary = RecyclerNew(recycler, FunctionBodyDictionary, recycler, initialFunctionCount, threadContext->GetEtwRundownCriticalSection()); } if (CONFIG_FLAG(DeferTopLevelTillFirstCall) && !m_deferredFunctionsInitialized) { Assert(this->m_deferredFunctionsDictionary == nullptr); this->m_deferredFunctionsDictionary = RecyclerNew(recycler, DeferredFunctionsDictionary, recycler, initialFunctionCount, threadContext->GetEtwRundownCriticalSection()); m_deferredFunctionsInitialized = true; } }
/* static */ bool JsrtContext::TrySetCurrent(JsrtContext * context) { Assert(s_tlsSlot != TLS_OUT_OF_INDEXES); ThreadContext * threadContext; //We are not pinning the context after SetCurrentContext, so if the context is not pinned //it might be reclaimed half way during execution. In jsrtshell the runtime was optimized out //at time of JsrtContext::Run by the compiler. //The change is to pin the context at setconcurrentcontext, and unpin the previous one. In //JsDisposeRuntime we'll reject if current context is active, so that will make sure all //contexts are unpinned at time of JsDisposeRuntime. if (context != nullptr) { threadContext = context->GetScriptContext()->GetThreadContext(); if (!ThreadContextTLSEntry::TrySetThreadContext(threadContext)) { return false; } threadContext->GetRecycler()->RootAddRef((LPVOID)context); } else { if (!ThreadContextTLSEntry::ClearThreadContext(true)) { return false; } } JsrtContext* originalContext = (JsrtContext*) TlsGetValue(s_tlsSlot); if (originalContext != nullptr) { originalContext->GetScriptContext()->GetRecycler()->RootRelease((LPVOID) originalContext); } TlsSetValue(s_tlsSlot, context); return true; }
Js::ScriptContext* JsrtContextCore::EnsureScriptContext() { Assert(this->GetJavascriptLibrary() == nullptr); ThreadContext* localThreadContext = this->GetRuntime()->GetThreadContext(); AutoPtr<Js::ScriptContext> newScriptContext(Js::ScriptContext::New(localThreadContext)); newScriptContext->Initialize(); hostContext = HeapNew(ChakraCoreHostScriptContext, newScriptContext); newScriptContext->SetHostScriptContext(hostContext); this->SetJavascriptLibrary(newScriptContext.Detach()->GetLibrary()); Js::JavascriptLibrary *library = this->GetScriptContext()->GetLibrary(); Assert(library != nullptr); localThreadContext->GetRecycler()->RootRelease(library->GetGlobalObject()); library->GetEvalFunctionObject()->SetEntryPoint(&Js::GlobalObject::EntryEval); library->GetFunctionConstructor()->SetEntryPoint(&Js::JavascriptFunction::NewInstance); return this->GetScriptContext(); }