| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- namespace Js
- {
- class ScriptContext;
- struct InlineCache;
- class CodeGenRecyclableData;
- #ifdef ENABLE_SCRIPT_DEBUGGING
- class DebugManager;
- struct ReturnedValue;
- typedef JsUtil::List<ReturnedValue*> ReturnedValueList;
- #endif
- class DelayedFreeArrayBuffer;
- }
- typedef BVSparse<ArenaAllocator> ActiveFunctionSet;
- using namespace PlatformAgnostic;
- struct IAuthorFileContext;
- class HostScriptContext;
- class ScriptSite;
- class ThreadServiceWrapper;
- struct IActiveScriptProfilerHeapEnum;
- class DynamicProfileMutator;
- class StackProber;
- enum DisableImplicitFlags : BYTE
- {
- DisableImplicitNoFlag = 0x00,
- DisableImplicitCallFlag = 0x01,
- DisableImplicitExceptionFlag = 0x02,
- DisableImplicitCallAndExceptionFlag = DisableImplicitCallFlag | DisableImplicitExceptionFlag
- };
- enum ThreadContextFlags
- {
- ThreadContextFlagNoFlag = 0x00000000,
- ThreadContextFlagCanDisableExecution = 0x00000001,
- ThreadContextFlagEvalDisabled = 0x00000002,
- ThreadContextFlagNoJIT = 0x00000004,
- ThreadContextFlagDisableFatalOnOOM = 0x00000008,
- ThreadContextFlagNoDynamicThunks = 0x00000010,
- };
- const int LS_MAX_STACK_SIZE_KB = 300;
- struct IProjectionContext
- {
- public:
- virtual HRESULT Close() = 0;
- };
- class ThreadContext;
- class InterruptPoller
- {
- // Interface with a polling object located in the hosting layer.
- public:
- InterruptPoller(ThreadContext *tc);
- virtual ~InterruptPoller() { }
- void CheckInterruptPoll();
- void GetStatementCount(ULONG *pluHi, ULONG *pluLo);
- void ResetStatementCount() { lastResetTick = lastPollTick; }
- void StartScript() { lastResetTick = lastPollTick = ::GetTickCount(); }
- void EndScript() { lastResetTick = lastPollTick = 0;}
- bool IsDisabled() const { return isDisabled; }
- void SetDisabled(bool disable) { isDisabled = disable; }
- virtual void TryInterruptPoll(Js::ScriptContext *scriptContext) = 0;
- // Default: throw up QC dialog after 5M statements == 2 minutes
- static const DWORD TicksToStatements = (5000000 / 120000);
- protected:
- ThreadContext *threadContext;
- DWORD lastPollTick;
- DWORD lastResetTick;
- bool isDisabled;
- };
- #define PROBE_STACK(scriptContext, size) ((scriptContext)->GetThreadContext()->ProbeStack(size, scriptContext))
- #define PROBE_STACK_NO_DISPOSE(scriptContext, size) ((scriptContext)->GetThreadContext()->ProbeStackNoDispose(size, scriptContext))
- #define PROBE_STACK_PARTIAL_INITIALIZED_INTERPRETER_FRAME(scriptContext, size) ((scriptContext)->GetThreadContext()->ProbeStack(size, scriptContext, _ReturnAddress()))
- #define PROBE_STACK_PARTIAL_INITIALIZED_BAILOUT_FRAME(scriptContext, size, returnAddress) ((scriptContext)->GetThreadContext()->ProbeStack(size, scriptContext, returnAddress))
- #define PROBE_STACK_CALL(scriptContext, obj, size) ((scriptContext)->GetThreadContext()->ProbeStack(size, obj, scriptContext))
- #define AssertInScript() Assert(ThreadContext::GetContextForCurrentThread()->IsScriptActive());
- #define AssertNotInScript() Assert(!ThreadContext::GetContextForCurrentThread()->IsScriptActive());
- #define LEAVE_SCRIPT_START_EX(scriptContext, stackProbe, leaveForHost, isFPUControlRestoreNeeded) \
- { \
- void * __frameAddr = nullptr; \
- GET_CURRENT_FRAME_ID(__frameAddr); \
- Js::LeaveScriptObject<stackProbe, leaveForHost, isFPUControlRestoreNeeded> __leaveScriptObject(scriptContext, __frameAddr); \
- AutoReentrancyHandler autoReentrancyHandler(scriptContext->GetThreadContext());
- #define LEAVE_SCRIPT_END_EX(scriptContext) \
- if (scriptContext != nullptr) \
- { \
- scriptContext->GetThreadContext()->DisposeOnLeaveScript(); \
- }\
- }
- #define LEAVE_SCRIPT_IF_ACTIVE(scriptContext, externalCall) \
- if (scriptContext->GetThreadContext()->IsScriptActive()) \
- { \
- BEGIN_LEAVE_SCRIPT(scriptContext); \
- externalCall \
- END_LEAVE_SCRIPT(scriptContext); \
- } \
- else \
- { \
- DECLARE_EXCEPTION_CHECK_DATA \
- SAVE_EXCEPTION_CHECK \
- externalCall \
- RESTORE_EXCEPTION_CHECK \
- }
- #define ENTER_SCRIPT_IF(scriptContext, doCleanup, isCallRoot, hasCaller, condition, block) \
- if (condition) \
- { \
- BEGIN_ENTER_SCRIPT(scriptContext, doCleanup, isCallRoot, hasCaller); \
- block \
- END_ENTER_SCRIPT(scriptContext, doCleanup, isCallRoot, hasCaller); \
- } \
- else \
- { \
- block \
- }
- #define BEGIN_LEAVE_SCRIPT(scriptContext) \
- LEAVE_SCRIPT_START_EX(scriptContext, /* stackProbe */ true, /* leaveForHost */ true, /* isFPUControlRestoreNeeded */ false)
- #define BEGIN_LEAVE_SCRIPT_SAVE_FPU_CONTROL(scriptContext) \
- LEAVE_SCRIPT_START_EX(scriptContext, /* stackProbe */ true, /* leaveForHost */ true, /* isFPUControlRestoreNeeded */ true)
- // BEGIN_LEAVE_SCRIPT_INTERNAL is used when there are no explicit external call after leave script,
- // but we might have external call when allocation memory doing QC or GC Dispose, which may enter script again.
- // This will record the reentry as an implicit call (ImplicitCall_AsyncHostOperation)
- #define BEGIN_LEAVE_SCRIPT_INTERNAL(scriptContext) \
- LEAVE_SCRIPT_START_EX(scriptContext, /* stackProbe */ true, /* leaveForHost */ false, /* isFPUControlRestoreNeeded */ false)
- #define BEGIN_LEAVE_SCRIPT_NO_STACK_PROBE(scriptContext) \
- LEAVE_SCRIPT_START_EX(scriptContext, /* stackProbe */ false, /* leaveForHost */ true, /* isFPUControlRestoreNeeded */ false)
- #define END_LEAVE_SCRIPT(scriptContext) \
- LEAVE_SCRIPT_END_EX(scriptContext)
- #define END_LEAVE_SCRIPT_RESTORE_FPU_CONTROL(scriptContext) \
- LEAVE_SCRIPT_END_EX(scriptContext)
- #define END_LEAVE_SCRIPT_INTERNAL(scriptContext) \
- LEAVE_SCRIPT_END_EX(scriptContext)
- #define END_LEAVE_SCRIPT_NO_STACK_PROBE(scriptContext) \
- LEAVE_SCRIPT_END_EX(scriptContext)
- #define BEGIN_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext) \
- BEGIN_LEAVE_SCRIPT(scriptContext)
- #define END_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext) \
- Assert(!scriptContext->HasRecordedException()); \
- END_LEAVE_SCRIPT(scriptContext)
- #define BEGIN_SAFE_REENTRANT_CALL(threadContext) \
- { \
- AutoReentrancyHandler autoReentrancyHandler(threadContext);
- #define END_SAFE_REENTRANT_CALL }
- #define BEGIN_SAFE_REENTRANT_REGION(threadContext) \
- { \
- AutoReentrancySafeRegion autoReentrancySafeRegion(threadContext);
- #define END_SAFE_REENTRANT_REGION }
- // Keep in sync with CollectGarbageCallBackFlags in scriptdirect.idl
- enum RecyclerCollectCallBackFlags
- {
- Collect_Begin = 0x01,
- Collect_Begin_Concurrent = 0x11,
- Collect_Begin_Partial = 0x21,
- Collect_Begin_Concurrent_Partial = Collect_Begin_Concurrent | Collect_Begin_Partial,
- Collect_End = 0x02,
- Collect_Wait = 0x04 // callback can be from another thread
- };
- typedef void (__cdecl *RecyclerCollectCallBackFunction)(void * context, RecyclerCollectCallBackFlags flags);
- #ifdef ENABLE_PROJECTION
- class ExternalWeakReferenceCache
- {
- public:
- virtual void MarkNow(Recycler *recycler, bool inPartialCollect) = 0;
- virtual void ResolveNow(Recycler *recycler) = 0;
- };
- #if DBG_DUMP
- class IProjectionContextMemoryInfo abstract
- {
- public:
- virtual void DumpCurrentStats(LPCWSTR headerMsg, bool forceDetailed) = 0;
- virtual void Release() = 0;
- };
- #endif
- #endif
- #ifdef NTBUILD
- struct ThreadContextWatsonTelemetryBlock
- {
- FILETIME lastScriptStartTime;
- FILETIME lastScriptEndTime;
- };
- #endif
- class NativeLibraryEntryRecord
- {
- public:
- struct Entry
- {
- Js::RecyclableObject* function;
- Js::CallInfo callInfo;
- PCWSTR name;
- PVOID addr;
- Entry* next;
- };
- private:
- Entry* head;
- public:
- NativeLibraryEntryRecord() : head(nullptr)
- {
- }
- const Entry* Peek() const
- {
- return head;
- }
- void Push(_In_ Entry* e)
- {
- e->next = head;
- head = e;
- }
- void Pop()
- {
- head = head->next;
- }
- };
- class AutoTagNativeLibraryEntry
- {
- private:
- NativeLibraryEntryRecord::Entry entry;
- public:
- AutoTagNativeLibraryEntry(Js::RecyclableObject* function, Js::CallInfo callInfo, PCWSTR name, void* addr);
- ~AutoTagNativeLibraryEntry();
- };
- #define AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, name) \
- AutoTagNativeLibraryEntry __tag(function, callInfo, name, _AddressOfReturnAddress())
- class ThreadConfiguration
- {
- public:
- ThreadConfiguration(bool enableExperimentalFeatures)
- {
- CopyGlobalFlags();
- if (enableExperimentalFeatures)
- {
- EnableExperimentalFeatures();
- ResetExperimentalFeaturesFromConfig();
- }
- }
- #define DEFINE_FLAG(threadFlag, globalFlag) \
- public: \
- inline bool threadFlag() const { return m_##globalFlag##; } \
- \
- private: \
- bool m_##globalFlag##;
- #define FLAG(threadFlag, globalFlag) DEFINE_FLAG(threadFlag, globalFlag)
- #define FLAG_RELEASE(threadFlag, globalFlag) DEFINE_FLAG(threadFlag, globalFlag)
- #include "ThreadConfigFlagsList.h"
- #undef FLAG_RELEASE
- #undef FLAG
- #undef DEFINE_FLAG
- private:
- void CopyGlobalFlags()
- {
- AutoCriticalSection autocs(&Js::Configuration::Global.flags.csExperimentalFlags);
- #define FLAG(threadFlag, globalFlag) m_##globalFlag## = CONFIG_FLAG(globalFlag);
- #define FLAG_RELEASE(threadFlag, globalFlag) m_##globalFlag## = CONFIG_FLAG_RELEASE(globalFlag);
- #include "ThreadConfigFlagsList.h"
- #undef FLAG_RELEASE
- #undef FLAG
- }
- void EnableExperimentalFeatures()
- {
- // If a ES6 flag is disabled using compile flag don't enable it
- #define FLAG_REGOVR_EXP(type, name, ...) m_##name## = COMPILE_DISABLE_##name## ? false : true;
- #include "ConfigFlagsList.h"
- #undef FLAG_REGOVR_EXP
- }
- void ResetExperimentalFeaturesFromConfig()
- {
- // If a flag was overridden using config/command line it should take precedence
- #define FLAG_REGOVR_EXP(type, name, ...) if(CONFIG_ISENABLED(Js::Flag::##name##Flag)) { m_##name## = CONFIG_FLAG_RELEASE(##name##); }
- #include "ConfigFlagsList.h"
- #undef FLAG_REGOVR_EXP
- }
- };
- class AutoReentrancyHandler;
- class ThreadContext sealed :
- public DefaultRecyclerCollectionWrapper,
- public JsUtil::DoublyLinkedListElement<ThreadContext>,
- public ThreadContextInfo
- {
- public:
- static void GlobalInitialize();
- static const DWORD NoThread = 0xFFFFFFFF;
- struct CollectCallBack
- {
- RecyclerCollectCallBackFunction callback;
- void * context;
- };
- struct WorkerThread
- {
- // Abstract notion to hold onto threadHandle of worker thread
- HANDLE threadHandle;
- WorkerThread(HANDLE handle = nullptr) :threadHandle(handle){};
- };
- void SetCurrentThreadId(DWORD threadId) { this->currentThreadId = threadId; }
- DWORD GetCurrentThreadId() const { return this->currentThreadId; }
- void SetIsThreadBound()
- {
- if (this->recycler)
- {
- this->recycler->SetIsThreadBound();
- }
- this->isThreadBound = true;
- }
- bool IsJSRT() const { return !this->isThreadBound; }
- virtual bool IsThreadBound() const override { return this->isThreadBound; }
- void SetStackProber(StackProber * stackProber);
- static DWORD GetStackLimitForCurrentThreadOffset() { return offsetof(ThreadContext, stackLimitForCurrentThread); }
- template <class Fn>
- Js::ImplicitCallFlags TryWithDisabledImplicitCall(Fn fn)
- {
- DisableImplicitFlags prevDisableImplicitFlags = this->GetDisableImplicitFlags();
- Js::ImplicitCallFlags savedImplicitCallFlags = this->GetImplicitCallFlags();
- this->DisableImplicitCall();
- this->SetImplicitCallFlags(Js::ImplicitCallFlags::ImplicitCall_None);
- fn();
- Js::ImplicitCallFlags curImplicitCallFlags = this->GetImplicitCallFlags();
- this->SetDisableImplicitFlags(prevDisableImplicitFlags);
- this->SetImplicitCallFlags(savedImplicitCallFlags);
- return curImplicitCallFlags;
- }
- void * GetAddressOfStackLimitForCurrentThread() const
- {
- FAULTINJECT_SCRIPT_TERMINATION
- return &this->stackLimitForCurrentThread;
- }
- void InitAvailableCommit();
- // This is always on for JSRT APIs.
- bool IsRentalThreadingEnabledInJSRT() const { return true; }
- IActiveScriptProfilerHeapEnum* GetHeapEnum();
- void SetHeapEnum(IActiveScriptProfilerHeapEnum* newHeapEnum);
- void ClearHeapEnum();
- Js::PropertyRecord const * GetPropertyRecord(Js::PropertyId propertyId);
- virtual bool IsNumericProperty(Js::PropertyId propertyId) override;
- #ifdef ENABLE_WASM_SIMD
- #if _M_IX86 || _M_AMD64
- // auxiliary SIMD values in memory to help JIT'ed code. E.g. used for Int8x16 shuffle.
- _x86_SIMDValue X86_TEMP_SIMD[SIMD_TEMP_SIZE];
- _x86_SIMDValue * GetSimdTempArea() { return X86_TEMP_SIMD; }
- #endif
- #endif
- public:
- Js::PropertyRecord const * GetEmptyStringPropertyRecord()
- {
- if (!emptyStringPropertyRecord)
- {
- emptyStringPropertyRecord = propertyMap->LookupWithKey(Js::HashedCharacterBuffer<char16>(_u(""), 0));
- if (emptyStringPropertyRecord == nullptr)
- {
- emptyStringPropertyRecord = this->UncheckedAddPropertyId(_u(""), 0, true);
- }
- }
- return emptyStringPropertyRecord;
- }
- Js::PropertyId GetEmptyStringPropertyId()
- {
- return GetEmptyStringPropertyRecord()->GetPropertyId();
- }
- private:
- const Js::PropertyRecord * emptyStringPropertyRecord;
- bool noScriptScope;
- #ifdef ENABLE_SCRIPT_DEBUGGING
- Js::DebugManager * debugManager;
- #endif
- static uint const MaxTemporaryArenaAllocators = 5;
- static CriticalSection s_csThreadContext;
- StackProber * GetStackProber() const { return this->stackProber; }
- size_t GetStackLimitForCurrentThread() const;
- void SetStackLimitForCurrentThread(size_t limit);
- // The current heap enumeration object being used during enumeration.
- IActiveScriptProfilerHeapEnum* heapEnum;
- struct PropertyGuardEntry
- {
- public:
- typedef JsUtil::BaseHashSet<RecyclerWeakReference<Js::PropertyGuard>*, Recycler, PowerOf2SizePolicy> PropertyGuardHashSet;
- // we do not have WeaklyReferencedKeyHashSet - hence use BYTE as a dummy value.
- typedef JsUtil::WeaklyReferencedKeyDictionary<Js::EntryPointInfo, BYTE> EntryPointDictionary;
- // The sharedGuard is strongly referenced and will be kept alive by ThreadContext::propertyGuards until it's invalidated or
- // the property record itself is collected. If the code using the guard needs access to it after it's been invalidated, it
- // (the code) is responsible for keeping it alive.
- // Each unique guard, is weakly referenced, such that it can be reclaimed if not referenced elsewhere even without being
- // invalidated. The entry of a unique guard is removed from the table once the corresponding cache is invalidated.
- Field(Js::PropertyGuard*) sharedGuard;
- Field(PropertyGuardHashSet) uniqueGuards;
- Field(EntryPointDictionary*) entryPoints;
- PropertyGuardEntry(Recycler* recycler) : sharedGuard(nullptr), uniqueGuards(recycler), entryPoints(nullptr) {}
- };
- public:
- typedef JsUtil::BaseHashSet<const Js::PropertyRecord *, HeapAllocator, PowerOf2SizePolicy, const Js::PropertyRecord *,
- Js::PropertyRecordStringHashComparer, JsUtil::SimpleHashedEntry, JsUtil::AsymetricResizeLock> PropertyMap;
- PropertyMap * propertyMap;
- typedef JsUtil::BaseHashSet<Js::CaseInvariantPropertyListWithHashCode*, Recycler, PowerOf2SizePolicy, Js::CaseInvariantPropertyListWithHashCode*, JsUtil::NoCaseComparer, JsUtil::SimpleDictionaryEntry>
- PropertyNoCaseSetType;
- typedef JsUtil::WeaklyReferencedKeyDictionary<Js::Type, bool> TypeHashSet;
- typedef JsUtil::BaseDictionary<Js::PropertyId, TypeHashSet *, Recycler, PowerOf2SizePolicy> PropertyIdToTypeHashSetDictionary;
- typedef JsUtil::WeaklyReferencedKeyDictionary<const Js::PropertyRecord, PropertyGuardEntry*, Js::PropertyRecordPointerComparer> PropertyGuardDictionary;
- private:
- PTHREADCONTEXT_HANDLE m_remoteThreadContextInfo;
- intptr_t m_prereservedRegionAddr;
- intptr_t m_jitThunkStartAddr;
- #if ENABLE_NATIVE_CODEGEN
- BVSparse<HeapAllocator> * m_jitNumericProperties;
- bool m_jitNeedsPropertyUpdate;
- public:
- intptr_t GetPreReservedRegionAddr()
- {
- return m_prereservedRegionAddr;
- }
- intptr_t GetJITThunkStartAddr()
- {
- return m_jitThunkStartAddr;
- }
- BVSparse<HeapAllocator> * GetJITNumericProperties() const
- {
- return m_jitNumericProperties;
- }
- bool JITNeedsPropUpdate() const
- {
- return m_jitNeedsPropertyUpdate;
- }
- void ResetJITNeedsPropUpdate()
- {
- m_jitNeedsPropertyUpdate = false;
- }
- static void SetJITConnectionInfo(HANDLE processHandle, void* serverSecurityDescriptor, UUID connectionId);
- bool EnsureJITThreadContext(bool allowPrereserveAlloc);
- PTHREADCONTEXT_HANDLE GetRemoteThreadContextAddr()
- {
- Assert(m_remoteThreadContextInfo);
- return m_remoteThreadContextInfo;
- }
- #endif
- private:
- typedef JsUtil::BaseDictionary<uint, Js::SourceDynamicProfileManager*, Recycler, PowerOf2SizePolicy> SourceDynamicProfileManagerMap;
- typedef JsUtil::BaseDictionary<Js::HashedCharacterBuffer<char16>*, const Js::PropertyRecord*, Recycler, PowerOf2SizePolicy, Js::PropertyRecordStringHashComparer> SymbolRegistrationMap;
- class SourceDynamicProfileManagerCache
- {
- public:
- SourceDynamicProfileManagerCache() : refCount(0), sourceProfileManagerMap(nullptr) {}
- Field(SourceDynamicProfileManagerMap*) sourceProfileManagerMap;
- void AddRef() { refCount++; }
- uint Release() { Assert(refCount > 0); return --refCount; }
- private:
- Field(uint) refCount; // For every script context using this cache, there is a ref count added.
- };
- typedef JsUtil::BaseDictionary<const WCHAR*, SourceDynamicProfileManagerCache*, Recycler, PowerOf2SizePolicy> SourceProfileManagersByUrlMap;
- struct RecyclableData
- {
- RecyclableData(Recycler *const recycler);
- Field(Js::TempArenaAllocatorObject *) temporaryArenaAllocators[MaxTemporaryArenaAllocators];
- Field(Js::TempGuestArenaAllocatorObject *) temporaryGuestArenaAllocators[MaxTemporaryArenaAllocators];
- Field(Js::JavascriptExceptionObject *) pendingFinallyException;
- Field(Js::JavascriptExceptionObject *) exceptionObject;
- Field(bool) propagateException;
- // We throw a JS catchable SO exception if we detect we might overflow the stack. Allocating this (JS)
- // object though might really overflow the stack. So use this thread global to identify them from the throw point
- // to where they are caught; where the stack has been unwound and it is safer to allocate the real exception
- // object and throw.
- Field(Js::JavascriptExceptionObject) soErrorObject;
- // We can't allocate an out of memory object... So use this static as a way to identify
- // them from the throw point to where they are caught.
- Field(Js::JavascriptExceptionObject) oomErrorObject;
- // This is for JsRT scenario where a runtime is not usable after a suspend request, before a resume runtime call is made
- Field(Js::JavascriptExceptionObject) terminatedErrorObject;
- Field(Js::JavascriptExceptionObject*) unhandledExceptionObject;
- // Used to temporarily keep throwing exception object alive (thrown but not yet caught)
- Field(Js::JavascriptExceptionObject*) tempUncaughtException;
- // Contains types that have property caches that need to be tracked, as the caches may need to be cleared. Types that
- // contain a property cache for a property that is on a prototype object will be tracked in this map since those caches
- // need to be cleared if for instance, the property is deleted from the prototype object.
- //
- // It is expected that over time, types that are deleted will eventually be removed by the weak reference hash sets when
- // they're searching through a bucket while registering a type or enumerating types to invalidate, or when a property ID
- // is reclaimed. If none of those happen, then this collection may contain weak reference handles to deleted objects
- // that would not get removed, but it would also not get any bigger.
- Field(PropertyIdToTypeHashSetDictionary) typesWithProtoPropertyCache;
- #if ENABLE_NATIVE_CODEGEN
- // The property guard dictionary contains property guards which need to be invalidated in response to properties changing
- // from writable to read-only and vice versa, properties being shadowed or unshadowed on prototypes, etc. The dictionary
- // holds only weak references to property guards and their lifetimes are controlled by their creators (typically entry points).
- // When a guard is no longer needed it is garbage collected, but the weak references and dictionary entries remain, until
- // the guards for a given property get invalidated.
- // TODO: Create and use a self-cleaning weak reference dictionary, which would periodically remove any unused weak references.
- Field(PropertyGuardDictionary) propertyGuards;
- #endif
- Field(PropertyNoCaseSetType *) caseInvariantPropertySet;
- Field(JsUtil::List<Js::PropertyRecord const*>*) boundPropertyStrings; // Recycler allocated list of property strings that we need to strongly reference so that they're not reclaimed
- Field(SourceProfileManagersByUrlMap*) sourceProfileManagersByUrl;
- // Used to register recyclable data that needs to be kept alive while jitting
- typedef JsUtil::DoublyLinkedList<Js::CodeGenRecyclableData, Recycler> CodeGenRecyclableDataList;
- Field(CodeGenRecyclableDataList) codeGenRecyclableDatas;
- // Used to root old entry points so that they're not prematurely collected
- Field(Js::FunctionEntryPointInfo*) oldEntryPointInfo;
- // Used to store a mapping of string to Symbol for cross-realm Symbol registration
- // See ES6 (draft 22) 19.4.2.2
- Field(SymbolRegistrationMap*) symbolRegistrationMap;
- #ifdef ENABLE_SCRIPT_DEBUGGING
- // Just holding the reference to the returnedValueList of the stepController. This way that list will not get recycled prematurely.
- Field(Js::ReturnedValueList *) returnedValueList;
- #endif
- Field(uint) constructorCacheInvalidationCount;
- #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
- // use for autoProxy called from Debug.setAutoProxyName. we need to keep the buffer from GetSz() alive.
- Field(LPCWSTR) autoProxyName;
- #endif
- };
- static ThreadContext * globalListLast;
- ThreadContextFlags threadContextFlags;
- DWORD currentThreadId;
- mutable size_t stackLimitForCurrentThread;
- StackProber * stackProber;
- bool isThreadBound;
- bool hasThrownPendingException;
- bool * hasBailedOutBitPtr;
- #if ENABLE_JS_REENTRANCY_CHECK
- bool noJsReentrancy;
- #endif
- private:
- bool reentrancySafeOrHandled;
- bool isInReentrancySafeRegion;
- AllocationPolicyManager * allocationPolicyManager;
- JsUtil::ThreadService threadService;
- #if ENABLE_NATIVE_CODEGEN
- PreReservedVirtualAllocWrapper preReservedVirtualAllocator;
- #endif
- uint callRootLevel;
- #if ENABLE_BACKGROUND_PAGE_FREEING
- // The thread page allocator is used by the recycler and need the background page queue
- PageAllocator::BackgroundPageQueue backgroundPageQueue;
- #endif
- IdleDecommitPageAllocator pageAllocator;
- Recycler* recycler;
- // This instance holds list of delay-free array buffer - this will be used in
- // scanning the stack in order to release any delay-free buffer.
- Js::DelayedFreeArrayBuffer delayFreeCallback;
- // Fake RecyclerWeakReference for built-in properties
- class StaticPropertyRecordReference : public RecyclerWeakReference<const Js::PropertyRecord>
- {
- public:
- StaticPropertyRecordReference(const Js::PropertyRecord* propertyRecord)
- {
- strongRef = (char*)propertyRecord;
- strongRefHeapBlock = &CollectedRecyclerWeakRefHeapBlock::Instance;
- }
- };
- static const Js::PropertyRecord * const builtInPropertyRecords[];
- PropertyNoCaseSetType * caseInvariantPropertySet;
- Js::ScriptContext * rootPendingClose;
- JsUtil::List<IProjectionContext *, ArenaAllocator>* pendingProjectionContextCloseList;
- Js::ScriptEntryExitRecord * entryExitRecord;
- Js::InterpreterStackFrame* leafInterpreterFrame;
- const Js::PropertyRecord * propertyNamesDirect[128];
- ArenaAllocator threadAlloc;
- ThreadServiceWrapper* threadServiceWrapper;
- uint functionCount;
- uint sourceInfoCount;
- void * tryHandlerAddrOfReturnAddr;
- enum RedeferralState
- {
- InitialRedeferralState,
- StartupRedeferralState,
- MainRedeferralState
- };
- RedeferralState redeferralState;
- uint gcSinceLastRedeferral;
- uint gcSinceCallCountsCollected;
- static const uint InitialRedeferralDelay = 5;
- static const uint StartupRedeferralCheckInterval = 10;
- static const uint StartupRedeferralInactiveThreshold = 5;
- static const uint MainRedeferralCheckInterval = 20;
- static const uint MainRedeferralInactiveThreshold = 10;
- Js::TypeId nextTypeId;
- uint32 polymorphicCacheState;
- #ifdef ENABLE_PROJECTION
- SListBase<ExternalWeakReferenceCache *, HeapAllocator> externalWeakReferenceCacheList;
- #if DBG_DUMP
- IProjectionContextMemoryInfo *projectionMemoryInformation;
- #endif
- #endif
- #if ENABLE_NATIVE_CODEGEN
- JsUtil::JobProcessor *jobProcessor;
- Js::Var * bailOutRegisterSaveSpace;
- #if !FLOATVAR
- CodeGenNumberThreadAllocator * codeGenNumberThreadAllocator;
- XProcNumberPageSegmentManager * xProcNumberPageSegmentManager;
- #endif
- #if DYNAMIC_INTERPRETER_THUNK || defined(ASMJS_PLAT)
- CustomHeap::InProcCodePageAllocators thunkPageAllocators;
- #endif
- CustomHeap::InProcCodePageAllocators codePageAllocators;
- #if defined(_CONTROL_FLOW_GUARD) && !defined(_M_ARM)
- InProcJITThunkEmitter jitThunkEmitter;
- #endif
- #endif
- RecyclerRootPtr<RecyclableData> recyclableData;
- uint temporaryArenaAllocatorCount;
- uint temporaryGuestArenaAllocatorCount;
- #if DBG_DUMP || defined(PROFILE_EXEC)
- ScriptSite* topLevelScriptSite;
- #endif
- Js::ScriptContext *scriptContextList;
- bool scriptContextEverRegistered;
- static size_t processNativeCodeSize;
- size_t nativeCodeSize;
- size_t sourceCodeSize;
- DateTime::HiResTimer hTimer;
- int stackProbeCount;
- // Count stack probes and poll for continuation every n probes
- static const int StackProbePollThreshold = 1000;
- EXCEPTION_POINTERS exceptionInfo;
- uint32 exceptionCode;
- ArenaAllocator inlineCacheThreadInfoAllocator;
- ArenaAllocator isInstInlineCacheThreadInfoAllocator;
- ArenaAllocator equivalentTypeCacheInfoAllocator;
- DListBase<Js::EntryPointInfo *> equivalentTypeCacheEntryPoints;
- typedef SList<Js::InlineCache*> InlineCacheList;
- typedef JsUtil::BaseDictionary<Js::PropertyId, InlineCacheList*, ArenaAllocator, PrimeSizePolicy> InlineCacheListMapByPropertyId;
- InlineCacheListMapByPropertyId protoInlineCacheByPropId;
- InlineCacheListMapByPropertyId storeFieldInlineCacheByPropId;
- uint registeredInlineCacheCount;
- uint unregisteredInlineCacheCount;
- #if DBG
- uint totalUnregisteredCacheCount;
- uint arrayMutationSeed; // This is mostly to aid in debugging.
- #endif
- typedef JsUtil::BaseDictionary<Js::Var, Js::IsInstInlineCache*, ArenaAllocator, PrimeSizePolicy> IsInstInlineCacheListMapByFunction;
- IsInstInlineCacheListMapByFunction isInstInlineCacheByFunction;
- Js::IsConcatSpreadableCache isConcatSpreadableCache;
- Js::NoSpecialPropertyThreadRegistry noSpecialPropertyRegistry;
- Js::OnlyWritablePropertyThreadRegistry onlyWritablePropertyRegistry;
- DListBase<CollectCallBack> collectCallBackList;
- CriticalSection csCollectionCallBack;
- bool hasCollectionCallBack;
- bool isOptimizedForManyInstances;
- bool bgJit;
- // We report library code to profiler only if called directly by user code. Not if called by library implementation.
- bool isProfilingUserCode;
- void* jsrtRuntime;
- bool hasUnhandledException;
- bool hasCatchHandler;
- DisableImplicitFlags disableImplicitFlags;
- // Used for identifying that any particular time, the caller chain has try/catch blocks belong to the user code.
- // If all try/catch blocks in the current stack marked as non-user code then this member will remain false.
- bool hasCatchHandlerToUserCode;
- #ifdef ENABLE_GLOBALIZATION
- Js::DelayLoadWinRtString delayLoadWinRtString;
- #ifdef ENABLE_PROJECTION
- Js::DelayLoadWinRtError delayLoadWinRtError;
- Js::DelayLoadWinRtTypeResolution delayLoadWinRtTypeResolution;
- Js::DelayLoadWinRtRoParameterizedIID delayLoadWinRtRoParameterizedIID;
- #endif
- #if defined(ENABLE_INTL_OBJECT) || defined(ENABLE_ES6_CHAR_CLASSIFIER)
- #ifdef INTL_WINGLOB
- Js::DelayLoadWindowsGlobalization delayLoadWindowsGlobalizationLibrary;
- Js::WindowsGlobalizationAdapter windowsGlobalizationAdapter;
- #endif
- #endif
- #ifdef ENABLE_FOUNDATION_OBJECT
- Js::DelayLoadWinRtFoundation delayLoadWinRtFoundationLibrary;
- Js::WindowsFoundationAdapter windowsFoundationAdapter;
- #endif
- #endif
- // Number of script context attached with probe manager.
- // This counter will be used as addref when the script context is created, this way we maintain the life of diagnostic object.
- // Once no script context available , diagnostic will go away.
- LONG crefSContextForDiag;
- Entropy entropy;
- JsUtil::Stack<HostScriptContext*>* hostScriptContextStack;
- //
- // Regex globals
- //
- UnifiedRegex::StandardChars<uint8>* standardUTF8Chars;
- UnifiedRegex::StandardChars<char16>* standardUnicodeChars;
- Js::ImplicitCallFlags implicitCallFlags;
- THREAD_LOCAL static uint activeScriptSiteCount;
- bool isScriptActive;
- // When ETW rundown in background thread which needs to walk scriptContext/functionBody/entryPoint lists,
- // or when JIT thread is getting auxPtrs from function body, we should not be modifying the list of
- // functionBody/entrypoints, or expanding the auxPtrs
- CriticalSection csFunctionBody;
- #ifdef _M_X64
- friend class Js::Amd64StackFrame;
- Js::Amd64ContextsManager amd64ContextsManager;
- Js::Amd64ContextsManager* GetAmd64ContextsManager() { return &amd64ContextsManager; }
- #endif
- typedef JsUtil::BaseDictionary<Js::DynamicType const *, void *, HeapAllocator, PowerOf2SizePolicy> DynamicObjectEnumeratorCacheMap;
- DynamicObjectEnumeratorCacheMap dynamicObjectEnumeratorCacheMap;
- #ifdef NTBUILD
- ThreadContextWatsonTelemetryBlock localTelemetryBlock;
- ThreadContextWatsonTelemetryBlock * telemetryBlock;
- #endif
- NativeLibraryEntryRecord nativeLibraryEntry;
- UCrtC99MathApis ucrtC99MathApis;
- // Indicates the current loop depth as observed by the interpreter. The interpreter causes this value to be updated upon
- // entering and leaving a loop.
- uint8 loopDepth;
- const ThreadConfiguration configuration;
- public:
- static ThreadContext * globalListFirst;
- static uint GetScriptSiteHolderCount() { return activeScriptSiteCount; }
- static uint IncrementActiveScriptSiteCount() { return ++activeScriptSiteCount; }
- static uint DecrementActiveScriptSiteCount() { return --activeScriptSiteCount; }
- static ThreadContext * GetThreadContextList() { return globalListFirst; }
- void ValidateThreadContext();
- bool IsInScript() const { return callRootLevel != 0; }
- uint GetCallRootLevel() const { return callRootLevel; }
- PageAllocator * GetPageAllocator() { return &pageAllocator; }
- AllocationPolicyManager * GetAllocationPolicyManager() { return allocationPolicyManager; }
- // used for diagnosing abnormally high number of closed, but still formally reachable script contexts
- // at the time of failfast due to allocation limits.
- // high number may indicate that context leaks have occured.
- uint closedScriptContextCount;
- enum VisibilityState : BYTE
- {
- Undefined = 0,
- Visible = 1,
- NotVisible = 2
- };
- // indicates the visibility state of the hosting application/window/tab if known.
- VisibilityState visibilityState;
- #if ENABLE_NATIVE_CODEGEN
- PreReservedVirtualAllocWrapper * GetPreReservedVirtualAllocator() { return &preReservedVirtualAllocator; }
- #if DYNAMIC_INTERPRETER_THUNK || defined(ASMJS_PLAT)
- CustomHeap::InProcCodePageAllocators * GetThunkPageAllocators() { return &thunkPageAllocators; }
- #endif
- CustomHeap::InProcCodePageAllocators * GetCodePageAllocators() { return &codePageAllocators; }
- #if defined(_CONTROL_FLOW_GUARD) && !defined(_M_ARM)
- InProcJITThunkEmitter * GetJITThunkEmitter() { return &jitThunkEmitter; }
- #endif
- #endif // ENABLE_NATIVE_CODEGEN
- CriticalSection* GetFunctionBodyLock() { return &csFunctionBody; }
- UCrtC99MathApis* GetUCrtC99MathApis() { return &ucrtC99MathApis; }
- Js::IsConcatSpreadableCache* GetIsConcatSpreadableCache() { return &isConcatSpreadableCache; }
- #ifdef ENABLE_GLOBALIZATION
- Js::DelayLoadWinRtString *GetWinRTStringLibrary();
- #ifdef ENABLE_PROJECTION
- Js::DelayLoadWinRtError *GetWinRTErrorLibrary();
- Js::DelayLoadWinRtTypeResolution* GetWinRTTypeResolutionLibrary();
- Js::DelayLoadWinRtRoParameterizedIID* GetWinRTRoParameterizedIIDLibrary();
- #endif
- #if defined(ENABLE_INTL_OBJECT) || defined(ENABLE_ES6_CHAR_CLASSIFIER)
- #ifdef INTL_WINGLOB
- Js::DelayLoadWindowsGlobalization *GetWindowsGlobalizationLibrary();
- Js::WindowsGlobalizationAdapter *GetWindowsGlobalizationAdapter();
- #endif
- #endif
- #ifdef ENABLE_FOUNDATION_OBJECT
- Js::DelayLoadWinRtFoundation *GetWinRtFoundationLibrary();
- Js::WindowsFoundationAdapter *GetWindowsFoundationAdapter();
- #endif
- #endif
- void SetAbnormalExceptionRecord(EXCEPTION_POINTERS *exceptionInfo) { this->exceptionInfo = *exceptionInfo; }
- void SetAbnormalExceptionCode(uint32 exceptionInfo) { this->exceptionCode = exceptionInfo; }
- uint32 GetAbnormalExceptionCode() const { return this->exceptionCode; }
- #ifdef ENABLE_BASIC_TELEMETRY
- GUID activityId;
- LPFILETIME GetLastScriptExecutionEndTime() const;
- #endif
- void *tridentLoadAddress;
- void* GetTridentLoadAddress() const { return tridentLoadAddress; }
- void SetTridentLoadAddress(void *loadAddress) { tridentLoadAddress = loadAddress; }
- Js::NoSpecialPropertyThreadRegistry* GetNoSpecialPropertyRegistry() { return &this->noSpecialPropertyRegistry; }
- Js::OnlyWritablePropertyThreadRegistry* GetOnlyWritablePropertyRegistry() { return &this->onlyWritablePropertyRegistry; }
- Js::DelayedFreeArrayBuffer * GetScanStackCallback()
- {
- return &this->delayFreeCallback;
- }
- #ifdef ENABLE_DIRECTCALL_TELEMETRY
- DirectCallTelemetry directCallTelemetry;
- #endif
- BOOL HasPreviousHostScriptContext();
- HostScriptContext* GetPreviousHostScriptContext() ;
- void PushHostScriptContext(HostScriptContext* topProvider);
- HostScriptContext* PopHostScriptContext();
- void SetInterruptPoller(InterruptPoller *poller) { interruptPoller = poller; }
- InterruptPoller *GetInterruptPoller() const { return interruptPoller; }
- BOOL HasInterruptPoller() const { return interruptPoller != nullptr; }
- void CheckScriptInterrupt();
- void CheckInterruptPoll();
- bool DoInterruptProbe(Js::FunctionBody *const func) const
- {
- return
- (this->TestThreadContextFlag(ThreadContextFlagCanDisableExecution) &&
- !PHASE_OFF(Js::InterruptProbePhase, func)) ||
- PHASE_ON(Js::InterruptProbePhase, func);
- }
- bool DoInterruptProbe() const
- {
- return
- (this->TestThreadContextFlag(ThreadContextFlagCanDisableExecution) &&
- !PHASE_OFF1(Js::InterruptProbePhase)) ||
- PHASE_ON1(Js::InterruptProbePhase);
- }
- bool EvalDisabled() const
- {
- return this->TestThreadContextFlag(ThreadContextFlagEvalDisabled);
- }
- bool NoJIT() const
- {
- return this->TestThreadContextFlag(ThreadContextFlagNoJIT);
- }
- bool NoDynamicThunks() const
- {
- return this->TestThreadContextFlag(ThreadContextFlagNoDynamicThunks);
- }
- #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
- Js::Var GetMemoryStat(Js::ScriptContext* scriptContext);
- void SetAutoProxyName(LPCWSTR objectName);
- LPCWSTR GetAutoProxyName() const { return recyclableData->autoProxyName; }
- Js::PropertyId handlerPropertyId = Js::Constants::NoProperty;
- #endif
- #ifdef ENABLE_SCRIPT_DEBUGGING
- void SetReturnedValueList(Js::ReturnedValueList *returnedValueList)
- {
- Assert(this->recyclableData != nullptr);
- this->recyclableData->returnedValueList = returnedValueList;
- }
- #if DBG
- void EnsureNoReturnedValueList()
- {
- Assert(this->recyclableData == nullptr || this->recyclableData->returnedValueList == nullptr);
- }
- #endif
- #endif
- #if DBG || defined(RUNTIME_DATA_COLLECTION)
- uint GetScriptContextCount() const { return this->scriptContextCount; }
- #endif
- Js::ScriptContext* GetScriptContextList() const { return this->scriptContextList; }
- bool WasAnyScriptContextEverRegistered() const { return this->scriptContextEverRegistered; }
- #if DBG_DUMP || defined(PROFILE_EXEC)
- void SetTopLevelScriptSite(ScriptSite* topScriptSite) { this->topLevelScriptSite = topScriptSite; }
- ScriptSite* GetTopLevelScriptSite () { return this->topLevelScriptSite; }
- #endif
- #if DBG || defined(PROFILE_EXEC)
- virtual bool AsyncHostOperationStart(void *) override;
- virtual void AsyncHostOperationEnd(bool wasInAsync, void *) override;
- #endif
- #if DBG
- virtual void CheckJsReentrancyOnDispose() override;
- bool IsInAsyncHostOperation() const;
- #endif
- #if ENABLE_TTD
- //The class that holds info on the TTD state for the thread context
- TTD::ThreadContextTTD* TTDContext;
- //The class that holds information on TTD <-> debugger interaction state
- TTD::ExecutionInfoManager* TTDExecutionInfo;
- //The event log for time-travel (or null if TTD is not turned on)
- TTD::EventLog* TTDLog;
- //Keep track of the number of re-entrant calls currently pending (i.e., if we make an external call it may call back into Chakra)
- int32 TTDRootNestingCount;
- bool IsRuntimeInTTDMode() const
- {
- return this->TTDLog != nullptr;
- }
- //Initialize the context for time-travel
- void InitTimeTravel(ThreadContext* threadContext, void* runtimeHandle, uint32 snapInterval, uint32 snapHistoryLength);
- void InitHostFunctionsAndTTData(bool record, bool replay, bool debug, size_t optTTUriLength, const char* optTTUri,
- TTD::TTDOpenResourceStreamCallback openResourceStreamfp, TTD::TTDReadBytesFromStreamCallback readBytesFromStreamfp,
- TTD::TTDWriteBytesToStreamCallback writeBytesToStreamfp, TTD::TTDFlushAndCloseStreamCallback flushAndCloseStreamfp,
- TTD::TTDCreateExternalObjectCallback createExternalObjectfp,
- TTD::TTDCreateJsRTContextCallback createJsRTContextCallbackfp, TTD::TTDReleaseJsRTContextCallback releaseJsRTContextCallbackfp, TTD::TTDSetActiveJsRTContext fpSetActiveJsRTContext);
- #endif
- BOOL ReserveStaticTypeIds(__in int first, __in int last);
- Js::TypeId ReserveTypeIds(int count);
- Js::TypeId CreateTypeId();
- Js::TypeId GetNextTypeId() { return nextTypeId; }
- // Lookup the well known type registered with a Js::TypeId.
- // wellKnownType: The well known type which we should register
- // typeId: The type id to match
- // returns: true if the typeid is the wellKnownType
- template<WellKnownHostType wellKnownType>
- bool IsWellKnownHostType(Js::TypeId typeId)
- {
- CompileAssert(wellKnownType <= WellKnownHostType_Last);
- return wellKnownHostTypeIds[wellKnownType] == typeId;
- }
- // Register a well known type to a Js::TypeId.
- // wellKnownType: The well known type which we should register
- // typeId: The type id which matches to the well known type
- void SetWellKnownHostTypeId(WellKnownHostType wellKnownType, Js::TypeId typeId);
- uint32 GetNextPolymorphicCacheState()
- {
- return ++polymorphicCacheState;
- };
- ~ThreadContext();
- void CloseForJSRT();
- //Call back is called for one or more handles
- //It does multiple callbacks (For example: separate call back for GC thread handle & JIT thread handles)
- // template<class Fn>
- //void ShutdownThreads(Fn callback);
- void ShutdownThreads()
- {
- #if ENABLE_NATIVE_CODEGEN
- if (jobProcessor)
- {
- jobProcessor->Close();
- }
- if (JITManager::GetJITManager()->IsOOPJITEnabled() && JITManager::GetJITManager()->IsConnected() && m_remoteThreadContextInfo)
- {
- if (JITManager::GetJITManager()->CleanupThreadContext(&m_remoteThreadContextInfo) == S_OK)
- {
- Assert(m_remoteThreadContextInfo == nullptr);
- }
- m_remoteThreadContextInfo = nullptr;
- }
- #endif
- #if ENABLE_CONCURRENT_GC
- if (this->recycler != nullptr)
- {
- this->recycler->ShutdownThread();
- }
- #endif
- }
- DateTime::HiResTimer * GetHiResTimer() { return &hTimer; }
- ArenaAllocator* GetThreadAlloc() { return &threadAlloc; }
- static CriticalSection * GetCriticalSection() { return &s_csThreadContext; }
- ThreadContext(AllocationPolicyManager * allocationPolicyManager = nullptr, JsUtil::ThreadService::ThreadServiceCallback threadServiceCallback = nullptr, bool enableExperimentalFeatures = false);
- static void Add(ThreadContext *threadContext);
- ThreadConfiguration const * GetConfig() const { return &configuration; }
- public:
- #ifdef NTBUILD
- void SetTelemetryBlock(ThreadContextWatsonTelemetryBlock * telemetryBlock) { this->telemetryBlock = telemetryBlock; }
- #endif
- static ThreadContext* GetContextForCurrentThread();
- Recycler* GetRecycler() { return recycler; }
- Recycler* EnsureRecycler();
- ThreadContext::CollectCallBack * AddRecyclerCollectCallBack(RecyclerCollectCallBackFunction callback, void * context);
- void RemoveRecyclerCollectCallBack(ThreadContext::CollectCallBack * collectCallBack);
- void AddToPendingProjectionContextCloseList(IProjectionContext *projectionContext);
- void RemoveFromPendingClose(IProjectionContext *projectionContext);
- void ClosePendingProjectionContexts();
- void AddToPendingScriptContextCloseList(Js::ScriptContext * scriptContext);
- void RemoveFromPendingClose(Js::ScriptContext * scriptContext);
- void ClosePendingScriptContexts();
- Js::PropertyRecord const * GetPropertyName(Js::PropertyId propertyId);
- Js::PropertyRecord const * GetPropertyNameLocked(Js::PropertyId propertyId);
- private:
- template <bool locked> Js::PropertyRecord const * GetPropertyNameImpl(Js::PropertyId propertyId);
- public:
- void FindPropertyRecord(Js::JavascriptString *pstName, Js::PropertyRecord const ** propertyRecord);
- void FindPropertyRecord(__in LPCWCH propertyName, __in int propertyNameLength, Js::PropertyRecord const ** propertyRecord);
- const Js::PropertyRecord * FindPropertyRecord(const char16 * propertyName, int propertyNameLength);
- JsUtil::List<const RecyclerWeakReference<Js::PropertyRecord const>*>* FindPropertyIdNoCase(Js::ScriptContext * scriptContext, LPCWSTR propertyName, int propertyNameLength);
- JsUtil::List<const RecyclerWeakReference<Js::PropertyRecord const>*>* FindPropertyIdNoCase(Js::ScriptContext * scriptContext, JsUtil::CharacterBuffer<WCHAR> const& propertyName);
- bool FindExistingPropertyRecord(_In_ JsUtil::CharacterBuffer<WCHAR> const& propertyName, Js::CaseInvariantPropertyListWithHashCode** propertyRecord);
- void CleanNoCasePropertyMap();
- void ForceCleanPropertyMap();
- const Js::PropertyRecord * GetOrAddPropertyRecord(JsUtil::CharacterBuffer<char16> propertyName)
- {
- return GetOrAddPropertyRecordImpl(propertyName, false);
- }
- const Js::PropertyRecord * GetOrAddPropertyRecordBind(JsUtil::CharacterBuffer<char16> propertyName)
- {
- return GetOrAddPropertyRecordImpl(propertyName, true);
- }
- void AddBuiltInPropertyRecord(const Js::PropertyRecord *propertyRecord);
- void GetOrAddPropertyId(_In_ LPCWSTR propertyName, _In_ int propertyNameLength, _Out_ Js::PropertyRecord const** propertyRecord);
- void GetOrAddPropertyId(_In_ JsUtil::CharacterBuffer<WCHAR> const& propertyName, _Out_ Js::PropertyRecord const** propertyRecord);
- Js::PropertyRecord const * UncheckedAddPropertyId(JsUtil::CharacterBuffer<WCHAR> const& propertyName, bool bind, bool isSymbol = false);
- Js::PropertyRecord const * UncheckedAddPropertyId(__in LPCWSTR propertyName, __in int propertyNameLength, bool bind = false, bool isSymbol = false);
- #ifdef ENABLE_JS_ETW
- void EtwLogPropertyIdList();
- #endif
- private:
- const Js::PropertyRecord * GetOrAddPropertyRecordImpl(JsUtil::CharacterBuffer<char16> propertyName, bool bind);
- void AddPropertyRecordInternal(const Js::PropertyRecord * propertyRecord);
- void BindPropertyRecord(const Js::PropertyRecord * propertyRecord);
- bool IsDirectPropertyName(const char16 * propertyName, int propertyNameLength);
- RecyclerWeakReference<const Js::PropertyRecord> * CreatePropertyRecordWeakRef(const Js::PropertyRecord * propertyRecord);
- void AddCaseInvariantPropertyRecord(const Js::PropertyRecord * propertyRecord);
- #if DBG || defined(RUNTIME_DATA_COLLECTION)
- uint scriptContextCount;
- #endif
- public:
- void UncheckedAddBuiltInPropertyId();
- BOOL IsNumericPropertyId(Js::PropertyId propertyId, uint32* value);
- bool IsActivePropertyId(Js::PropertyId pid);
- void InvalidatePropertyRecord(const Js::PropertyRecord * propertyRecord);
- Js::PropertyId GetNextPropertyId();
- Js::PropertyId GetMaxPropertyId();
- uint GetHighestPropertyNameIndex() const;
- void SetThreadServiceWrapper(ThreadServiceWrapper*);
- ThreadServiceWrapper* GetThreadServiceWrapper();
- #ifdef ENABLE_PROJECTION
- void AddExternalWeakReferenceCache(ExternalWeakReferenceCache *externalWeakReferenceCache);
- void RemoveExternalWeakReferenceCache(ExternalWeakReferenceCache *externalWeakReferenceCache);
- virtual void MarkExternalWeakReferencedObjects(bool inPartialCollect) override;
- virtual void ResolveExternalWeakReferencedObjects() override;
- #if DBG_DUMP
- void RegisterProjectionMemoryInformation(IProjectionContextMemoryInfo* projectionContextMemoryInfo);
- void DumpProjectionContextMemoryStats(LPCWSTR headerMsg, bool forceDetailed = false);
- IProjectionContextMemoryInfo* GetProjectionContextMemoryInformation();
- #endif
- #endif
- uint NewFunctionNumber() { return ++functionCount; }
- uint PeekNewFunctionNumber() { return functionCount + 1; }
- uint NewSourceInfoNumber() { return ++sourceInfoCount; }
- void AddCodeSize(size_t newCode)
- {
- ::InterlockedExchangeAdd(&nativeCodeSize, newCode);
- ::InterlockedExchangeAdd(&processNativeCodeSize, newCode);
- }
- void AddSourceSize(size_t newCode) { sourceCodeSize += newCode; }
- void SubCodeSize(size_t deadCode)
- {
- Assert(nativeCodeSize >= deadCode);
- Assert(processNativeCodeSize >= deadCode);
- ::InterlockedExchangeSubtract(&nativeCodeSize, deadCode);
- ::InterlockedExchangeSubtract(&processNativeCodeSize, deadCode);
- }
- void SubSourceSize(size_t deadCode) { Assert(sourceCodeSize >= deadCode); sourceCodeSize -= deadCode; }
- size_t GetCodeSize() { return nativeCodeSize; }
- static size_t GetProcessCodeSize() { return processNativeCodeSize; }
- size_t GetSourceSize() { return sourceCodeSize; }
- bool DoTryRedeferral() const;
- void TryRedeferral();
- bool DoRedeferFunctionBodies() const;
- void UpdateRedeferralState();
- uint GetRedeferralCollectionInterval() const;
- uint GetRedeferralInactiveThreshold() const;
- void GetActiveFunctions(ActiveFunctionSet * pActive);
- #if DBG
- uint redeferredFunctions;
- uint recoveredBytes;
- #endif
- Js::ScriptEntryExitRecord * GetScriptEntryExit() const { return entryExitRecord; }
- void RegisterCodeGenRecyclableData(Js::CodeGenRecyclableData *const codeGenRecyclableData);
- void UnregisterCodeGenRecyclableData(Js::CodeGenRecyclableData *const codeGenRecyclableData);
- #if ENABLE_NATIVE_CODEGEN
- bool IsNativeAddressHelper(void * pCodeAddr, Js::ScriptContext* currentScriptContext);
- BOOL IsNativeAddress(void * pCodeAddr, Js::ScriptContext* currentScriptContext = nullptr);
- JsUtil::JobProcessor *GetJobProcessor();
- Js::Var * GetBailOutRegisterSaveSpace() const { return bailOutRegisterSaveSpace; }
- virtual intptr_t GetBailOutRegisterSaveSpaceAddr() const override { return (intptr_t)bailOutRegisterSaveSpace; }
- #if !FLOATVAR
- CodeGenNumberThreadAllocator * GetCodeGenNumberThreadAllocator() const
- {
- return codeGenNumberThreadAllocator;
- }
- XProcNumberPageSegmentManager * GetXProcNumberPageSegmentManager() const
- {
- return this->xProcNumberPageSegmentManager;
- }
- #endif
- #endif
- void ResetFunctionCount() { Assert(this->GetScriptSiteHolderCount() == 0); this->functionCount = 0; }
- void PushEntryExitRecord(Js::ScriptEntryExitRecord *);
- void PopEntryExitRecord(Js::ScriptEntryExitRecord *);
- uint EnterScriptStart(Js::ScriptEntryExitRecord *, bool doCleanup);
- void EnterScriptEnd(Js::ScriptEntryExitRecord *, bool doCleanup);
- void * GetTryHandlerAddrOfReturnAddr() { return this->tryHandlerAddrOfReturnAddr; }
- void SetTryHandlerAddrOfReturnAddr(void * addrOfReturnAddr) { this->tryHandlerAddrOfReturnAddr = addrOfReturnAddr; }
- template <bool leaveForHost>
- void LeaveScriptStart(void *);
- template <bool leaveForHost>
- void LeaveScriptEnd(void *);
- void DisposeOnLeaveScript();
- void PushInterpreterFrame(Js::InterpreterStackFrame *interpreterFrame);
- Js::InterpreterStackFrame *PopInterpreterFrame();
- Js::InterpreterStackFrame *GetLeafInterpreterFrame() const { return leafInterpreterFrame; }
- Js::TempArenaAllocatorObject * GetTemporaryAllocator(LPCWSTR name);
- void ReleaseTemporaryAllocator(Js::TempArenaAllocatorObject * tempAllocator);
- Js::TempGuestArenaAllocatorObject * GetTemporaryGuestAllocator(LPCWSTR name);
- void ReleaseTemporaryGuestAllocator(Js::TempGuestArenaAllocatorObject * tempAllocator);
- #ifdef ENABLE_SCRIPT_DEBUGGING
- // Should be called from script context, at the time when construction for scriptcontext is just done.
- void EnsureDebugManager();
- // Should be called from script context 's destructor,
- void ReleaseDebugManager();
- #endif
- void RegisterScriptContext(Js::ScriptContext *scriptContext);
- void UnregisterScriptContext(Js::ScriptContext *scriptContext);
- // NoScriptScope
- void SetNoScriptScope(bool noScriptScope) { this->noScriptScope = noScriptScope; }
- bool IsNoScriptScope() { return this->noScriptScope; }
- void SetPendingFinallyException(Js::JavascriptExceptionObject * exceptionObj)
- {
- recyclableData->pendingFinallyException = exceptionObj;
- }
- Js::JavascriptExceptionObject * GetPendingFinallyException()
- {
- return recyclableData->pendingFinallyException;
- }
- Js::EntryPointInfo ** RegisterEquivalentTypeCacheEntryPoint(Js::EntryPointInfo * entryPoint);
- void UnregisterEquivalentTypeCacheEntryPoint(Js::EntryPointInfo ** entryPoint);
- void RegisterProtoInlineCache(Js::InlineCache * inlineCache, Js::PropertyId propertyId);
- void RegisterStoreFieldInlineCache(Js::InlineCache * inlineCache, Js::PropertyId propertyId);
- void NotifyInlineCacheBatchUnregistered(uint count);
- #if DBG
- bool IsProtoInlineCacheRegistered(const Js::InlineCache * inlineCache, Js::PropertyId propertyId);
- bool IsStoreFieldInlineCacheRegistered(const Js::InlineCache * inlineCache, Js::PropertyId propertyId);
- #endif
- #if ENABLE_NATIVE_CODEGEN
- Js::PropertyGuard* RegisterSharedPropertyGuard(Js::PropertyId propertyId);
- void RegisterLazyBailout(Js::PropertyId propertyId, Js::EntryPointInfo* entryPoint);
- void RegisterUniquePropertyGuard(Js::PropertyId propertyId, Js::PropertyGuard* guard);
- void RegisterUniquePropertyGuard(Js::PropertyId propertyId, RecyclerWeakReference<Js::PropertyGuard>* guardWeakRef);
- void RegisterConstructorCache(Js::PropertyId propertyId, Js::ConstructorCache* cache);
- #endif
- virtual size_t GetScriptStackLimit() const override;
- virtual HANDLE GetProcessHandle() const override;
- virtual intptr_t GetThreadStackLimitAddr() const override;
- #if ENABLE_NATIVE_CODEGEN && defined(ENABLE_WASM_SIMD)
- virtual intptr_t GetSimdTempAreaAddr(uint8 tempIndex) const override;
- #endif
- virtual intptr_t GetDisableImplicitFlagsAddr() const override;
- virtual intptr_t GetImplicitCallFlagsAddr() const override;
- virtual ptrdiff_t GetChakraBaseAddressDifference() const override;
- virtual ptrdiff_t GetCRTBaseAddressDifference() const override;
- private:
- void RegisterInlineCache(InlineCacheListMapByPropertyId& inlineCacheMap, Js::InlineCache* inlineCache, Js::PropertyId propertyId);
- static bool IsInlineCacheRegistered(InlineCacheListMapByPropertyId& inlineCacheMap, const Js::InlineCache* inlineCache, Js::PropertyId propertyId);
- void InvalidateAndDeleteInlineCacheList(InlineCacheList *inlineCacheList);
- void CompactInlineCacheList(InlineCacheList *inlineCacheList);
- void CompactInlineCacheInvalidationLists();
- void CompactProtoInlineCaches();
- void CompactStoreFieldInlineCaches();
- #if DBG
- static bool IsInlineCacheInList(const Js::InlineCache* inlineCache, const InlineCacheList* inlineCacheChain);
- #endif
- #if ENABLE_NATIVE_CODEGEN
- void InvalidateFixedFieldGuard(Js::PropertyGuard* guard);
- PropertyGuardEntry* EnsurePropertyGuardEntry(const Js::PropertyRecord* propertyRecord, bool& foundExistingEntry);
- void InvalidatePropertyGuardEntry(const Js::PropertyRecord* propertyRecord, PropertyGuardEntry* entry, bool isAllPropertyGuardsInvalidation);
- #endif
- public:
- class AutoDisableExpiration
- {
- public:
- AutoDisableExpiration(ThreadContext* threadContext):
- _threadContext(threadContext),
- _oldExpirationDisabled(threadContext->disableExpiration)
- {
- _threadContext->disableExpiration = true;
- }
- ~AutoDisableExpiration()
- {
- _threadContext->disableExpiration = _oldExpirationDisabled;
- }
- private:
- ThreadContext* _threadContext;
- bool _oldExpirationDisabled;
- };
- void InvalidateProtoInlineCaches(Js::PropertyId propertyId);
- void InvalidateStoreFieldInlineCaches(Js::PropertyId propertyId);
- void InvalidateAllProtoInlineCaches();
- #if DBG
- bool IsObjectRegisteredInProtoInlineCaches(Js::DynamicObject * object);
- bool IsObjectRegisteredInStoreFieldInlineCaches(Js::DynamicObject * object);
- #endif
- bool AreAllProtoInlineCachesInvalidated();
- void InvalidateAllStoreFieldInlineCaches();
- bool AreAllStoreFieldInlineCachesInvalidated();
- void InvalidatePropertyGuards(Js::PropertyId propertyId);
- void InvalidateAllPropertyGuards();
- void RegisterIsInstInlineCache(Js::IsInstInlineCache * inlineCache, Js::Var function);
- void UnregisterIsInstInlineCache(Js::IsInstInlineCache * inlineCache, Js::Var function);
- #if DBG
- bool IsIsInstInlineCacheRegistered(Js::IsInstInlineCache * inlineCache, Js::Var function);
- #endif
- private:
- void InvalidateIsInstInlineCacheList(Js::IsInstInlineCache* inlineCacheList);
- #if DBG
- bool IsIsInstInlineCacheInList(const Js::IsInstInlineCache* inlineCache, const Js::IsInstInlineCache* inlineCacheList);
- #endif
- public:
- void InvalidateIsInstInlineCachesForFunction(Js::Var function);
- void InvalidateAllIsInstInlineCaches();
- bool AreAllIsInstInlineCachesInvalidated() const;
- #ifdef PERSISTENT_INLINE_CACHES
- void ClearInlineCachesWithDeadWeakRefs();
- #endif
- void ClearInvalidatedUniqueGuards();
- void ClearInlineCaches();
- void ClearIsInstInlineCaches();
- void ClearEnumeratorCaches();
- void ClearEquivalentTypeCaches();
- void ClearScriptContextCaches();
- void RegisterTypeWithProtoPropertyCache(const Js::PropertyId propertyId, Js::Type *const type);
- void InvalidateProtoTypePropertyCaches(const Js::PropertyId propertyId);
- void InternalInvalidateProtoTypePropertyCaches(const Js::PropertyId propertyId);
- void InvalidateAllProtoTypePropertyCaches();
- BOOL HasUnhandledException() const { return hasUnhandledException; }
- void SetHasUnhandledException() {hasUnhandledException = TRUE; }
- void ResetHasUnhandledException() {hasUnhandledException = FALSE; }
- void SetUnhandledExceptionObject(Js::JavascriptExceptionObject* exceptionObject) {recyclableData->unhandledExceptionObject = exceptionObject; }
- Js::JavascriptExceptionObject* GetUnhandledExceptionObject() const { return recyclableData->unhandledExceptionObject; };
- // To temporarily keep throwing exception object alive (thrown but not yet caught)
- void SaveTempUncaughtException(Js::JavascriptExceptionObject* exceptionObject)
- {
- Js::JavascriptExceptionObject::Insert(&recyclableData->tempUncaughtException, exceptionObject);
- }
- void ClearTempUncaughtException(Js::JavascriptExceptionObject* exceptionObject)
- {
- Js::JavascriptExceptionObject::Remove(&recyclableData->tempUncaughtException, exceptionObject);
- }
- public:
- bool HasCatchHandler() const { return hasCatchHandler; }
- void SetHasCatchHandler(bool hasCatchHandler) { this->hasCatchHandler = hasCatchHandler; }
- bool IsUserCode() const { return this->hasCatchHandlerToUserCode; }
- void SetIsUserCode(bool set) { this->hasCatchHandlerToUserCode = set; }
- void QueueFreeOldEntryPointInfoIfInScript(Js::FunctionEntryPointInfo* oldEntryPointInfo)
- {
- if (this->IsInScript())
- {
- // Add it to the list only if it's not already in it
- if (oldEntryPointInfo->nextEntryPoint == nullptr && !oldEntryPointInfo->IsCleanedUp())
- {
- oldEntryPointInfo->nextEntryPoint = recyclableData->oldEntryPointInfo;
- recyclableData->oldEntryPointInfo = oldEntryPointInfo;
- }
- }
- }
- bool IsOldEntryPointInfo(Js::ProxyEntryPointInfo* entryPointInfo)
- {
- Js::FunctionEntryPointInfo* current = this->recyclableData->oldEntryPointInfo;
- while (current != nullptr)
- {
- if (current == entryPointInfo)
- return true;
- current = current->nextEntryPoint;
- }
- return false;
- }
- static bool IsOnStack(void const *ptr);
- _NOINLINE bool IsStackAvailable(size_t size, bool* isInterrupt = nullptr);
- _NOINLINE bool IsStackAvailableNoThrow(size_t size = Js::Constants::MinStackDefault);
- static bool IsCurrentStackAvailable(size_t size);
- void ProbeStackNoDispose(size_t size, Js::ScriptContext *scriptContext, PVOID returnAddress = nullptr);
- void ProbeStack(size_t size, Js::ScriptContext *scriptContext, PVOID returnAddress = nullptr);
- void ProbeStack(size_t size, Js::RecyclableObject * obj, Js::ScriptContext *scriptContext);
- void ProbeStack(size_t size);
- static void __stdcall ProbeCurrentStackNoDispose(size_t size, Js::ScriptContext *scriptContext);
- static void __stdcall ProbeCurrentStack(size_t size, Js::ScriptContext *scriptContext);
- static void __stdcall ProbeCurrentStack2(size_t size, Js::ScriptContext *scriptContext, uint32 u1, uint32 u2)
- {
- ProbeCurrentStack(size, scriptContext);
- }
- #if ENABLE_PROFILE_INFO
- void EnsureSourceProfileManagersByUrlMap();
- Js::SourceDynamicProfileManager* GetSourceDynamicProfileManager(_In_z_ const WCHAR* url, _In_ uint hash, _Inout_ bool* addref);
- uint ReleaseSourceDynamicProfileManagers(const WCHAR* url);
- #endif
- void EnsureSymbolRegistrationMap();
- const Js::PropertyRecord* GetSymbolFromRegistrationMap(const char16* stringKey, charcount_t stringLength);
- const Js::PropertyRecord* AddSymbolToRegistrationMap(const char16* stringKey, charcount_t stringLength);
- #if ENABLE_TTD
- JsUtil::BaseDictionary<Js::HashedCharacterBuffer<char16>*, const Js::PropertyRecord*, Recycler, PowerOf2SizePolicy, Js::PropertyRecordStringHashComparer>* GetSymbolRegistrationMap_TTD();
- #endif
- inline void ClearPendingSOError()
- {
- this->GetPendingSOErrorObject()->ClearError();
- }
- inline void ClearPendingOOMError()
- {
- this->GetPendingOOMErrorObject()->ClearError();
- }
- Js::JavascriptExceptionObject *GetPendingSOErrorObject()
- {
- Assert(recyclableData->soErrorObject.IsPendingExceptionObject());
- return &recyclableData->soErrorObject;
- }
- Js::JavascriptExceptionObject *GetPendingOOMErrorObject()
- {
- Assert(recyclableData->oomErrorObject.IsPendingExceptionObject());
- return &recyclableData->oomErrorObject;
- }
- Js::JavascriptExceptionObject *GetPendingTerminatedErrorObject()
- {
- return &recyclableData->terminatedErrorObject;
- }
- Js::JavascriptExceptionObject* GetRecordedException()
- {
- return recyclableData->exceptionObject;
- }
- bool GetPropagateException()
- {
- return recyclableData->propagateException;
- }
- void SetHasThrownPendingException()
- {
- Assert(this->IsInScript());
- this->hasThrownPendingException = true;
- }
- bool * GetHasBailedOutBitPtr()
- {
- return this->hasBailedOutBitPtr;
- }
- void SetHasBailedOutBitPtr(bool *setValue)
- {
- this->hasBailedOutBitPtr = setValue;
- }
- void SetRecordedException(Js::JavascriptExceptionObject* exceptionObject, bool propagateToDebugger = false)
- {
- this->recyclableData->exceptionObject = exceptionObject;
- this->recyclableData->propagateException = propagateToDebugger;
- }
- #ifdef ENABLE_CUSTOM_ENTROPY
- Entropy& GetEntropy()
- {
- return entropy;
- }
- #endif
- Js::ImplicitCallFlags * GetAddressOfImplicitCallFlags()
- {
- return &implicitCallFlags;
- }
- DisableImplicitFlags * GetAddressOfDisableImplicitFlags()
- {
- return &disableImplicitFlags;
- }
- Js::ImplicitCallFlags GetImplicitCallFlags()
- {
- return implicitCallFlags;
- }
- void SetImplicitCallFlags(Js::ImplicitCallFlags flags)
- {
- //Note: this action is inlined into JITed code in Lowerer::GenerateCallProfiling.
- // if you change this, you might want to add it there too.
- implicitCallFlags = flags;
- }
- void ClearImplicitCallFlags();
- void ClearImplicitCallFlags(Js::ImplicitCallFlags flags);
- void AddImplicitCallFlags(Js::ImplicitCallFlags flags)
- {
- SetImplicitCallFlags((Js::ImplicitCallFlags)(implicitCallFlags | flags));
- }
- void CheckAndResetImplicitCallAccessorFlag();
- template <class Fn>
- inline Js::Var ExecuteImplicitCall(Js::RecyclableObject * function, Js::ImplicitCallFlags flags, Fn implicitCall)
- {
- AutoReentrancyHandler autoReentrancyHandler(this);
- Js::FunctionInfo::Attributes attributes = Js::FunctionInfo::GetAttributes(function);
- // we can hoist out const method if we know the function doesn't have side effect,
- // and the value can be hoisted.
- if (this->HasNoSideEffect(function, attributes))
- {
- // Has no side effect means the function does not change global value or
- // will check for implicit call flags
- Js::Var result = implicitCall();
- // If the value is on stack we need to bailout so that it can be boxed.
- // Instead of putting this in valueOf (or other builtins which have no side effect) adding
- // the check here to cover any other scenario we might miss.
- if (IsOnStack(result))
- {
- AddImplicitCallFlags(flags);
- }
- return result;
- }
- // Don't call the implicit call if disable implicit call
- if (IsDisableImplicitCall())
- {
- AddImplicitCallFlags(flags);
- // Return "undefined" just so we have a valid var, in case subsequent instructions are executed
- // before we bail out.
- return function->GetScriptContext()->GetLibrary()->GetUndefined();
- }
- if ((attributes & Js::FunctionInfo::HasNoSideEffect) != 0)
- {
- // Has no side effect means the function does not change global value or
- // will check for implicit call flags
- Js::Var result = implicitCall();
- // If the value is on stack we need to bailout so that it can be boxed.
- // Instead of putting this in valueOf (or other builtins which have no side effect) adding
- // the check here to cover any other scenario we might miss.
- if (IsOnStack(result))
- {
- AddImplicitCallFlags(flags);
- }
- return result;
- }
- // Save and restore implicit flags around the implicit call
- struct RestoreFlags
- {
- ThreadContext * const ctx;
- const Js::ImplicitCallFlags flags;
- const Js::ImplicitCallFlags savedFlags;
- RestoreFlags(ThreadContext *ctx, Js::ImplicitCallFlags flags) :
- ctx(ctx),
- flags(flags),
- savedFlags(ctx->GetImplicitCallFlags())
- {
- }
- ~RestoreFlags()
- {
- ctx->SetImplicitCallFlags(static_cast<Js::ImplicitCallFlags>(savedFlags | flags));
- }
- };
- RestoreFlags restoreFlags(this, flags);
- return implicitCall();
- }
- bool HasNoSideEffect(Js::RecyclableObject * function) const;
- bool HasNoSideEffect(Js::RecyclableObject * function, Js::FunctionInfo::Attributes attr) const;
- bool RecordImplicitException();
- DisableImplicitFlags GetDisableImplicitFlags() const { return disableImplicitFlags; }
- void SetDisableImplicitFlags(DisableImplicitFlags flags) { disableImplicitFlags = flags; }
- bool IsDisableImplicitCall() const { return (disableImplicitFlags & DisableImplicitCallFlag) != 0; }
- bool IsDisableImplicitException() const { return (disableImplicitFlags & DisableImplicitExceptionFlag) != 0; }
- void DisableImplicitCall() { disableImplicitFlags = (DisableImplicitFlags)(disableImplicitFlags | DisableImplicitCallFlag); }
- void ClearDisableImplicitFlags() { disableImplicitFlags = DisableImplicitNoFlag; }
- virtual uint GetRandomNumber() override;
- virtual bool DoSpecialMarkOnScanStack() override { return this->DoRedeferFunctionBodies(); }
- virtual void OnScanStackCallback(void ** stackTop, size_t byteCount, void ** registers, size_t registersByteCount) override;
- virtual void PostSweepRedeferralCallBack() override;
- // DefaultCollectWrapper
- virtual void PreCollectionCallBack(CollectionFlags flags) override;
- virtual void PreSweepCallback() override;
- virtual void PreRescanMarkCallback() override;
- virtual void WaitCollectionCallBack() override;
- virtual void PostCollectionCallBack() override;
- virtual BOOL ExecuteRecyclerCollectionFunction(Recycler * recycler, CollectionFunction function, CollectionFlags flags) override;
- #ifdef FAULT_INJECTION
- virtual void DisposeScriptContextByFaultInjectionCallBack() override;
- #endif
- virtual void DisposeObjects(Recycler * recycler) override;
- virtual void PreDisposeObjectsCallBack() override;
- void DoExpirableCollectModeStackWalk();
- typedef DList<ExpirableObject*, ArenaAllocator> ExpirableObjectList;
- ExpirableObjectList* expirableObjectList;
- ExpirableObjectList* expirableObjectDisposeList;
- int numExpirableObjects;
- int expirableCollectModeGcCount;
- bool disableExpiration;
- bool callDispose;
- bool InExpirableCollectMode();
- void TryEnterExpirableCollectMode();
- void TryExitExpirableCollectMode();
- void RegisterExpirableObject(ExpirableObject* object);
- void UnregisterExpirableObject(ExpirableObject* object);
- void * GetDynamicObjectEnumeratorCache(Js::DynamicType const * dynamicType);
- void AddDynamicObjectEnumeratorCache(Js::DynamicType const * dynamicType, void * cache);
- public:
- bool IsScriptActive() const { return isScriptActive; }
- void SetIsScriptActive(bool isActive) { isScriptActive = isActive; }
- bool IsExecutionDisabled() const
- {
- return this->GetStackLimitForCurrentThread() == Js::Constants::StackLimitForScriptInterrupt;
- }
- void DisableExecution();
- void EnableExecution();
- bool TestThreadContextFlag(ThreadContextFlags threadContextFlag) const;
- void SetThreadContextFlag(ThreadContextFlags threadContextFlag);
- void ClearThreadContextFlag(ThreadContextFlags threadContextFlag);
- void SetForceOneIdleCollection();
- bool IsInThreadServiceCallback() const { return threadService.IsInCallback(); }
- #ifdef ENABLE_SCRIPT_DEBUGGING
- Js::DebugManager * GetDebugManager() const { return this->debugManager; }
- #endif
- const NativeLibraryEntryRecord::Entry* PeekNativeLibraryEntry() const { return this->nativeLibraryEntry.Peek(); }
- void PushNativeLibraryEntry(_In_ NativeLibraryEntryRecord::Entry* entry) { this->nativeLibraryEntry.Push(entry); }
- void PopNativeLibraryEntry() { this->nativeLibraryEntry.Pop(); }
- bool IsProfilingUserCode() const { return isProfilingUserCode; }
- void SetIsProfilingUserCode(bool value) { isProfilingUserCode = value; }
- #if DBG_DUMP
- uint scriptSiteCount;
- #endif
- #ifdef BAILOUT_INJECTION
- uint bailOutByteCodeLocationCount;
- #endif
- #ifdef DYNAMIC_PROFILE_MUTATOR
- DynamicProfileMutator * dynamicProfileMutator;
- #endif
- //
- // Regex helpers
- //
- UnifiedRegex::StandardChars<uint8>* GetStandardChars(__inout_opt uint8* dummy);
- UnifiedRegex::StandardChars<char16>* GetStandardChars(__inout_opt char16* dummy);
- bool IsOptimizedForManyInstances() const { return isOptimizedForManyInstances; }
- void OptimizeForManyInstances(const bool optimizeForManyInstances)
- {
- Assert(!recycler || optimizeForManyInstances == isOptimizedForManyInstances); // mode cannot be changed after recycler is created
- isOptimizedForManyInstances = optimizeForManyInstances;
- }
- #if ENABLE_NATIVE_CODEGEN
- bool IsBgJitEnabled() const { return bgJit; }
- void EnableBgJit(const bool enableBgJit)
- {
- Assert(!jobProcessor || enableBgJit == bgJit);
- bgJit = enableBgJit;
- }
- #endif
- void* GetJSRTRuntime() const { return jsrtRuntime; }
- void SetJSRTRuntime(void* runtime);
- private:
- BOOL ExecuteRecyclerCollectionFunctionCommon(Recycler * recycler, CollectionFunction function, CollectionFlags flags);
- void DoInvalidateProtoTypePropertyCaches(const Js::PropertyId propertyId, TypeHashSet *const typeHashSet);
- void InitializePropertyMaps();
- void CreateNoCasePropertyMap();
- InterruptPoller *interruptPoller;
- void CollectionCallBack(RecyclerCollectCallBackFlags flags);
- // Cache used by HostDispatch::GetBuiltInOperationFromEntryPoint
- private:
- JsUtil::BaseDictionary<Js::JavascriptMethod, uint, ArenaAllocator, PowerOf2SizePolicy> entryPointToBuiltInOperationIdCache;
- #if ENABLE_JS_REENTRANCY_CHECK
- public:
- void SetNoJsReentrancy(bool val) { noJsReentrancy = val; }
- bool GetNoJsReentrancy() { return noJsReentrancy; }
- void AssertJsReentrancy()
- {
- if (GetNoJsReentrancy())
- {
- Js::Throw::FatalJsReentrancyError();
- }
- }
- #else
- void AssertJsReentrancy() {}
- #endif
- public:
- void CheckAndResetReentrancySafeOrHandled()
- {
- AssertOrFailFast(reentrancySafeOrHandled || isInReentrancySafeRegion);
- SetReentrancySafeOrHandled(false);
- }
- void SetReentrancySafeOrHandled(bool val) { reentrancySafeOrHandled = val; }
- bool GetReentrancySafeOrHandled() { return reentrancySafeOrHandled; }
- void SetIsInReentrancySafeRegion(bool val) { isInReentrancySafeRegion = val; }
- bool GetIsInReentrancySafeRegion() { return isInReentrancySafeRegion; }
- template <typename Fn>
- Js::Var SafeReentrantCall(Fn fn)
- {
- AutoReentrancyHandler autoReentrancyHandler(this);
- return fn();
- }
- bool IsEntryPointToBuiltInOperationIdCacheInitialized()
- {
- return entryPointToBuiltInOperationIdCache.Count() != 0;
- }
- bool GetBuiltInOperationIdFromEntryPoint(Js::JavascriptMethod entryPoint, uint * id)
- {
- return entryPointToBuiltInOperationIdCache.TryGetValue(entryPoint, id);
- }
- void SetBuiltInOperationIdForEntryPoint(Js::JavascriptMethod entryPoint, uint id)
- {
- entryPointToBuiltInOperationIdCache.Add(entryPoint, id);
- }
- void ResetEntryPointToBuiltInOperationIdCache()
- {
- entryPointToBuiltInOperationIdCache.ResetNoDelete();
- }
- uint8 LoopDepth() const
- {
- return loopDepth;
- }
- void SetLoopDepth(const uint8 loopDepth)
- {
- this->loopDepth = loopDepth;
- }
- void IncrementLoopDepth()
- {
- if(loopDepth != UCHAR_MAX)
- {
- ++loopDepth;
- }
- }
- void DecrementLoopDepth()
- {
- if(loopDepth != 0)
- {
- --loopDepth;
- }
- }
- #if defined(CHECK_MEMORY_LEAK) || defined(LEAK_REPORT)
- static void ReportAndCheckLeaksOnProcessDetach();
- #endif
- #ifdef LEAK_REPORT
- void SetRootTrackerScriptContext(Js::ScriptContext * scriptContext);
- void ClearRootTrackerScriptContext(Js::ScriptContext * scriptContext);
- private:
- Js::ScriptContext * rootTrackerScriptContext;
- DWORD threadId;
- #endif
- private:
- class ThreadContextRecyclerTelemetryHostInterface : public RecyclerTelemetryHostInterface
- {
- public:
- ThreadContextRecyclerTelemetryHostInterface(ThreadContext* tc) :
- tc(tc)
- {
- }
- virtual LPFILETIME GetLastScriptExecutionEndTime() const;
- virtual bool TransmitGCTelemetryStats(RecyclerTelemetryInfo& rti);
- virtual bool TransmitTelemetryError(const RecyclerTelemetryInfo& rti, const char * msg);
- virtual bool TransmitHeapUsage(size_t totalHeapBytes, size_t usedHeapBytes, double heapUsedRatio);
- virtual bool ThreadContextRecyclerTelemetryHostInterface::IsThreadBound() const;
- virtual DWORD ThreadContextRecyclerTelemetryHostInterface::GetCurrentScriptThreadID() const;
- virtual bool IsTelemetryProviderEnabled() const;
- virtual uint GetClosedContextCount() const;
- private:
- ThreadContext * tc;
- };
- ThreadContextRecyclerTelemetryHostInterface recyclerTelemetryHostInterface;
- };
- extern void(*InitializeAdditionalProperties)(ThreadContext *threadContext);
- // This is for protecting a region of code, where we can't recover and be consistent upon failures (mainly due to OOM and SO).
- // FailFast on that.
- class AutoDisableInterrupt
- {
- public:
- AutoDisableInterrupt(ThreadContext *threadContext, bool explicitCompletion = true)
- : m_operationCompleted(false), m_interruptDisableState(false), m_threadContext(threadContext), m_explicitCompletion(explicitCompletion)
- {
- if (m_threadContext->HasInterruptPoller())
- {
- m_interruptDisableState = m_threadContext->GetInterruptPoller()->IsDisabled();
- m_threadContext->GetInterruptPoller()->SetDisabled(true);
- }
- }
- ~AutoDisableInterrupt()
- {
- if (m_threadContext->HasInterruptPoller())
- {
- m_threadContext->GetInterruptPoller()->SetDisabled(m_interruptDisableState);
- }
- if (m_explicitCompletion && !m_operationCompleted)
- {
- AssertOrFailFast(false);
- }
- }
- void RequireExplicitCompletion() { m_explicitCompletion = true; }
- void Completed() { m_operationCompleted = true; }
- private:
- ThreadContext * m_threadContext;
- bool m_operationCompleted;
- bool m_interruptDisableState;
- bool m_explicitCompletion;
- };
- class AutoReentrancyHandler
- {
- ThreadContext * m_threadContext;
- bool m_savedReentrancySafeOrHandled;
- public:
- AutoReentrancyHandler(ThreadContext * threadContext)
- {
- m_threadContext = threadContext;
- m_savedReentrancySafeOrHandled = threadContext->GetReentrancySafeOrHandled();
- threadContext->SetReentrancySafeOrHandled(true);
- }
- ~AutoReentrancyHandler()
- {
- m_threadContext->SetReentrancySafeOrHandled(m_savedReentrancySafeOrHandled);
- }
- };
- class AutoReentrancySafeRegion
- {
- ThreadContext * m_threadContext;
- bool m_savedIsInReentrancySafeRegion;
- public:
- AutoReentrancySafeRegion(ThreadContext * threadContext)
- {
- m_threadContext = threadContext;
- m_savedIsInReentrancySafeRegion = threadContext->GetIsInReentrancySafeRegion();
- threadContext->SetIsInReentrancySafeRegion(true);
- }
- ~AutoReentrancySafeRegion()
- {
- m_threadContext->SetIsInReentrancySafeRegion(m_savedIsInReentrancySafeRegion);
- }
- };
- #if ENABLE_JS_REENTRANCY_CHECK
- class JsReentLock
- {
- ThreadContext *m_threadContext;
- #if DBG
- Js::Var m_arrayObject;
- Js::Var m_arrayObject2; // This is for adding the second object in the mutation equation.
- #endif
- bool m_savedNoJsReentrancy;
- public:
- JsReentLock(ThreadContext *threadContext)
- #if DBG
- : m_arrayObject(nullptr), m_arrayObject2(nullptr)
- #endif
- {
- m_savedNoJsReentrancy = threadContext->GetNoJsReentrancy();
- threadContext->SetNoJsReentrancy(true);
- m_threadContext = threadContext;
- }
- void unlock() { m_threadContext->SetNoJsReentrancy(m_savedNoJsReentrancy); }
- void relock() { m_threadContext->SetNoJsReentrancy(true); }
- #if DBG
- void setObjectForMutation(Js::Var object);
- void setSecondObjectForMutation(Js::Var object);
- void MutateArrayObject();
- #endif
- ~JsReentLock()
- {
- m_threadContext->SetNoJsReentrancy(m_savedNoJsReentrancy);
- }
- #if DBG
- private:
- static void MutateArrayObject(Js::Var arrayObject);
- #endif
- };
- #endif
|