ThreadContext.h 78 KB

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