ThreadContext.h 67 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. namespace Js
  7. {
  8. class ScriptContext;
  9. struct InlineCache;
  10. class DebugManager;
  11. class CodeGenRecyclableData;
  12. struct ReturnedValue;
  13. typedef JsUtil::List<ReturnedValue*> ReturnedValueList;
  14. }
  15. typedef BVSparse<ArenaAllocator> ActiveFunctionSet;
  16. using namespace PlatformAgnostic;
  17. struct IAuthorFileContext;
  18. class HostScriptContext;
  19. class ScriptSite;
  20. class ThreadServiceWrapper;
  21. struct IActiveScriptProfilerHeapEnum;
  22. class DynamicProfileMutator;
  23. class StackProber;
  24. enum DisableImplicitFlags : BYTE
  25. {
  26. DisableImplicitNoFlag = 0x00,
  27. DisableImplicitCallFlag = 0x01,
  28. DisableImplicitExceptionFlag = 0x02,
  29. DisableImplicitCallAndExceptionFlag = DisableImplicitCallFlag | DisableImplicitExceptionFlag
  30. };
  31. enum ThreadContextFlags
  32. {
  33. ThreadContextFlagNoFlag = 0x00000000,
  34. ThreadContextFlagCanDisableExecution = 0x00000001,
  35. ThreadContextFlagEvalDisabled = 0x00000002,
  36. ThreadContextFlagNoJIT = 0x00000004,
  37. };
  38. const int LS_MAX_STACK_SIZE_KB = 300;
  39. struct IProjectionContext
  40. {
  41. public:
  42. virtual HRESULT Close() = 0;
  43. };
  44. class ThreadContext;
  45. class InterruptPoller _ABSTRACT
  46. {
  47. // Interface with a polling object located in the hosting layer.
  48. public:
  49. InterruptPoller(ThreadContext *tc);
  50. virtual ~InterruptPoller() { }
  51. void CheckInterruptPoll();
  52. void GetStatementCount(ULONG *pluHi, ULONG *pluLo);
  53. void ResetStatementCount() { lastResetTick = lastPollTick; }
  54. void StartScript() { lastResetTick = lastPollTick = ::GetTickCount(); }
  55. void EndScript() { lastResetTick = lastPollTick = 0;}
  56. bool IsDisabled() const { return isDisabled; }
  57. void SetDisabled(bool disable) { isDisabled = disable; }
  58. virtual void TryInterruptPoll(Js::ScriptContext *scriptContext) = 0;
  59. // Default: throw up QC dialog after 5M statements == 2 minutes
  60. static const DWORD TicksToStatements = (5000000 / 120000);
  61. protected:
  62. ThreadContext *threadContext;
  63. DWORD lastPollTick;
  64. DWORD lastResetTick;
  65. bool isDisabled;
  66. };
  67. class AutoDisableInterrupt
  68. {
  69. private:
  70. InterruptPoller* interruptPoller;
  71. bool previousState;
  72. public:
  73. AutoDisableInterrupt(InterruptPoller* interruptPoller, bool disable)
  74. : interruptPoller(interruptPoller)
  75. {
  76. if (interruptPoller != nullptr)
  77. {
  78. previousState = interruptPoller->IsDisabled();
  79. interruptPoller->SetDisabled(disable);
  80. }
  81. }
  82. ~AutoDisableInterrupt()
  83. {
  84. if (interruptPoller != nullptr)
  85. {
  86. interruptPoller->SetDisabled(previousState);
  87. }
  88. }
  89. };
  90. // This function is called before we step out of script (currently only for WinRT callout).
  91. // Debugger would put a breakpoint on this function if they want to detect the point at which we step
  92. // over the boundary.
  93. // It is intentionally left blank and the next operation should be the callout.
  94. extern "C" void* MarkerForExternalDebugStep();
  95. #define PROBE_STACK(scriptContext, size) ((scriptContext)->GetThreadContext()->ProbeStack(size, scriptContext))
  96. #define PROBE_STACK_NO_DISPOSE(scriptContext, size) ((scriptContext)->GetThreadContext()->ProbeStackNoDispose(size, scriptContext))
  97. #define PROBE_STACK_PARTIAL_INITIALIZED_INTERPRETER_FRAME(scriptContext, size) ((scriptContext)->GetThreadContext()->ProbeStack(size, scriptContext, _ReturnAddress()))
  98. #define PROBE_STACK_PARTIAL_INITIALIZED_BAILOUT_FRAME(scriptContext, size, returnAddress) ((scriptContext)->GetThreadContext()->ProbeStack(size, scriptContext, returnAddress))
  99. #define PROBE_STACK_CALL(scriptContext, obj, size) ((scriptContext)->GetThreadContext()->ProbeStack(size, obj, scriptContext))
  100. #define AssertInScript() Assert(ThreadContext::GetContextForCurrentThread()->IsScriptActive());
  101. #define AssertNotInScript() Assert(!ThreadContext::GetContextForCurrentThread()->IsScriptActive());
  102. #define LEAVE_SCRIPT_START_EX(scriptContext, stackProbe, leaveForHost, isFPUControlRestoreNeeded) \
  103. { \
  104. void * __frameAddr = nullptr; \
  105. GET_CURRENT_FRAME_ID(__frameAddr); \
  106. Js::LeaveScriptObject<stackProbe, leaveForHost, isFPUControlRestoreNeeded> __leaveScriptObject(scriptContext, __frameAddr);
  107. #define LEAVE_SCRIPT_END_EX(scriptContext) \
  108. if (scriptContext != nullptr) \
  109. { \
  110. scriptContext->GetThreadContext()->DisposeOnLeaveScript(); \
  111. }\
  112. }
  113. #define BEGIN_LEAVE_SCRIPT(scriptContext) \
  114. LEAVE_SCRIPT_START_EX(scriptContext, /* stackProbe */ true, /* leaveForHost */ true, /* isFPUControlRestoreNeeded */ false)
  115. #define BEGIN_LEAVE_SCRIPT_SAVE_FPU_CONTROL(scriptContext) \
  116. LEAVE_SCRIPT_START_EX(scriptContext, /* stackProbe */ true, /* leaveForHost */ true, /* isFPUControlRestoreNeeded */ true)
  117. // BEGIN_LEAVE_SCRIPT_INTERNAL is used when there are no explicit external call after leave script,
  118. // but we might have external call when allocation memory doing QC or GC Dispose, which may enter script again.
  119. // This will record the reentry as an implicit call (ImplicitCall_AsyncHostOperation)
  120. #define BEGIN_LEAVE_SCRIPT_INTERNAL(scriptContext) \
  121. LEAVE_SCRIPT_START_EX(scriptContext, /* stackProbe */ true, /* leaveForHost */ false, /* isFPUControlRestoreNeeded */ false)
  122. #define BEGIN_LEAVE_SCRIPT_NO_STACK_PROBE(scriptContext) \
  123. LEAVE_SCRIPT_START_EX(scriptContext, /* stackProbe */ false, /* leaveForHost */ true, /* isFPUControlRestoreNeeded */ false)
  124. #define END_LEAVE_SCRIPT(scriptContext) \
  125. LEAVE_SCRIPT_END_EX(scriptContext)
  126. #define END_LEAVE_SCRIPT_RESTORE_FPU_CONTROL(scriptContext) \
  127. LEAVE_SCRIPT_END_EX(scriptContext)
  128. #define END_LEAVE_SCRIPT_INTERNAL(scriptContext) \
  129. LEAVE_SCRIPT_END_EX(scriptContext)
  130. #define END_LEAVE_SCRIPT_NO_STACK_PROBE(scriptContext) \
  131. LEAVE_SCRIPT_END_EX(scriptContext)
  132. #define BEGIN_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext) \
  133. BEGIN_LEAVE_SCRIPT(scriptContext)
  134. #define END_LEAVE_SCRIPT_WITH_EXCEPTION(scriptContext) \
  135. Assert(!scriptContext->HasRecordedException()); \
  136. END_LEAVE_SCRIPT(scriptContext)
  137. // Keep in sync with CollectGarbageCallBackFlags in scriptdirect.idl
  138. enum RecyclerCollectCallBackFlags
  139. {
  140. Collect_Begin = 0x01,
  141. Collect_Begin_Concurrent = 0x11,
  142. Collect_Begin_Partial = 0x21,
  143. Collect_Begin_Concurrent_Partial = Collect_Begin_Concurrent | Collect_Begin_Partial,
  144. Collect_End = 0x02,
  145. Collect_Wait = 0x04 // callback can be from another thread
  146. };
  147. typedef void (__cdecl *RecyclerCollectCallBackFunction)(void * context, RecyclerCollectCallBackFlags flags);
  148. // Keep in sync with WellKnownType in scriptdirect.idl
  149. typedef enum WellKnownHostType
  150. {
  151. WellKnownHostType_HTMLAllCollection = 0,
  152. WellKnownHostType_Last = WellKnownHostType_HTMLAllCollection,
  153. WellKnownHostType_Invalid = WellKnownHostType_Last+1
  154. } WellKnownHostType;
  155. #ifdef ENABLE_PROJECTION
  156. class ExternalWeakReferenceCache
  157. {
  158. public:
  159. virtual void MarkNow(Recycler *recycler, bool inPartialCollect) = 0;
  160. virtual void ResolveNow(Recycler *recycler) = 0;
  161. };
  162. #if DBG_DUMP
  163. class IProjectionContextMemoryInfo abstract
  164. {
  165. public:
  166. virtual void DumpCurrentStats(LPCWSTR headerMsg, bool forceDetailed) = 0;
  167. virtual void Release() = 0;
  168. };
  169. #endif
  170. #endif
  171. #ifdef NTBUILD
  172. struct ThreadContextWatsonTelemetryBlock
  173. {
  174. FILETIME lastScriptStartTime;
  175. FILETIME lastScriptEndTime;
  176. };
  177. #endif
  178. class NativeLibraryEntryRecord
  179. {
  180. public:
  181. struct Entry
  182. {
  183. Js::RecyclableObject* function;
  184. Js::CallInfo callInfo;
  185. PCWSTR name;
  186. PVOID addr;
  187. Entry* next;
  188. };
  189. private:
  190. Entry* head;
  191. public:
  192. NativeLibraryEntryRecord() : head(nullptr)
  193. {
  194. }
  195. const Entry* Peek() const
  196. {
  197. return head;
  198. }
  199. void Push(_In_ Entry* e)
  200. {
  201. e->next = head;
  202. head = e;
  203. }
  204. void Pop()
  205. {
  206. head = head->next;
  207. }
  208. };
  209. class AutoTagNativeLibraryEntry
  210. {
  211. private:
  212. NativeLibraryEntryRecord::Entry entry;
  213. public:
  214. AutoTagNativeLibraryEntry(Js::RecyclableObject* function, Js::CallInfo callInfo, PCWSTR name, void* addr);
  215. ~AutoTagNativeLibraryEntry();
  216. };
  217. #define AUTO_TAG_NATIVE_LIBRARY_ENTRY(function, callInfo, name) \
  218. AutoTagNativeLibraryEntry __tag(function, callInfo, name, _AddressOfReturnAddress())
  219. class ThreadConfiguration
  220. {
  221. public:
  222. ThreadConfiguration(bool enableExperimentalFeatures)
  223. {
  224. CopyGlobalFlags();
  225. if (enableExperimentalFeatures)
  226. {
  227. EnableExperimentalFeatures();
  228. ResetExperimentalFeaturesFromConfig();
  229. }
  230. }
  231. #define DEFINE_FLAG(threadFlag, globalFlag) \
  232. public: \
  233. inline bool threadFlag() const { return m_##globalFlag##; } \
  234. \
  235. private: \
  236. bool m_##globalFlag##;
  237. #define FLAG(threadFlag, globalFlag) DEFINE_FLAG(threadFlag, globalFlag)
  238. #define FLAG_RELEASE(threadFlag, globalFlag) DEFINE_FLAG(threadFlag, globalFlag)
  239. #include "ThreadConfigFlagsList.h"
  240. #undef FLAG_RELEASE
  241. #undef FLAG
  242. #undef DEFINE_FLAG
  243. private:
  244. void CopyGlobalFlags()
  245. {
  246. AutoCriticalSection autocs(&Js::Configuration::Global.flags.csExperimentalFlags);
  247. #define FLAG(threadFlag, globalFlag) m_##globalFlag## = CONFIG_FLAG(globalFlag);
  248. #define FLAG_RELEASE(threadFlag, globalFlag) m_##globalFlag## = CONFIG_FLAG_RELEASE(globalFlag);
  249. #include "ThreadConfigFlagsList.h"
  250. #undef FLAG_RELEASE
  251. #undef FLAG
  252. }
  253. void EnableExperimentalFeatures()
  254. {
  255. // If a ES6 flag is disabled using compile flag don't enable it
  256. #define FLAG_REGOVR_EXP(type, name, ...) m_##name## = COMPILE_DISABLE_##name## ? false : true;
  257. #include "ConfigFlagsList.h"
  258. #undef FLAG_REGOVR_EXP
  259. }
  260. void ResetExperimentalFeaturesFromConfig()
  261. {
  262. // If a flag was overridden using config/command line it should take precedence
  263. #define FLAG_REGOVR_EXP(type, name, ...) if(CONFIG_ISENABLED(Js::Flag::##name##Flag)) { m_##name## = CONFIG_FLAG_RELEASE(##name##); }
  264. #include "ConfigFlagsList.h"
  265. #undef FLAG_REGOVR_EXP
  266. }
  267. };
  268. class ThreadContext sealed :
  269. public DefaultRecyclerCollectionWrapper,
  270. public JsUtil::DoublyLinkedListElement<ThreadContext>,
  271. public ThreadContextInfo
  272. {
  273. public:
  274. static void GlobalInitialize();
  275. static const DWORD NoThread = 0xFFFFFFFF;
  276. struct CollectCallBack
  277. {
  278. RecyclerCollectCallBackFunction callback;
  279. void * context;
  280. };
  281. struct WorkerThread
  282. {
  283. // Abstract notion to hold onto threadHandle of worker thread
  284. HANDLE threadHandle;
  285. WorkerThread(HANDLE handle = nullptr) :threadHandle(handle){};
  286. };
  287. void SetCurrentThreadId(DWORD threadId) { this->currentThreadId = threadId; }
  288. DWORD GetCurrentThreadId() const { return this->currentThreadId; }
  289. void SetIsThreadBound()
  290. {
  291. if (this->recycler)
  292. {
  293. this->recycler->SetIsThreadBound();
  294. }
  295. this->isThreadBound = true;
  296. }
  297. bool IsJSRT() const { return !this->isThreadBound; }
  298. virtual bool IsThreadBound() const override { return this->isThreadBound; }
  299. void SetStackProber(StackProber * stackProber);
  300. static DWORD GetStackLimitForCurrentThreadOffset() { return offsetof(ThreadContext, stackLimitForCurrentThread); }
  301. template <class Fn>
  302. Js::ImplicitCallFlags TryWithDisabledImplicitCall(Fn fn)
  303. {
  304. DisableImplicitFlags prevDisableImplicitFlags = this->GetDisableImplicitFlags();
  305. Js::ImplicitCallFlags savedImplicitCallFlags = this->GetImplicitCallFlags();
  306. this->DisableImplicitCall();
  307. this->SetImplicitCallFlags(Js::ImplicitCallFlags::ImplicitCall_None);
  308. fn();
  309. Js::ImplicitCallFlags curImplicitCallFlags = this->GetImplicitCallFlags();
  310. this->SetDisableImplicitFlags(prevDisableImplicitFlags);
  311. this->SetImplicitCallFlags(savedImplicitCallFlags);
  312. return curImplicitCallFlags;
  313. }
  314. void * GetAddressOfStackLimitForCurrentThread() const
  315. {
  316. FAULTINJECT_SCRIPT_TERMINATION
  317. return &this->stackLimitForCurrentThread;
  318. }
  319. void InitAvailableCommit();
  320. // This is always on for JSRT APIs.
  321. bool IsRentalThreadingEnabledInJSRT() const { return true; }
  322. IActiveScriptProfilerHeapEnum* GetHeapEnum();
  323. void SetHeapEnum(IActiveScriptProfilerHeapEnum* newHeapEnum);
  324. void ClearHeapEnum();
  325. Js::PropertyRecord const * GetPropertyRecord(Js::PropertyId propertyId);
  326. virtual bool IsNumericProperty(Js::PropertyId propertyId) override;
  327. #ifdef ENABLE_BASIC_TELEMETRY
  328. Js::LanguageStats* GetLanguageStats()
  329. {
  330. return langTel.GetLanguageStats();
  331. }
  332. void ResetLangStats()
  333. {
  334. this->langTel.Reset();
  335. }
  336. #endif
  337. #if ENABLE_NATIVE_CODEGEN && defined(ENABLE_SIMDJS)
  338. // used by inliner. Maps Simd FuncInfo (library func) to equivalent opcode.
  339. typedef JsUtil::BaseDictionary<Js::FunctionInfo *, Js::OpCode, ArenaAllocator> FuncInfoToOpcodeMap;
  340. FuncInfoToOpcodeMap * simdFuncInfoToOpcodeMap;
  341. struct SimdFuncSignature
  342. {
  343. bool valid;
  344. uint argCount; // actual arguments count (excluding this)
  345. ValueType returnType;
  346. ValueType *args; // argument types
  347. };
  348. SimdFuncSignature *simdOpcodeToSignatureMap;
  349. void AddSimdFuncToMaps(Js::OpCode op, ...);
  350. void AddSimdFuncInfo(Js::OpCode op, Js::FunctionInfo *funcInfo);
  351. Js::OpCode GetSimdOpcodeFromFuncInfo(Js::FunctionInfo * funcInfo);
  352. void GetSimdFuncSignatureFromOpcode(Js::OpCode op, SimdFuncSignature &funcSignature);
  353. #if _M_IX86 || _M_AMD64
  354. // auxiliary SIMD values in memory to help JIT'ed code. E.g. used for Int8x16 shuffle.
  355. _x86_SIMDValue X86_TEMP_SIMD[SIMD_TEMP_SIZE];
  356. _x86_SIMDValue * GetSimdTempArea() { return X86_TEMP_SIMD; }
  357. #endif
  358. #endif
  359. private:
  360. bool noScriptScope;
  361. Js::DebugManager * debugManager;
  362. static uint const MaxTemporaryArenaAllocators = 5;
  363. static CriticalSection s_csThreadContext;
  364. StackProber * GetStackProber() const { return this->stackProber; }
  365. size_t GetStackLimitForCurrentThread() const;
  366. void SetStackLimitForCurrentThread(size_t limit);
  367. // The current heap enumeration object being used during enumeration.
  368. IActiveScriptProfilerHeapEnum* heapEnum;
  369. #ifdef ENABLE_BASIC_TELEMETRY
  370. Js::LanguageTelemetry langTel;
  371. #endif
  372. struct PropertyGuardEntry
  373. {
  374. public:
  375. typedef JsUtil::BaseHashSet<RecyclerWeakReference<Js::PropertyGuard>*, Recycler, PowerOf2SizePolicy> PropertyGuardHashSet;
  376. // we do not have WeaklyReferencedKeyHashSet - hence use BYTE as a dummy value.
  377. typedef JsUtil::WeaklyReferencedKeyDictionary<Js::EntryPointInfo, BYTE> EntryPointDictionary;
  378. // The sharedGuard is strongly referenced and will be kept alive by ThreadContext::propertyGuards until it's invalidated or
  379. // the property record itself is collected. If the code using the guard needs access to it after it's been invalidated, it
  380. // (the code) is responsible for keeping it alive.
  381. // Each unique guard, is weakly referenced, such that it can be reclaimed if not referenced elsewhere even without being
  382. // invalidated. The entry of a unique guard is removed from the table once the corresponding cache is invalidated.
  383. Js::PropertyGuard* sharedGuard;
  384. PropertyGuardHashSet uniqueGuards;
  385. EntryPointDictionary* entryPoints;
  386. PropertyGuardEntry(Recycler* recycler) : sharedGuard(nullptr), uniqueGuards(recycler), entryPoints(nullptr) {}
  387. };
  388. public:
  389. typedef JsUtil::BaseHashSet<const Js::PropertyRecord *, HeapAllocator, PrimeSizePolicy, const Js::PropertyRecord *,
  390. Js::PropertyRecordStringHashComparer, JsUtil::SimpleHashedEntry, JsUtil::AsymetricResizeLock> PropertyMap;
  391. PropertyMap * propertyMap;
  392. typedef JsUtil::BaseHashSet<Js::CaseInvariantPropertyListWithHashCode*, Recycler, PowerOf2SizePolicy, Js::CaseInvariantPropertyListWithHashCode*, JsUtil::NoCaseComparer, JsUtil::SimpleDictionaryEntry>
  393. PropertyNoCaseSetType;
  394. typedef JsUtil::WeaklyReferencedKeyDictionary<Js::Type, bool> TypeHashSet;
  395. typedef JsUtil::BaseDictionary<Js::PropertyId, TypeHashSet *, Recycler, PowerOf2SizePolicy> PropertyIdToTypeHashSetDictionary;
  396. typedef JsUtil::WeaklyReferencedKeyDictionary<const Js::PropertyRecord, PropertyGuardEntry*, Js::PropertyRecordPointerComparer> PropertyGuardDictionary;
  397. private:
  398. PTHREADCONTEXT_HANDLE m_remoteThreadContextInfo;
  399. intptr_t m_prereservedRegionAddr;
  400. #if ENABLE_NATIVE_CODEGEN
  401. BVSparse<HeapAllocator> * m_jitNumericProperties;
  402. bool m_jitNeedsPropertyUpdate;
  403. public:
  404. BVSparse<HeapAllocator> * GetJITNumericProperties() const
  405. {
  406. return m_jitNumericProperties;
  407. }
  408. bool JITNeedsPropUpdate() const
  409. {
  410. return m_jitNeedsPropertyUpdate;
  411. }
  412. void ResetJITNeedsPropUpdate()
  413. {
  414. m_jitNeedsPropertyUpdate = false;
  415. }
  416. static void SetJITConnectionInfo(HANDLE processHandle, void* serverSecurityDescriptor, UUID connectionId);
  417. void EnsureJITThreadContext(bool allowPrereserveAlloc);
  418. PTHREADCONTEXT_HANDLE GetRemoteThreadContextAddr()
  419. {
  420. Assert(m_remoteThreadContextInfo);
  421. return m_remoteThreadContextInfo;
  422. }
  423. #endif
  424. private:
  425. typedef JsUtil::BaseDictionary<uint, Js::SourceDynamicProfileManager*, Recycler, PowerOf2SizePolicy> SourceDynamicProfileManagerMap;
  426. typedef JsUtil::BaseDictionary<const char16*, const Js::PropertyRecord*, Recycler, PowerOf2SizePolicy> SymbolRegistrationMap;
  427. class SourceDynamicProfileManagerCache
  428. {
  429. public:
  430. SourceDynamicProfileManagerCache() : refCount(0), sourceProfileManagerMap(nullptr) {}
  431. SourceDynamicProfileManagerMap* sourceProfileManagerMap;
  432. void AddRef() { refCount++; }
  433. uint Release() { Assert(refCount > 0); return --refCount; }
  434. private:
  435. uint refCount; // For every script context using this cache, there is a ref count added.
  436. };
  437. typedef JsUtil::BaseDictionary<const WCHAR*, SourceDynamicProfileManagerCache*, Recycler, PowerOf2SizePolicy> SourceProfileManagersByUrlMap;
  438. struct RecyclableData
  439. {
  440. RecyclableData(Recycler *const recycler);
  441. Js::TempArenaAllocatorObject * temporaryArenaAllocators[MaxTemporaryArenaAllocators];
  442. Js::TempGuestArenaAllocatorObject * temporaryGuestArenaAllocators[MaxTemporaryArenaAllocators];
  443. Js::JavascriptExceptionObject * exceptionObject;
  444. bool propagateException;
  445. // We throw a JS catchable SO exception if we detect we might overflow the stack. Allocating this (JS)
  446. // object though might really overflow the stack. So use this thread global to identify them from the throw point
  447. // to where they are caught; where the stack has been unwound and it is safer to allocate the real exception
  448. // object and throw.
  449. Js::JavascriptExceptionObject soErrorObject;
  450. // We can't allocate an out of memory object... So use this static as a way to identify
  451. // them from the throw point to where they are caught.
  452. Js::JavascriptExceptionObject oomErrorObject;
  453. // This is for JsRT scenario where a runtime is not usable after a suspend request, before a resume runtime call is made
  454. Js::JavascriptExceptionObject terminatedErrorObject;
  455. Js::JavascriptExceptionObject* unhandledExceptionObject;
  456. // Used to temporarily keep throwing exception object alive (thrown but not yet caught)
  457. Js::JavascriptExceptionObject* tempUncaughtException;
  458. // Contains types that have property caches that need to be tracked, as the caches may need to be cleared. Types that
  459. // contain a property cache for a property that is on a prototype object will be tracked in this map since those caches
  460. // need to be cleared if for instance, the property is deleted from the prototype object.
  461. //
  462. // It is expected that over time, types that are deleted will eventually be removed by the weak reference hash sets when
  463. // they're searching through a bucket while registering a type or enumerating types to invalidate, or when a property ID
  464. // is reclaimed. If none of those happen, then this collection may contain weak reference handles to deleted objects
  465. // that would not get removed, but it would also not get any bigger.
  466. PropertyIdToTypeHashSetDictionary typesWithProtoPropertyCache;
  467. // The property guard dictionary contains property guards which need to be invalidated in response to properties changing
  468. // from writable to read-only and vice versa, properties being shadowed or unshadowed on prototypes, etc. The dictionary
  469. // holds only weak references to property guards and their lifetimes are controlled by their creators (typically entry points).
  470. // When a guard is no longer needed it is garbage collected, but the weak references and dictionary entries remain, until
  471. // the guards for a given property get invalidated.
  472. // TODO: Create and use a self-cleaning weak reference dictionary, which would periodically remove any unused weak references.
  473. PropertyGuardDictionary propertyGuards;
  474. PropertyNoCaseSetType * caseInvariantPropertySet;
  475. JsUtil::List<Js::PropertyRecord const*>* boundPropertyStrings; // Recycler allocated list of property strings that we need to strongly reference so that they're not reclaimed
  476. SourceProfileManagersByUrlMap* sourceProfileManagersByUrl;
  477. // Used to register recyclable data that needs to be kept alive while jitting
  478. JsUtil::DoublyLinkedList<Js::CodeGenRecyclableData> codeGenRecyclableDatas;
  479. // Used to root old entry points so that they're not prematurely collected
  480. Js::FunctionEntryPointInfo* oldEntryPointInfo;
  481. // Used to store a mapping of string to Symbol for cross-realm Symbol registration
  482. // See ES6 (draft 22) 19.4.2.2
  483. SymbolRegistrationMap* symbolRegistrationMap;
  484. // Just holding the reference to the returnedValueList of the stepController. This way that list will not get recycled prematurely.
  485. Js::ReturnedValueList *returnedValueList;
  486. uint constructorCacheInvalidationCount;
  487. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  488. // use for autoProxy called from Debug.setAutoProxyName. we need to keep the buffer from GetSz() alive.
  489. LPCWSTR autoProxyName;
  490. #endif
  491. };
  492. static ThreadContext * globalListLast;
  493. ThreadContextFlags threadContextFlags;
  494. DWORD currentThreadId;
  495. mutable size_t stackLimitForCurrentThread;
  496. StackProber * stackProber;
  497. bool isThreadBound;
  498. bool hasThrownPendingException;
  499. bool callDispose;
  500. AllocationPolicyManager * allocationPolicyManager;
  501. JsUtil::ThreadService threadService;
  502. PreReservedVirtualAllocWrapper preReservedVirtualAllocator;
  503. uint callRootLevel;
  504. #if ENABLE_BACKGROUND_PAGE_FREEING
  505. // The thread page allocator is used by the recycler and need the background page queue
  506. PageAllocator::BackgroundPageQueue backgroundPageQueue;
  507. #endif
  508. IdleDecommitPageAllocator pageAllocator;
  509. Recycler* recycler;
  510. // Fake RecyclerWeakReference for built-in properties
  511. class StaticPropertyRecordReference : public RecyclerWeakReference<const Js::PropertyRecord>
  512. {
  513. public:
  514. StaticPropertyRecordReference(const Js::PropertyRecord* propertyRecord)
  515. {
  516. strongRef = (char*)propertyRecord;
  517. strongRefHeapBlock = &CollectedRecyclerWeakRefHeapBlock::Instance;
  518. }
  519. };
  520. static const Js::PropertyRecord * const builtInPropertyRecords[];
  521. PropertyNoCaseSetType * caseInvariantPropertySet;
  522. Js::ScriptContext * rootPendingClose;
  523. JsUtil::List<IProjectionContext *, ArenaAllocator>* pendingProjectionContextCloseList;
  524. Js::ScriptEntryExitRecord * entryExitRecord;
  525. Js::InterpreterStackFrame* leafInterpreterFrame;
  526. const Js::PropertyRecord * propertyNamesDirect[128];
  527. ArenaAllocator threadAlloc;
  528. ThreadServiceWrapper* threadServiceWrapper;
  529. uint functionCount;
  530. uint sourceInfoCount;
  531. enum RedeferralState
  532. {
  533. InitialRedeferralState,
  534. StartupRedeferralState,
  535. MainRedeferralState
  536. };
  537. RedeferralState redeferralState;
  538. uint gcSinceLastRedeferral;
  539. uint gcSinceCallCountsCollected;
  540. static const uint InitialRedeferralDelay = 5;
  541. static const uint StartupRedeferralCheckInterval = 10;
  542. static const uint StartupRedeferralInactiveThreshold = 5;
  543. static const uint MainRedeferralCheckInterval = 20;
  544. static const uint MainRedeferralInactiveThreshold = 10;
  545. Js::TypeId nextTypeId;
  546. uint32 polymorphicCacheState;
  547. #ifdef ENABLE_PROJECTION
  548. SListBase<ExternalWeakReferenceCache *> externalWeakReferenceCacheList;
  549. #if DBG_DUMP
  550. IProjectionContextMemoryInfo *projectionMemoryInformation;
  551. #endif
  552. #endif
  553. #if ENABLE_NATIVE_CODEGEN
  554. JsUtil::JobProcessor *jobProcessor;
  555. Js::Var * bailOutRegisterSaveSpace;
  556. #if !FLOATVAR
  557. CodeGenNumberThreadAllocator * codeGenNumberThreadAllocator;
  558. XProcNumberPageSegmentManager * xProcNumberPageSegmentManager;
  559. #endif
  560. #if DYNAMIC_INTERPRETER_THUNK || defined(ASMJS_PLAT)
  561. CustomHeap::CodePageAllocators thunkPageAllocators;
  562. #endif
  563. CustomHeap::CodePageAllocators codePageAllocators;
  564. #endif
  565. RecyclerRootPtr<RecyclableData> recyclableData;
  566. uint temporaryArenaAllocatorCount;
  567. uint temporaryGuestArenaAllocatorCount;
  568. #if DBG_DUMP || defined(PROFILE_EXEC)
  569. ScriptSite* topLevelScriptSite;
  570. #endif
  571. Js::ScriptContext *scriptContextList;
  572. bool scriptContextEverRegistered;
  573. static size_t processNativeCodeSize;
  574. size_t nativeCodeSize;
  575. size_t sourceCodeSize;
  576. DateTime::HiResTimer hTimer;
  577. int stackProbeCount;
  578. // Count stack probes and poll for continuation every n probes
  579. static const int StackProbePollThreshold = 1000;
  580. ArenaAllocator inlineCacheThreadInfoAllocator;
  581. ArenaAllocator isInstInlineCacheThreadInfoAllocator;
  582. ArenaAllocator equivalentTypeCacheInfoAllocator;
  583. DListBase<Js::EntryPointInfo *> equivalentTypeCacheEntryPoints;
  584. typedef SList<Js::InlineCache*> InlineCacheList;
  585. typedef JsUtil::BaseDictionary<Js::PropertyId, InlineCacheList*, ArenaAllocator> InlineCacheListMapByPropertyId;
  586. InlineCacheListMapByPropertyId protoInlineCacheByPropId;
  587. InlineCacheListMapByPropertyId storeFieldInlineCacheByPropId;
  588. uint registeredInlineCacheCount;
  589. uint unregisteredInlineCacheCount;
  590. #if DBG
  591. uint totalUnregisteredCacheCount;
  592. #endif
  593. typedef JsUtil::BaseDictionary<Js::Var, Js::IsInstInlineCache*, ArenaAllocator> IsInstInlineCacheListMapByFunction;
  594. IsInstInlineCacheListMapByFunction isInstInlineCacheByFunction;
  595. Js::IsConcatSpreadableCache isConcatSpreadableCache;
  596. ArenaAllocator prototypeChainEnsuredToHaveOnlyWritableDataPropertiesAllocator;
  597. DListBase<Js::ScriptContext *> prototypeChainEnsuredToHaveOnlyWritableDataPropertiesScriptContext;
  598. DListBase<CollectCallBack> collectCallBackList;
  599. CriticalSection csCollectionCallBack;
  600. bool hasCollectionCallBack;
  601. bool isOptimizedForManyInstances;
  602. bool bgJit;
  603. // We report library code to profiler only if called directly by user code. Not if called by library implementation.
  604. bool isProfilingUserCode;
  605. void* jsrtRuntime;
  606. bool hasUnhandledException;
  607. bool hasCatchHandler;
  608. DisableImplicitFlags disableImplicitFlags;
  609. // Used for identifying that any particular time, the caller chain has try/catch blocks belong to the user code.
  610. // If all try/catch blocks in the current stack marked as non-user code then this member will remain false.
  611. bool hasCatchHandlerToUserCode;
  612. #ifdef ENABLE_GLOBALIZATION
  613. Js::DelayLoadWinRtString delayLoadWinRtString;
  614. #ifdef ENABLE_PROJECTION
  615. Js::DelayLoadWinRtError delayLoadWinRtError;
  616. Js::DelayLoadWinRtTypeResolution delayLoadWinRtTypeResolution;
  617. Js::DelayLoadWinRtRoParameterizedIID delayLoadWinRtRoParameterizedIID;
  618. #endif
  619. #if defined(ENABLE_INTL_OBJECT) || defined(ENABLE_ES6_CHAR_CLASSIFIER)
  620. Js::DelayLoadWindowsGlobalization delayLoadWindowsGlobalizationLibrary;
  621. Js::WindowsGlobalizationAdapter windowsGlobalizationAdapter;
  622. #endif
  623. #ifdef ENABLE_FOUNDATION_OBJECT
  624. Js::DelayLoadWinRtFoundation delayLoadWinRtFoundationLibrary;
  625. Js::WindowsFoundationAdapter windowsFoundationAdapter;
  626. #endif
  627. #endif
  628. // Number of script context attached with probe manager.
  629. // This counter will be used as addref when the script context is created, this way we maintain the life of diagnostic object.
  630. // Once no script context available , diagnostic will go away.
  631. LONG crefSContextForDiag;
  632. Entropy entropy;
  633. JsUtil::Stack<HostScriptContext*>* hostScriptContextStack;
  634. //
  635. // Regex globals
  636. //
  637. UnifiedRegex::StandardChars<uint8>* standardUTF8Chars;
  638. UnifiedRegex::StandardChars<char16>* standardUnicodeChars;
  639. Js::ImplicitCallFlags implicitCallFlags;
  640. THREAD_LOCAL static uint activeScriptSiteCount;
  641. bool isScriptActive;
  642. // To synchronize with ETW rundown, which needs to walk scriptContext/functionBody/entryPoint lists.
  643. CriticalSection csEtwRundown;
  644. #ifdef _M_X64
  645. friend class Js::Amd64StackFrame;
  646. Js::Amd64ContextsManager amd64ContextsManager;
  647. Js::Amd64ContextsManager* GetAmd64ContextsManager() { return &amd64ContextsManager; }
  648. #endif
  649. typedef JsUtil::BaseDictionary<Js::DynamicType const *, void *, HeapAllocator, PowerOf2SizePolicy> DynamicObjectEnumeratorCacheMap;
  650. DynamicObjectEnumeratorCacheMap dynamicObjectEnumeratorCacheMap;
  651. #ifdef NTBUILD
  652. ThreadContextWatsonTelemetryBlock localTelemetryBlock;
  653. ThreadContextWatsonTelemetryBlock * telemetryBlock;
  654. #endif
  655. NativeLibraryEntryRecord nativeLibraryEntry;
  656. UCrtC99MathApis ucrtC99MathApis;
  657. // Indicates the current loop depth as observed by the interpreter. The interpreter causes this value to be updated upon
  658. // entering and leaving a loop.
  659. uint8 loopDepth;
  660. const ThreadConfiguration configuration;
  661. public:
  662. static ThreadContext * globalListFirst;
  663. static uint GetScriptSiteHolderCount() { return activeScriptSiteCount; }
  664. static uint IncrementActiveScriptSiteCount() { return ++activeScriptSiteCount; }
  665. static uint DecrementActiveScriptSiteCount() { return --activeScriptSiteCount; }
  666. static ThreadContext * GetThreadContextList() { return globalListFirst; }
  667. void ValidateThreadContext();
  668. bool IsInScript() const { return callRootLevel != 0; }
  669. uint GetCallRootLevel() const { return callRootLevel; }
  670. PageAllocator * GetPageAllocator() { return &pageAllocator; }
  671. AllocationPolicyManager * GetAllocationPolicyManager() { return allocationPolicyManager; }
  672. #if ENABLE_NATIVE_CODEGEN
  673. PreReservedVirtualAllocWrapper * GetPreReservedVirtualAllocator() { return &preReservedVirtualAllocator; }
  674. #if DYNAMIC_INTERPRETER_THUNK || defined(ASMJS_PLAT)
  675. CustomHeap::CodePageAllocators * GetThunkPageAllocators() { return &thunkPageAllocators; }
  676. #endif
  677. CustomHeap::CodePageAllocators * GetCodePageAllocators() { return &codePageAllocators; }
  678. #endif // ENABLE_NATIVE_CODEGEN
  679. CriticalSection* GetEtwRundownCriticalSection() { return &csEtwRundown; }
  680. UCrtC99MathApis* GetUCrtC99MathApis() { return &ucrtC99MathApis; }
  681. Js::IsConcatSpreadableCache* GetIsConcatSpreadableCache() { return &isConcatSpreadableCache; }
  682. #ifdef ENABLE_GLOBALIZATION
  683. Js::DelayLoadWinRtString *GetWinRTStringLibrary();
  684. #ifdef ENABLE_PROJECTION
  685. Js::DelayLoadWinRtError *GetWinRTErrorLibrary();
  686. Js::DelayLoadWinRtTypeResolution* GetWinRTTypeResolutionLibrary();
  687. Js::DelayLoadWinRtRoParameterizedIID* GetWinRTRoParameterizedIIDLibrary();
  688. #endif
  689. #if defined(ENABLE_INTL_OBJECT) || defined(ENABLE_ES6_CHAR_CLASSIFIER)
  690. Js::DelayLoadWindowsGlobalization *GetWindowsGlobalizationLibrary();
  691. Js::WindowsGlobalizationAdapter *GetWindowsGlobalizationAdapter();
  692. #endif
  693. #ifdef ENABLE_FOUNDATION_OBJECT
  694. Js::DelayLoadWinRtFoundation *GetWinRtFoundationLibrary();
  695. Js::WindowsFoundationAdapter *GetWindowsFoundationAdapter();
  696. #endif
  697. #endif
  698. #ifdef ENABLE_BASIC_TELEMETRY
  699. GUID activityId;
  700. #endif
  701. void *tridentLoadAddress;
  702. void* GetTridentLoadAddress() const { return tridentLoadAddress; }
  703. void SetTridentLoadAddress(void *loadAddress) { tridentLoadAddress = loadAddress; }
  704. #ifdef ENABLE_DIRECTCALL_TELEMETRY
  705. DirectCallTelemetry directCallTelemetry;
  706. #endif
  707. BOOL HasPreviousHostScriptContext();
  708. HostScriptContext* GetPreviousHostScriptContext() ;
  709. void PushHostScriptContext(HostScriptContext* topProvider);
  710. HostScriptContext* PopHostScriptContext();
  711. void SetInterruptPoller(InterruptPoller *poller) { interruptPoller = poller; }
  712. InterruptPoller *GetInterruptPoller() const { return interruptPoller; }
  713. BOOL HasInterruptPoller() const { return interruptPoller != nullptr; }
  714. void CheckScriptInterrupt();
  715. void CheckInterruptPoll();
  716. bool DoInterruptProbe(Js::FunctionBody *const func) const
  717. {
  718. return
  719. (this->TestThreadContextFlag(ThreadContextFlagCanDisableExecution) &&
  720. !PHASE_OFF(Js::InterruptProbePhase, func)) ||
  721. PHASE_ON(Js::InterruptProbePhase, func);
  722. }
  723. bool DoInterruptProbe() const
  724. {
  725. return
  726. (this->TestThreadContextFlag(ThreadContextFlagCanDisableExecution) &&
  727. !PHASE_OFF1(Js::InterruptProbePhase)) ||
  728. PHASE_ON1(Js::InterruptProbePhase);
  729. }
  730. bool EvalDisabled() const
  731. {
  732. return this->TestThreadContextFlag(ThreadContextFlagEvalDisabled);
  733. }
  734. bool NoJIT() const
  735. {
  736. return this->TestThreadContextFlag(ThreadContextFlagNoJIT);
  737. }
  738. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  739. Js::Var GetMemoryStat(Js::ScriptContext* scriptContext);
  740. void SetAutoProxyName(LPCWSTR objectName);
  741. LPCWSTR GetAutoProxyName() const { return recyclableData->autoProxyName; }
  742. Js::PropertyId handlerPropertyId = Js::Constants::NoProperty;
  743. #endif
  744. void SetReturnedValueList(Js::ReturnedValueList *returnedValueList)
  745. {
  746. Assert(this->recyclableData != nullptr);
  747. this->recyclableData->returnedValueList = returnedValueList;
  748. }
  749. #if DBG
  750. void EnsureNoReturnedValueList()
  751. {
  752. Assert(this->recyclableData == nullptr || this->recyclableData->returnedValueList == nullptr);
  753. }
  754. #endif
  755. #if DBG || defined(RUNTIME_DATA_COLLECTION)
  756. uint GetScriptContextCount() const { return this->scriptContextCount; }
  757. #endif
  758. Js::ScriptContext* GetScriptContextList() const { return this->scriptContextList; }
  759. bool WasAnyScriptContextEverRegistered() const { return this->scriptContextEverRegistered; }
  760. #if DBG_DUMP || defined(PROFILE_EXEC)
  761. void SetTopLevelScriptSite(ScriptSite* topScriptSite) { this->topLevelScriptSite = topScriptSite; }
  762. ScriptSite* GetTopLevelScriptSite () { return this->topLevelScriptSite; }
  763. #endif
  764. #if DBG || defined(PROFILE_EXEC)
  765. virtual bool AsyncHostOperationStart(void *) override;
  766. virtual void AsyncHostOperationEnd(bool wasInAsync, void *) override;
  767. #endif
  768. #if DBG
  769. bool IsInAsyncHostOperation() const;
  770. #endif
  771. #if ENABLE_TTD
  772. //The class that holds info on the TTD state for the thread context
  773. TTD::ThreadContextTTD* TTDContext;
  774. //The event log for time-travel (or null if TTD is not turned on)
  775. TTD::EventLog* TTDLog;
  776. //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)
  777. int32 TTDRootNestingCount;
  778. bool IsRuntimeInTTDMode() const
  779. {
  780. return this->TTDLog != nullptr;
  781. }
  782. //Initialize the context for time-travel
  783. void InitTimeTravel(ThreadContext* threadContext, void* runtimeHandle, size_t uriByteLength, const byte* ttdUri, uint32 snapInterval, uint32 snapHistoryLength);
  784. void InitHostFunctionsAndTTData(bool record, bool replay, bool debug, TTD::TTDInitializeForWriteLogStreamCallback writeInitializefp,
  785. TTD::TTDOpenResourceStreamCallback getResourceStreamfp, TTD::TTDReadBytesFromStreamCallback readBytesFromStreamfp,
  786. TTD::TTDWriteBytesToStreamCallback writeBytesToStreamfp, TTD::TTDFlushAndCloseStreamCallback flushAndCloseStreamfp,
  787. TTD::TTDCreateExternalObjectCallback createExternalObjectfp,
  788. TTD::TTDCreateJsRTContextCallback createJsRTContextCallbackfp, TTD::TTDReleaseJsRTContextCallback releaseJsRTContextCallbackfp, TTD::TTDSetActiveJsRTContext fpSetActiveJsRTContext);
  789. #endif
  790. BOOL ReserveStaticTypeIds(__in int first, __in int last);
  791. Js::TypeId ReserveTypeIds(int count);
  792. Js::TypeId CreateTypeId();
  793. Js::TypeId GetNextTypeId() { return nextTypeId; }
  794. // Lookup the well known type registered with a Js::TypeId.
  795. // typeId: The type id to match
  796. // returns: The well known type which was previously registered via a call to SetWellKnownHostTypeId
  797. WellKnownHostType GetWellKnownHostType(Js::TypeId typeId);
  798. // Register a well known type to a Js::TypeId.
  799. // wellKnownType: The well known type which we should register
  800. // typeId: The type id which matches to the well known type
  801. void SetWellKnownHostTypeId(WellKnownHostType wellKnownType, Js::TypeId typeId);
  802. uint32 GetNextPolymorphicCacheState()
  803. {
  804. return ++polymorphicCacheState;
  805. };
  806. ~ThreadContext();
  807. void CloseForJSRT();
  808. //Call back is called for one or more handles
  809. //It does multiple callbacks (For example: separate call back for GC thread handle & JIT thread handles)
  810. // template<class Fn>
  811. //void ShutdownThreads(Fn callback);
  812. void ShutdownThreads()
  813. {
  814. #if ENABLE_NATIVE_CODEGEN
  815. if (jobProcessor)
  816. {
  817. jobProcessor->Close();
  818. }
  819. if (JITManager::GetJITManager()->IsOOPJITEnabled() && m_remoteThreadContextInfo)
  820. {
  821. if (JITManager::GetJITManager()->CleanupThreadContext(&m_remoteThreadContextInfo) == S_OK)
  822. {
  823. Assert(m_remoteThreadContextInfo == nullptr);
  824. }
  825. m_remoteThreadContextInfo = nullptr;
  826. }
  827. #endif
  828. #if ENABLE_CONCURRENT_GC
  829. if (this->recycler != nullptr)
  830. {
  831. this->recycler->ShutdownThread();
  832. }
  833. #endif
  834. }
  835. DateTime::HiResTimer * GetHiResTimer() { return &hTimer; }
  836. ArenaAllocator* GetThreadAlloc() { return &threadAlloc; }
  837. static CriticalSection * GetCriticalSection() { return &s_csThreadContext; }
  838. ThreadContext(AllocationPolicyManager * allocationPolicyManager = nullptr, JsUtil::ThreadService::ThreadServiceCallback threadServiceCallback = nullptr, bool enableExperimentalFeatures = false);
  839. static void Add(ThreadContext *threadContext);
  840. ThreadConfiguration const * GetConfig() const { return &configuration; }
  841. public:
  842. #ifdef NTBUILD
  843. void SetTelemetryBlock(ThreadContextWatsonTelemetryBlock * telemetryBlock) { this->telemetryBlock = telemetryBlock; }
  844. #endif
  845. static ThreadContext* GetContextForCurrentThread();
  846. Recycler* GetRecycler() { return recycler; }
  847. Recycler* EnsureRecycler();
  848. ThreadContext::CollectCallBack * AddRecyclerCollectCallBack(RecyclerCollectCallBackFunction callback, void * context);
  849. void RemoveRecyclerCollectCallBack(ThreadContext::CollectCallBack * collectCallBack);
  850. void AddToPendingProjectionContextCloseList(IProjectionContext *projectionContext);
  851. void RemoveFromPendingClose(IProjectionContext *projectionContext);
  852. void ClosePendingProjectionContexts();
  853. void AddToPendingScriptContextCloseList(Js::ScriptContext * scriptContext);
  854. void RemoveFromPendingClose(Js::ScriptContext * scriptContext);
  855. void ClosePendingScriptContexts();
  856. Js::PropertyRecord const * GetPropertyName(Js::PropertyId propertyId);
  857. Js::PropertyRecord const * GetPropertyNameLocked(Js::PropertyId propertyId);
  858. private:
  859. template <bool locked> Js::PropertyRecord const * GetPropertyNameImpl(Js::PropertyId propertyId);
  860. public:
  861. void FindPropertyRecord(Js::JavascriptString *pstName, Js::PropertyRecord const ** propertyRecord);
  862. void FindPropertyRecord(__in LPCWSTR propertyName, __in int propertyNameLength, Js::PropertyRecord const ** propertyRecord);
  863. const Js::PropertyRecord * FindPropertyRecord(const char16 * propertyName, int propertyNameLength);
  864. JsUtil::List<const RecyclerWeakReference<Js::PropertyRecord const>*>* FindPropertyIdNoCase(Js::ScriptContext * scriptContext, LPCWSTR propertyName, int propertyNameLength);
  865. JsUtil::List<const RecyclerWeakReference<Js::PropertyRecord const>*>* FindPropertyIdNoCase(Js::ScriptContext * scriptContext, JsUtil::CharacterBuffer<WCHAR> const& propertyName);
  866. bool FindExistingPropertyRecord(_In_ JsUtil::CharacterBuffer<WCHAR> const& propertyName, Js::CaseInvariantPropertyListWithHashCode** propertyRecord);
  867. void CleanNoCasePropertyMap();
  868. void ForceCleanPropertyMap();
  869. const Js::PropertyRecord * GetOrAddPropertyRecord(JsUtil::CharacterBuffer<char16> propertyName)
  870. {
  871. return GetOrAddPropertyRecordImpl(propertyName, false);
  872. }
  873. const Js::PropertyRecord * GetOrAddPropertyRecordBind(JsUtil::CharacterBuffer<char16> propertyName)
  874. {
  875. return GetOrAddPropertyRecordImpl(propertyName, true);
  876. }
  877. void AddBuiltInPropertyRecord(const Js::PropertyRecord *propertyRecord);
  878. void GetOrAddPropertyId(__in LPCWSTR propertyName, __in int propertyNameLength, Js::PropertyRecord const** propertyRecord);
  879. void GetOrAddPropertyId(JsUtil::CharacterBuffer<WCHAR> const& propertyName, Js::PropertyRecord const** propertyRecord);
  880. Js::PropertyRecord const * UncheckedAddPropertyId(JsUtil::CharacterBuffer<WCHAR> const& propertyName, bool bind, bool isSymbol = false);
  881. Js::PropertyRecord const * UncheckedAddPropertyId(__in LPCWSTR propertyName, __in int propertyNameLength, bool bind = false, bool isSymbol = false);
  882. #ifdef ENABLE_JS_ETW
  883. void EtwLogPropertyIdList();
  884. #endif
  885. private:
  886. const Js::PropertyRecord * GetOrAddPropertyRecordImpl(JsUtil::CharacterBuffer<char16> propertyName, bool bind);
  887. void AddPropertyRecordInternal(const Js::PropertyRecord * propertyRecord);
  888. void BindPropertyRecord(const Js::PropertyRecord * propertyRecord);
  889. bool IsDirectPropertyName(const char16 * propertyName, int propertyNameLength);
  890. RecyclerWeakReference<const Js::PropertyRecord> * CreatePropertyRecordWeakRef(const Js::PropertyRecord * propertyRecord);
  891. void AddCaseInvariantPropertyRecord(const Js::PropertyRecord * propertyRecord);
  892. #if DBG || defined(RUNTIME_DATA_COLLECTION)
  893. uint scriptContextCount;
  894. #endif
  895. public:
  896. void UncheckedAddBuiltInPropertyId();
  897. BOOL IsNumericPropertyId(Js::PropertyId propertyId, uint32* value);
  898. bool IsActivePropertyId(Js::PropertyId pid);
  899. void InvalidatePropertyRecord(const Js::PropertyRecord * propertyRecord);
  900. Js::PropertyId GetNextPropertyId();
  901. Js::PropertyId GetMaxPropertyId();
  902. uint GetHighestPropertyNameIndex() const;
  903. void SetThreadServiceWrapper(ThreadServiceWrapper*);
  904. ThreadServiceWrapper* GetThreadServiceWrapper();
  905. #ifdef ENABLE_PROJECTION
  906. void AddExternalWeakReferenceCache(ExternalWeakReferenceCache *externalWeakReferenceCache);
  907. void RemoveExternalWeakReferenceCache(ExternalWeakReferenceCache *externalWeakReferenceCache);
  908. virtual void MarkExternalWeakReferencedObjects(bool inPartialCollect) override;
  909. virtual void ResolveExternalWeakReferencedObjects() override;
  910. #if DBG_DUMP
  911. void RegisterProjectionMemoryInformation(IProjectionContextMemoryInfo* projectionContextMemoryInfo);
  912. void DumpProjectionContextMemoryStats(LPCWSTR headerMsg, bool forceDetailed = false);
  913. IProjectionContextMemoryInfo* GetProjectionContextMemoryInformation();
  914. #endif
  915. #endif
  916. uint NewFunctionNumber() { return ++functionCount; }
  917. uint PeekNewFunctionNumber() { return functionCount + 1; }
  918. uint NewSourceInfoNumber() { return ++sourceInfoCount; }
  919. void AddCodeSize(size_t newCode)
  920. {
  921. ::InterlockedExchangeAdd(&nativeCodeSize, newCode);
  922. ::InterlockedExchangeAdd(&processNativeCodeSize, newCode);
  923. }
  924. void AddSourceSize(size_t newCode) { sourceCodeSize += newCode; }
  925. void SubCodeSize(size_t deadCode)
  926. {
  927. Assert(nativeCodeSize >= deadCode);
  928. Assert(processNativeCodeSize >= deadCode);
  929. ::InterlockedExchangeSubtract(&nativeCodeSize, deadCode);
  930. ::InterlockedExchangeSubtract(&processNativeCodeSize, deadCode);
  931. }
  932. void SubSourceSize(size_t deadCode) { Assert(sourceCodeSize >= deadCode); sourceCodeSize -= deadCode; }
  933. size_t GetCodeSize() { return nativeCodeSize; }
  934. static size_t GetProcessCodeSize() { return processNativeCodeSize; }
  935. size_t GetSourceSize() { return sourceCodeSize; }
  936. bool DoTryRedeferral() const;
  937. void TryRedeferral();
  938. bool DoRedeferFunctionBodies() const;
  939. void UpdateRedeferralState();
  940. uint GetRedeferralCollectionInterval() const;
  941. uint GetRedeferralInactiveThreshold() const;
  942. void GetActiveFunctions(ActiveFunctionSet * pActive);
  943. #if DBG
  944. uint redeferredFunctions;
  945. uint recoveredBytes;
  946. #endif
  947. Js::ScriptEntryExitRecord * GetScriptEntryExit() const { return entryExitRecord; }
  948. void RegisterCodeGenRecyclableData(Js::CodeGenRecyclableData *const codeGenRecyclableData);
  949. void UnregisterCodeGenRecyclableData(Js::CodeGenRecyclableData *const codeGenRecyclableData);
  950. #if ENABLE_NATIVE_CODEGEN
  951. BOOL IsNativeAddress(void * pCodeAddr);
  952. JsUtil::JobProcessor *GetJobProcessor();
  953. Js::Var * GetBailOutRegisterSaveSpace() const { return bailOutRegisterSaveSpace; }
  954. virtual intptr_t GetBailOutRegisterSaveSpaceAddr() const override { return (intptr_t)bailOutRegisterSaveSpace; }
  955. #if !FLOATVAR
  956. CodeGenNumberThreadAllocator * GetCodeGenNumberThreadAllocator() const
  957. {
  958. return codeGenNumberThreadAllocator;
  959. }
  960. XProcNumberPageSegmentManager * GetXProcNumberPageSegmentManager() const
  961. {
  962. return this->xProcNumberPageSegmentManager;
  963. }
  964. #endif
  965. #endif
  966. void ResetFunctionCount() { Assert(this->GetScriptSiteHolderCount() == 0); this->functionCount = 0; }
  967. void PushEntryExitRecord(Js::ScriptEntryExitRecord *);
  968. void PopEntryExitRecord(Js::ScriptEntryExitRecord *);
  969. uint EnterScriptStart(Js::ScriptEntryExitRecord *, bool doCleanup);
  970. void EnterScriptEnd(Js::ScriptEntryExitRecord *, bool doCleanup);
  971. template <bool leaveForHost>
  972. void LeaveScriptStart(void *);
  973. template <bool leaveForHost>
  974. void LeaveScriptEnd(void *);
  975. void DisposeOnLeaveScript();
  976. void PushInterpreterFrame(Js::InterpreterStackFrame *interpreterFrame);
  977. Js::InterpreterStackFrame *PopInterpreterFrame();
  978. Js::InterpreterStackFrame *GetLeafInterpreterFrame() const { return leafInterpreterFrame; }
  979. Js::TempArenaAllocatorObject * GetTemporaryAllocator(LPCWSTR name);
  980. void ReleaseTemporaryAllocator(Js::TempArenaAllocatorObject * tempAllocator);
  981. Js::TempGuestArenaAllocatorObject * GetTemporaryGuestAllocator(LPCWSTR name);
  982. void ReleaseTemporaryGuestAllocator(Js::TempGuestArenaAllocatorObject * tempAllocator);
  983. // Should be called from script context, at the time when construction for scriptcontext is just done.
  984. void EnsureDebugManager();
  985. // Should be called from script context 's destructor,
  986. void ReleaseDebugManager();
  987. void RegisterScriptContext(Js::ScriptContext *scriptContext);
  988. void UnregisterScriptContext(Js::ScriptContext *scriptContext);
  989. // NoScriptScope
  990. void SetNoScriptScope(bool noScriptScope) { this->noScriptScope = noScriptScope; }
  991. bool IsNoScriptScope() { return this->noScriptScope; }
  992. Js::EntryPointInfo ** RegisterEquivalentTypeCacheEntryPoint(Js::EntryPointInfo * entryPoint);
  993. void UnregisterEquivalentTypeCacheEntryPoint(Js::EntryPointInfo ** entryPoint);
  994. void RegisterProtoInlineCache(Js::InlineCache * inlineCache, Js::PropertyId propertyId);
  995. void RegisterStoreFieldInlineCache(Js::InlineCache * inlineCache, Js::PropertyId propertyId);
  996. void NotifyInlineCacheBatchUnregistered(uint count);
  997. #if DBG
  998. bool IsProtoInlineCacheRegistered(const Js::InlineCache * inlineCache, Js::PropertyId propertyId);
  999. bool IsStoreFieldInlineCacheRegistered(const Js::InlineCache * inlineCache, Js::PropertyId propertyId);
  1000. #endif
  1001. #if ENABLE_NATIVE_CODEGEN
  1002. Js::PropertyGuard* RegisterSharedPropertyGuard(Js::PropertyId propertyId);
  1003. void RegisterLazyBailout(Js::PropertyId propertyId, Js::EntryPointInfo* entryPoint);
  1004. void RegisterUniquePropertyGuard(Js::PropertyId propertyId, Js::PropertyGuard* guard);
  1005. void RegisterUniquePropertyGuard(Js::PropertyId propertyId, RecyclerWeakReference<Js::PropertyGuard>* guardWeakRef);
  1006. void RegisterConstructorCache(Js::PropertyId propertyId, Js::ConstructorCache* cache);
  1007. #endif
  1008. virtual size_t GetScriptStackLimit() const override;
  1009. virtual HANDLE GetProcessHandle() const override;
  1010. virtual intptr_t GetThreadStackLimitAddr() const override;
  1011. #if ENABLE_NATIVE_CODEGEN && defined(ENABLE_SIMDJS) && (defined(_M_IX86) || defined(_M_X64))
  1012. virtual intptr_t GetSimdTempAreaAddr(uint8 tempIndex) const override;
  1013. #endif
  1014. virtual intptr_t GetDisableImplicitFlagsAddr() const override;
  1015. virtual intptr_t GetImplicitCallFlagsAddr() const override;
  1016. ptrdiff_t GetChakraBaseAddressDifference() const;
  1017. ptrdiff_t GetCRTBaseAddressDifference() const;
  1018. private:
  1019. void RegisterInlineCache(InlineCacheListMapByPropertyId& inlineCacheMap, Js::InlineCache* inlineCache, Js::PropertyId propertyId);
  1020. static bool IsInlineCacheRegistered(InlineCacheListMapByPropertyId& inlineCacheMap, const Js::InlineCache* inlineCache, Js::PropertyId propertyId);
  1021. void InvalidateAndDeleteInlineCacheList(InlineCacheList *inlineCacheList);
  1022. void CompactInlineCacheList(InlineCacheList *inlineCacheList);
  1023. void CompactInlineCacheInvalidationLists();
  1024. void CompactProtoInlineCaches();
  1025. void CompactStoreFieldInlineCaches();
  1026. #if DBG
  1027. static bool IsInlineCacheInList(const Js::InlineCache* inlineCache, const InlineCacheList* inlineCacheChain);
  1028. #endif
  1029. #if ENABLE_NATIVE_CODEGEN
  1030. void InvalidateFixedFieldGuard(Js::PropertyGuard* guard);
  1031. PropertyGuardEntry* EnsurePropertyGuardEntry(const Js::PropertyRecord* propertyRecord, bool& foundExistingEntry);
  1032. void InvalidatePropertyGuardEntry(const Js::PropertyRecord* propertyRecord, PropertyGuardEntry* entry, bool isAllPropertyGuardsInvalidation);
  1033. #endif
  1034. public:
  1035. class AutoDisableExpiration
  1036. {
  1037. public:
  1038. AutoDisableExpiration(ThreadContext* threadContext):
  1039. _threadContext(threadContext),
  1040. _oldExpirationDisabled(threadContext->disableExpiration)
  1041. {
  1042. _threadContext->disableExpiration = true;
  1043. }
  1044. ~AutoDisableExpiration()
  1045. {
  1046. _threadContext->disableExpiration = _oldExpirationDisabled;
  1047. }
  1048. private:
  1049. ThreadContext* _threadContext;
  1050. bool _oldExpirationDisabled;
  1051. };
  1052. void InvalidateProtoInlineCaches(Js::PropertyId propertyId);
  1053. void InvalidateStoreFieldInlineCaches(Js::PropertyId propertyId);
  1054. void InvalidateAllProtoInlineCaches();
  1055. #if DBG
  1056. bool IsObjectRegisteredInProtoInlineCaches(Js::DynamicObject * object);
  1057. bool IsObjectRegisteredInStoreFieldInlineCaches(Js::DynamicObject * object);
  1058. #endif
  1059. bool AreAllProtoInlineCachesInvalidated();
  1060. void InvalidateAllStoreFieldInlineCaches();
  1061. bool AreAllStoreFieldInlineCachesInvalidated();
  1062. void InvalidatePropertyGuards(Js::PropertyId propertyId);
  1063. void InvalidateAllPropertyGuards();
  1064. void RegisterIsInstInlineCache(Js::IsInstInlineCache * inlineCache, Js::Var function);
  1065. void UnregisterIsInstInlineCache(Js::IsInstInlineCache * inlineCache, Js::Var function);
  1066. #if DBG
  1067. bool IsIsInstInlineCacheRegistered(Js::IsInstInlineCache * inlineCache, Js::Var function);
  1068. #endif
  1069. private:
  1070. void InvalidateIsInstInlineCacheList(Js::IsInstInlineCache* inlineCacheList);
  1071. #if DBG
  1072. bool IsIsInstInlineCacheInList(const Js::IsInstInlineCache* inlineCache, const Js::IsInstInlineCache* inlineCacheList);
  1073. #endif
  1074. public:
  1075. void InvalidateIsInstInlineCachesForFunction(Js::Var function);
  1076. void InvalidateAllIsInstInlineCaches();
  1077. bool AreAllIsInstInlineCachesInvalidated() const;
  1078. #ifdef PERSISTENT_INLINE_CACHES
  1079. void ClearInlineCachesWithDeadWeakRefs();
  1080. #endif
  1081. void ClearInvalidatedUniqueGuards();
  1082. void ClearInlineCaches();
  1083. void ClearIsInstInlineCaches();
  1084. void ClearForInCaches();
  1085. void ClearEquivalentTypeCaches();
  1086. void ClearScriptContextCaches();
  1087. void RegisterTypeWithProtoPropertyCache(const Js::PropertyId propertyId, Js::Type *const type);
  1088. void InvalidateProtoTypePropertyCaches(const Js::PropertyId propertyId);
  1089. void InternalInvalidateProtoTypePropertyCaches(const Js::PropertyId propertyId);
  1090. void InvalidateAllProtoTypePropertyCaches();
  1091. Js::ScriptContext ** RegisterPrototypeChainEnsuredToHaveOnlyWritableDataPropertiesScriptContext(Js::ScriptContext * scriptContext);
  1092. void UnregisterPrototypeChainEnsuredToHaveOnlyWritableDataPropertiesScriptContext(Js::ScriptContext ** scriptContext);
  1093. void ClearPrototypeChainEnsuredToHaveOnlyWritableDataPropertiesCaches();
  1094. BOOL HasUnhandledException() const { return hasUnhandledException; }
  1095. void SetHasUnhandledException() {hasUnhandledException = TRUE; }
  1096. void ResetHasUnhandledException() {hasUnhandledException = FALSE; }
  1097. void SetUnhandledExceptionObject(Js::JavascriptExceptionObject* exceptionObject) {recyclableData->unhandledExceptionObject = exceptionObject; }
  1098. Js::JavascriptExceptionObject* GetUnhandledExceptionObject() const { return recyclableData->unhandledExceptionObject; };
  1099. // To temporarily keep throwing exception object alive (thrown but not yet caught)
  1100. Js::JavascriptExceptionObject** SaveTempUncaughtException(Js::JavascriptExceptionObject* exceptionObject)
  1101. {
  1102. // Previous save should have been caught and cleared
  1103. Assert(recyclableData->tempUncaughtException == nullptr);
  1104. recyclableData->tempUncaughtException = exceptionObject;
  1105. return &recyclableData->tempUncaughtException;
  1106. }
  1107. bool HasCatchHandler() const { return hasCatchHandler; }
  1108. void SetHasCatchHandler(bool hasCatchHandler) { this->hasCatchHandler = hasCatchHandler; }
  1109. bool IsUserCode() const { return this->hasCatchHandlerToUserCode; }
  1110. void SetIsUserCode(bool set) { this->hasCatchHandlerToUserCode = set; }
  1111. void QueueFreeOldEntryPointInfoIfInScript(Js::FunctionEntryPointInfo* oldEntryPointInfo)
  1112. {
  1113. if (this->IsInScript())
  1114. {
  1115. // Add it to the list only if it's not already in it
  1116. if (oldEntryPointInfo->nextEntryPoint == nullptr && !oldEntryPointInfo->IsCleanedUp())
  1117. {
  1118. oldEntryPointInfo->nextEntryPoint = recyclableData->oldEntryPointInfo;
  1119. recyclableData->oldEntryPointInfo = oldEntryPointInfo;
  1120. }
  1121. }
  1122. }
  1123. static BOOLEAN IsOnStack(void const *ptr);
  1124. _NOINLINE bool IsStackAvailable(size_t size);
  1125. _NOINLINE bool IsStackAvailableNoThrow(size_t size = Js::Constants::MinStackDefault);
  1126. static bool IsCurrentStackAvailable(size_t size);
  1127. void ProbeStackNoDispose(size_t size, Js::ScriptContext *scriptContext, PVOID returnAddress = nullptr);
  1128. void ProbeStack(size_t size, Js::ScriptContext *scriptContext, PVOID returnAddress = nullptr);
  1129. void ProbeStack(size_t size, Js::RecyclableObject * obj, Js::ScriptContext *scriptContext);
  1130. void ProbeStack(size_t size);
  1131. static void __stdcall ProbeCurrentStackNoDispose(size_t size, Js::ScriptContext *scriptContext);
  1132. static void __stdcall ProbeCurrentStack(size_t size, Js::ScriptContext *scriptContext);
  1133. static void __stdcall ProbeCurrentStack2(size_t size, Js::ScriptContext *scriptContext, uint32 u1, uint32 u2)
  1134. {
  1135. ProbeCurrentStack(size, scriptContext);
  1136. }
  1137. #if ENABLE_PROFILE_INFO
  1138. void ThreadContext::EnsureSourceProfileManagersByUrlMap();
  1139. Js::SourceDynamicProfileManager* GetSourceDynamicProfileManager(_In_z_ const WCHAR* url, _In_ uint hash, _Inout_ bool* addref);
  1140. uint ReleaseSourceDynamicProfileManagers(const WCHAR* url);
  1141. #endif
  1142. void EnsureSymbolRegistrationMap();
  1143. const Js::PropertyRecord* GetSymbolFromRegistrationMap(const char16* stringKey);
  1144. const Js::PropertyRecord* AddSymbolToRegistrationMap(const char16* stringKey, charcount_t stringLength);
  1145. inline void ClearPendingSOError()
  1146. {
  1147. this->GetPendingSOErrorObject()->ClearError();
  1148. }
  1149. inline void ClearPendingOOMError()
  1150. {
  1151. this->GetPendingOOMErrorObject()->ClearError();
  1152. }
  1153. Js::JavascriptExceptionObject *GetPendingSOErrorObject()
  1154. {
  1155. Assert(recyclableData->soErrorObject.IsPendingExceptionObject());
  1156. return &recyclableData->soErrorObject;
  1157. }
  1158. Js::JavascriptExceptionObject *GetPendingOOMErrorObject()
  1159. {
  1160. Assert(recyclableData->oomErrorObject.IsPendingExceptionObject());
  1161. return &recyclableData->oomErrorObject;
  1162. }
  1163. Js::JavascriptExceptionObject *GetPendingTerminatedErrorObject()
  1164. {
  1165. return &recyclableData->terminatedErrorObject;
  1166. }
  1167. Js::JavascriptExceptionObject* GetRecordedException()
  1168. {
  1169. return recyclableData->exceptionObject;
  1170. }
  1171. bool GetPropagateException()
  1172. {
  1173. return recyclableData->propagateException;
  1174. }
  1175. void SetHasThrownPendingException()
  1176. {
  1177. Assert(this->IsInScript());
  1178. this->hasThrownPendingException = true;
  1179. }
  1180. void SetRecordedException(Js::JavascriptExceptionObject* exceptionObject, bool propagateToDebugger = false)
  1181. {
  1182. this->recyclableData->exceptionObject = exceptionObject;
  1183. this->recyclableData->propagateException = propagateToDebugger;
  1184. }
  1185. #ifdef ENABLE_CUSTOM_ENTROPY
  1186. Entropy& GetEntropy()
  1187. {
  1188. return entropy;
  1189. }
  1190. #endif
  1191. Js::ImplicitCallFlags * GetAddressOfImplicitCallFlags()
  1192. {
  1193. return &implicitCallFlags;
  1194. }
  1195. DisableImplicitFlags * GetAddressOfDisableImplicitFlags()
  1196. {
  1197. return &disableImplicitFlags;
  1198. }
  1199. Js::ImplicitCallFlags GetImplicitCallFlags()
  1200. {
  1201. return implicitCallFlags;
  1202. }
  1203. void SetImplicitCallFlags(Js::ImplicitCallFlags flags)
  1204. {
  1205. //Note: this action is inlined into JITed code in Lowerer::GenerateCallProfiling.
  1206. // if you change this, you might want to add it there too.
  1207. implicitCallFlags = flags;
  1208. }
  1209. void ClearImplicitCallFlags();
  1210. void ClearImplicitCallFlags(Js::ImplicitCallFlags flags);
  1211. void AddImplicitCallFlags(Js::ImplicitCallFlags flags)
  1212. {
  1213. SetImplicitCallFlags((Js::ImplicitCallFlags)(implicitCallFlags | flags));
  1214. }
  1215. void CheckAndResetImplicitCallAccessorFlag();
  1216. template <class Fn>
  1217. inline Js::Var ExecuteImplicitCall(Js::RecyclableObject * function, Js::ImplicitCallFlags flags, Fn implicitCall)
  1218. {
  1219. // For now, we will not allow Function that is marked as HasNoSideEffect to be called, and we will just bailout.
  1220. // These function may still throw exceptions, so we will need to add checks with RecordImplicitException
  1221. // so that we don't throw exception when disableImplicitCall is set before we allow these function to be called
  1222. // as an optimization. (These functions are valueOf and toString calls for built-in non primitive types)
  1223. Js::FunctionInfo::Attributes attributes = Js::FunctionInfo::GetAttributes(function);
  1224. // we can hoist out const method if we know the function doesn't have side effect,
  1225. // and the value can be hoisted.
  1226. if (this->HasNoSideEffect(function, attributes))
  1227. {
  1228. // Has no side effect means the function does not change global value or
  1229. // will check for implicit call flags
  1230. return implicitCall();
  1231. }
  1232. // Don't call the implicit call if disable implicit call
  1233. if (IsDisableImplicitCall())
  1234. {
  1235. AddImplicitCallFlags(flags);
  1236. // Return "undefined" just so we have a valid var, in case subsequent instructions are executed
  1237. // before we bail out.
  1238. return function->GetScriptContext()->GetLibrary()->GetUndefined();
  1239. }
  1240. if ((attributes & Js::FunctionInfo::HasNoSideEffect) != 0)
  1241. {
  1242. // Has no side effect means the function does not change global value or
  1243. // will check for implicit call flags
  1244. return implicitCall();
  1245. }
  1246. // Save and restore implicit flags around the implicit call
  1247. Js::ImplicitCallFlags saveImplicitCallFlags = this->GetImplicitCallFlags();
  1248. Js::Var result = implicitCall();
  1249. this->SetImplicitCallFlags((Js::ImplicitCallFlags)(saveImplicitCallFlags | flags));
  1250. return result;
  1251. }
  1252. bool HasNoSideEffect(Js::RecyclableObject * function) const;
  1253. bool HasNoSideEffect(Js::RecyclableObject * function, Js::FunctionInfo::Attributes attr) const;
  1254. bool RecordImplicitException();
  1255. DisableImplicitFlags GetDisableImplicitFlags() const { return disableImplicitFlags; }
  1256. void SetDisableImplicitFlags(DisableImplicitFlags flags) { disableImplicitFlags = flags; }
  1257. bool IsDisableImplicitCall() const { return (disableImplicitFlags & DisableImplicitCallFlag) != 0; }
  1258. bool IsDisableImplicitException() const { return (disableImplicitFlags & DisableImplicitExceptionFlag) != 0; }
  1259. void DisableImplicitCall() { disableImplicitFlags = (DisableImplicitFlags)(disableImplicitFlags | DisableImplicitCallFlag); }
  1260. void ClearDisableImplicitFlags() { disableImplicitFlags = DisableImplicitNoFlag; }
  1261. virtual uint GetRandomNumber() override;
  1262. // DefaultCollectWrapper
  1263. virtual void PreCollectionCallBack(CollectionFlags flags) override;
  1264. virtual void PreSweepCallback() override;
  1265. virtual void WaitCollectionCallBack() override;
  1266. virtual void PostCollectionCallBack() override;
  1267. virtual BOOL ExecuteRecyclerCollectionFunction(Recycler * recycler, CollectionFunction function, CollectionFlags flags) override;
  1268. #ifdef FAULT_INJECTION
  1269. virtual void DisposeScriptContextByFaultInjectionCallBack() override;
  1270. #endif
  1271. virtual void DisposeObjects(Recycler * recycler) override;
  1272. typedef DList<ExpirableObject*, ArenaAllocator> ExpirableObjectList;
  1273. ExpirableObjectList* expirableObjectList;
  1274. ExpirableObjectList* expirableObjectDisposeList;
  1275. int numExpirableObjects;
  1276. int expirableCollectModeGcCount;
  1277. bool disableExpiration;
  1278. bool InExpirableCollectMode();
  1279. void TryEnterExpirableCollectMode();
  1280. void TryExitExpirableCollectMode();
  1281. void RegisterExpirableObject(ExpirableObject* object);
  1282. void UnregisterExpirableObject(ExpirableObject* object);
  1283. void DisposeExpirableObject(ExpirableObject* object);
  1284. void * GetDynamicObjectEnumeratorCache(Js::DynamicType const * dynamicType);
  1285. void AddDynamicObjectEnumeratorCache(Js::DynamicType const * dynamicType, void * cache);
  1286. public:
  1287. bool IsScriptActive() const { return isScriptActive; }
  1288. void SetIsScriptActive(bool isActive) { isScriptActive = isActive; }
  1289. bool IsExecutionDisabled() const
  1290. {
  1291. return this->GetStackLimitForCurrentThread() == Js::Constants::StackLimitForScriptInterrupt;
  1292. }
  1293. void DisableExecution();
  1294. void EnableExecution();
  1295. bool TestThreadContextFlag(ThreadContextFlags threadContextFlag) const;
  1296. void SetThreadContextFlag(ThreadContextFlags threadContextFlag);
  1297. void ClearThreadContextFlag(ThreadContextFlags threadContextFlag);
  1298. void SetForceOneIdleCollection();
  1299. bool IsInThreadServiceCallback() const { return threadService.IsInCallback(); }
  1300. Js::DebugManager * GetDebugManager() const { return this->debugManager; }
  1301. const NativeLibraryEntryRecord::Entry* PeekNativeLibraryEntry() const { return this->nativeLibraryEntry.Peek(); }
  1302. void PushNativeLibraryEntry(_In_ NativeLibraryEntryRecord::Entry* entry) { this->nativeLibraryEntry.Push(entry); }
  1303. void PopNativeLibraryEntry() { this->nativeLibraryEntry.Pop(); }
  1304. bool IsProfilingUserCode() const { return isProfilingUserCode; }
  1305. void SetIsProfilingUserCode(bool value) { isProfilingUserCode = value; }
  1306. #if DBG_DUMP
  1307. uint scriptSiteCount;
  1308. #endif
  1309. #ifdef BAILOUT_INJECTION
  1310. uint bailOutByteCodeLocationCount;
  1311. #endif
  1312. #ifdef DYNAMIC_PROFILE_MUTATOR
  1313. DynamicProfileMutator * dynamicProfileMutator;
  1314. #endif
  1315. //
  1316. // Regex helpers
  1317. //
  1318. UnifiedRegex::StandardChars<uint8>* GetStandardChars(__inout_opt uint8* dummy);
  1319. UnifiedRegex::StandardChars<char16>* GetStandardChars(__inout_opt char16* dummy);
  1320. bool IsOptimizedForManyInstances() const { return isOptimizedForManyInstances; }
  1321. void OptimizeForManyInstances(const bool optimizeForManyInstances)
  1322. {
  1323. Assert(!recycler || optimizeForManyInstances == isOptimizedForManyInstances); // mode cannot be changed after recycler is created
  1324. isOptimizedForManyInstances = optimizeForManyInstances;
  1325. }
  1326. #if ENABLE_NATIVE_CODEGEN
  1327. bool IsBgJitEnabled() const { return bgJit; }
  1328. void EnableBgJit(const bool enableBgJit)
  1329. {
  1330. Assert(!jobProcessor || enableBgJit == bgJit);
  1331. bgJit = enableBgJit;
  1332. }
  1333. #endif
  1334. void* GetJSRTRuntime() const { return jsrtRuntime; }
  1335. void SetJSRTRuntime(void* runtime);
  1336. private:
  1337. BOOL ExecuteRecyclerCollectionFunctionCommon(Recycler * recycler, CollectionFunction function, CollectionFlags flags);
  1338. void DoInvalidateProtoTypePropertyCaches(const Js::PropertyId propertyId, TypeHashSet *const typeHashSet);
  1339. void InitializePropertyMaps();
  1340. void CreateNoCasePropertyMap();
  1341. InterruptPoller *interruptPoller;
  1342. void CollectionCallBack(RecyclerCollectCallBackFlags flags);
  1343. // Cache used by HostDispatch::GetBuiltInOperationFromEntryPoint
  1344. private:
  1345. JsUtil::BaseDictionary<Js::JavascriptMethod, uint, ArenaAllocator, PowerOf2SizePolicy> entryPointToBuiltInOperationIdCache;
  1346. public:
  1347. bool IsEntryPointToBuiltInOperationIdCacheInitialized()
  1348. {
  1349. return entryPointToBuiltInOperationIdCache.Count() != 0;
  1350. }
  1351. bool GetBuiltInOperationIdFromEntryPoint(Js::JavascriptMethod entryPoint, uint * id)
  1352. {
  1353. return entryPointToBuiltInOperationIdCache.TryGetValue(entryPoint, id);
  1354. }
  1355. void SetBuiltInOperationIdForEntryPoint(Js::JavascriptMethod entryPoint, uint id)
  1356. {
  1357. entryPointToBuiltInOperationIdCache.Add(entryPoint, id);
  1358. }
  1359. void ResetEntryPointToBuiltInOperationIdCache()
  1360. {
  1361. entryPointToBuiltInOperationIdCache.ResetNoDelete();
  1362. }
  1363. uint8 LoopDepth() const
  1364. {
  1365. return loopDepth;
  1366. }
  1367. void SetLoopDepth(const uint8 loopDepth)
  1368. {
  1369. this->loopDepth = loopDepth;
  1370. }
  1371. void IncrementLoopDepth()
  1372. {
  1373. if(loopDepth != UCHAR_MAX)
  1374. {
  1375. ++loopDepth;
  1376. }
  1377. }
  1378. void DecrementLoopDepth()
  1379. {
  1380. if(loopDepth != 0)
  1381. {
  1382. --loopDepth;
  1383. }
  1384. }
  1385. #if defined(CHECK_MEMORY_LEAK) || defined(LEAK_REPORT)
  1386. static void ReportAndCheckLeaksOnProcessDetach();
  1387. #endif
  1388. #ifdef LEAK_REPORT
  1389. void SetRootTrackerScriptContext(Js::ScriptContext * scriptContext);
  1390. void ClearRootTrackerScriptContext(Js::ScriptContext * scriptContext);
  1391. private:
  1392. Js::ScriptContext * rootTrackerScriptContext;
  1393. DWORD threadId;
  1394. #endif
  1395. };
  1396. extern void(*InitializeAdditionalProperties)(ThreadContext *threadContext);
  1397. // Temporarily set script profiler isProfilingUserCode state, restore at destructor
  1398. class AutoProfilingUserCode
  1399. {
  1400. private:
  1401. ThreadContext* threadContext;
  1402. const bool oldIsProfilingUserCode;
  1403. public:
  1404. AutoProfilingUserCode(ThreadContext* threadContext, bool isProfilingUserCode) :
  1405. threadContext(threadContext),
  1406. oldIsProfilingUserCode(threadContext->IsProfilingUserCode())
  1407. {
  1408. threadContext->SetIsProfilingUserCode(isProfilingUserCode);
  1409. }
  1410. ~AutoProfilingUserCode()
  1411. {
  1412. threadContext->SetIsProfilingUserCode(oldIsProfilingUserCode);
  1413. }
  1414. };