ScriptContext.h 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688
  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. #ifdef ENABLE_SCRIPT_PROFILING
  7. #include "activprof.h"
  8. #endif
  9. #if DBG || ENABLE_REGEX_CONFIG_OPTIONS || defined(PROFILE_STRINGS)
  10. #define NEED_MISC_ALLOCATOR
  11. #endif
  12. #define BuiltInFunctionsScriptId 0
  13. class NativeCodeGenerator;
  14. class BackgroundParser;
  15. struct IActiveScriptDirect;
  16. #ifdef ENABLE_BASIC_TELEMETRY
  17. class ScriptContextTelemetry;
  18. #endif
  19. namespace Js
  20. {
  21. class ScriptContext;
  22. class ScriptEditQuery;
  23. class MutationBreakpoint;
  24. class StringProfiler;
  25. class DebugContext;
  26. struct HaltCallback;
  27. struct DebuggerOptionsCallback;
  28. class ModuleRecordBase;
  29. }
  30. // Created for every source buffer passed by host.
  31. // This structure has all the details.
  32. class SRCINFO
  33. {
  34. // We currently don't free SRCINFO object so we don't want to add extra variables here.
  35. // In future, when we do make it freeable and will be able to allocate more than one per Module,
  36. // we can move variables m_isGlobalFunc and m_isEval from FunctionBody.cpp here.
  37. public:
  38. SourceContextInfo * sourceContextInfo;
  39. ULONG dlnHost; // Line number passed to ParseScriptText
  40. ULONG ulColumnHost; // Column number on the line where the parse script text started
  41. ULONG lnMinHost; // Line offset of first host-supplied line
  42. ULONG ichMinHost; // Range of host supplied characters
  43. ULONG ichLimHost;
  44. ULONG ulCharOffset; // Char offset of the source text relative to the document. (Populated using IActiveScriptContext)
  45. Js::ModuleID moduleID;
  46. ULONG grfsi;
  47. static SRCINFO* Copy(Recycler* recycler, const SRCINFO* srcInfo)
  48. {
  49. SRCINFO* copySrcInfo = RecyclerNew(recycler, SRCINFO, *srcInfo);
  50. return copySrcInfo;
  51. }
  52. SRCINFO* Clone(Js::ScriptContext* scriptContext) const;
  53. };
  54. struct CustomExternalObjectOperations
  55. {
  56. size_t offsetOfOperationsUsage;
  57. DWORD operationFlagEquals;
  58. DWORD operationFlagStrictEquals;
  59. };
  60. enum ExternalJitData
  61. {
  62. ExternalJitData_CustomExternalObjectOperations
  63. };
  64. enum LoadScriptFlag
  65. {
  66. LoadScriptFlag_None = 0x0,
  67. LoadScriptFlag_Expression = 0x1, // the script returns a value.
  68. LoadScriptFlag_disableDeferredParse = 0x2, // do not defer-parse the code.
  69. LoadScriptFlag_isByteCodeBufferForLibrary = 0x4, // for bytecode buffer
  70. LoadScriptFlag_disableAsmJs = 0x8, // disable parse as asmjs. The code is not conform to asmjs requirement.
  71. LoadScriptFlag_Module = 0x10, // input script is module code.
  72. LoadScriptFlag_isFunction = 0x20, // input script is in a function scope, not global code.
  73. LoadScriptFlag_Utf8Source = 0x40, // input buffer is utf8 encoded.
  74. LoadScriptFlag_LibraryCode = 0x80 // for debugger, indicating 'not my code'
  75. };
  76. class HostScriptContext
  77. {
  78. public:
  79. HostScriptContext(Js::ScriptContext* inScriptContext) { this->scriptContext = inScriptContext; }
  80. virtual void Delete() = 0;
  81. virtual HRESULT GetPreviousHostScriptContext(__deref_out HostScriptContext** ppUnkCaller) = 0;
  82. virtual HRESULT PushHostScriptContext() = 0;
  83. virtual void PopHostScriptContext() = 0;
  84. virtual HRESULT SetCaller(IUnknown *punkNew, IUnknown **ppunkPrev) = 0;
  85. virtual HRESULT GetDispatchExCaller(__deref_out void** dispatchExCaller) = 0;
  86. virtual void ReleaseDispatchExCaller(__in void* dispatchExCaler) = 0;
  87. virtual Js::ModuleRoot * GetModuleRoot(int moduleID) = 0;
  88. virtual HRESULT CheckCrossDomainScriptContext(__in Js::ScriptContext* scriptContext) = 0;
  89. virtual HRESULT GetHostContextUrl(__in DWORD_PTR hostSourceContext, __out BSTR& pUrl) = 0;
  90. virtual BOOL HasCaller() = 0;
  91. virtual void CleanDynamicCodeCache() = 0;
  92. virtual HRESULT VerifyDOMSecurity(Js::ScriptContext* targetContext, Js::Var obj) = 0;
  93. virtual HRESULT CheckEvalRestriction() = 0;
  94. virtual HRESULT HostExceptionFromHRESULT(HRESULT hr, Js::Var* outError) = 0;
  95. virtual HRESULT GetExternalJitData(ExternalJitData id, void *data) = 0;
  96. virtual HRESULT SetDispatchInvoke(Js::JavascriptMethod dispatchInvoke) = 0;
  97. virtual HRESULT ArrayBufferFromExternalObject(__in Js::RecyclableObject *obj,
  98. __out Js::ArrayBuffer **ppArrayBuffer) = 0;
  99. virtual Js::JavascriptError* CreateWinRTError(IErrorInfo* perrinfo, Js::RestrictedErrorStrings * proerrstr) = 0;
  100. virtual Js::JavascriptFunction* InitializeHostPromiseContinuationFunction() = 0;
  101. virtual HRESULT FetchImportedModule(Js::ModuleRecordBase* referencingModule, LPCOLESTR specifier, Js::ModuleRecordBase** dependentModuleRecord) = 0;
  102. virtual HRESULT NotifyHostAboutModuleReady(Js::ModuleRecordBase* referencingModule, Js::Var exceptionVar) = 0;
  103. Js::ScriptContext* GetScriptContext() { return scriptContext; }
  104. virtual bool SetCrossSiteForFunctionType(Js::JavascriptFunction * function) = 0;
  105. #if DBG_DUMP || defined(PROFILE_EXEC) || defined(PROFILE_MEM)
  106. virtual void EnsureParentInfo(Js::ScriptContext* scriptContext = NULL) = 0;
  107. #endif
  108. #if DBG
  109. virtual bool IsHostCrossSiteThunk(Js::JavascriptMethod address) = 0;
  110. #endif
  111. private:
  112. Js::ScriptContext* scriptContext;
  113. };
  114. namespace Js
  115. {
  116. #pragma pack(push, 1)
  117. struct StackFrameInfo
  118. {
  119. StackFrameInfo() { }
  120. StackFrameInfo(DWORD_PTR _scriptContextID
  121. , UINT32 _sourceLocationLineNumber
  122. , UINT32 _sourceLocationColumnNumber
  123. , UINT32 _methodIDOrNameIndex
  124. , UINT8 _isFrameIndex)
  125. : scriptContextID(_scriptContextID)
  126. , sourceLocationLineNumber(_sourceLocationLineNumber)
  127. , sourceLocationColumnNumber(_sourceLocationColumnNumber)
  128. , methodIDOrNameIndex(_methodIDOrNameIndex)
  129. , isFrameIndex(_isFrameIndex)
  130. { }
  131. DWORD_PTR scriptContextID;
  132. UINT32 sourceLocationLineNumber;
  133. UINT32 sourceLocationColumnNumber;
  134. UINT32 methodIDOrNameIndex;
  135. UINT8 isFrameIndex;
  136. };
  137. #pragma pack(pop)
  138. #ifdef ENABLE_PROJECTION
  139. class ProjectionConfiguration
  140. {
  141. public:
  142. ProjectionConfiguration() : targetVersion(0)
  143. {
  144. }
  145. DWORD GetTargetVersion() const { return this->targetVersion; }
  146. void SetTargetVersion(DWORD version) { this->targetVersion = version; }
  147. bool IsTargetWindows8() const { return this->targetVersion == NTDDI_WIN8; }
  148. bool IsTargetWindowsBlueOrLater() const { return this->targetVersion >= NTDDI_WINBLUE; }
  149. private:
  150. DWORD targetVersion;
  151. };
  152. #endif // ENABLE_PROJECTION
  153. class ScriptConfiguration
  154. {
  155. public:
  156. ScriptConfiguration(const ThreadConfiguration * const threadConfig, const bool isOptimizedForManyInstances) :
  157. #ifdef ENABLE_PROJECTION
  158. HostType(Configuration::Global.flags.HostType),
  159. WinRTConstructorAllowed(Configuration::Global.flags.WinRTConstructorAllowed),
  160. #endif
  161. NoNative(Configuration::Global.flags.NoNative),
  162. isOptimizedForManyInstances(isOptimizedForManyInstances),
  163. threadConfig(threadConfig)
  164. {
  165. }
  166. // Version
  167. bool SupportsES3() const { return true; }
  168. bool SupportsES3Extensions() const {
  169. #ifdef ENABLE_PROJECTION
  170. return HostType != HostTypeApplication;
  171. #else
  172. return true;
  173. #endif
  174. }
  175. #define FORWARD_THREAD_CONFIG(flag) inline bool flag() const { return threadConfig->flag(); }
  176. #define FLAG(threadFlag, globalFlag) FORWARD_THREAD_CONFIG(threadFlag)
  177. #define FLAG_RELEASE(threadFlag, globalFlag) FORWARD_THREAD_CONFIG(threadFlag)
  178. #include "../Base/ThreadConfigFlagsList.h"
  179. #undef FLAG_RELEASE
  180. #undef FLAG
  181. #undef FORWARD_THREAD_CONFIG
  182. bool SupportsCollectGarbage() const { return true; }
  183. bool IsTypedArrayEnabled() const { return true; }
  184. void ForceNoNative() { this->NoNative = true; }
  185. void ForceNative() { this->NoNative = false; }
  186. bool IsNoNative() const { return this->NoNative; }
  187. void SetCanOptimizeGlobalLookupFlag(BOOL f){ this->fCanOptimizeGlobalLookup = f;}
  188. BOOL CanOptimizeGlobalLookup() const { return this->fCanOptimizeGlobalLookup;}
  189. bool IsOptimizedForManyInstances() const { return isOptimizedForManyInstances; }
  190. void CopyFrom(ScriptConfiguration& other)
  191. {
  192. this->NoNative = other.NoNative;
  193. this->fCanOptimizeGlobalLookup = other.fCanOptimizeGlobalLookup;
  194. #ifdef ENABLE_PROJECTION
  195. this->HostType = other.HostType;
  196. this->WinRTConstructorAllowed = other.WinRTConstructorAllowed;
  197. this->projectionConfiguration = other.projectionConfiguration;
  198. #endif
  199. }
  200. #ifdef ENABLE_PROJECTION
  201. Number GetHostType() const // Returns one of enum HostType values (see ConfigFlagsTable.h).
  202. {
  203. AssertMsg(this->HostType >= HostTypeMin && this->HostType <= HostTypeMax, "HostType value is out of valid range.");
  204. return this->HostType;
  205. }
  206. ProjectionConfiguration const * GetProjectionConfig() const
  207. {
  208. return &projectionConfiguration;
  209. }
  210. void SetHostType(long hostType) { this->HostType = hostType; }
  211. void SetWinRTConstructorAllowed(bool allowed) { this->WinRTConstructorAllowed = allowed; }
  212. void SetProjectionTargetVersion(DWORD version)
  213. {
  214. projectionConfiguration.SetTargetVersion(version);
  215. }
  216. bool IsWinRTEnabled() const { return (GetHostType() == Js::HostTypeApplication) || (GetHostType() == Js::HostTypeWebview); }
  217. bool IsWinRTConstructorAllowed() const { return (GetHostType() != Js::HostTypeWebview) || this->WinRTConstructorAllowed; }
  218. #endif
  219. private:
  220. // Per script configurations
  221. bool NoNative;
  222. BOOL fCanOptimizeGlobalLookup;
  223. const bool isOptimizedForManyInstances;
  224. const ThreadConfiguration * const threadConfig;
  225. #ifdef ENABLE_PROJECTION
  226. Number HostType; // One of enum HostType values (see ConfigFlagsTable.h).
  227. bool WinRTConstructorAllowed; // whether allow constructor in webview host type. Also note that this is not a security feature.
  228. ProjectionConfiguration projectionConfiguration;
  229. #endif
  230. };
  231. struct ScriptEntryExitRecord
  232. {
  233. BOOL hasCaller : 1;
  234. BOOL hasReentered : 1;
  235. #if DBG_DUMP
  236. BOOL isCallRoot : 1;
  237. #endif
  238. #if DBG || defined(PROFILE_EXEC)
  239. BOOL leaveForHost : 1;
  240. #endif
  241. #if DBG
  242. BOOL leaveForAsyncHostOperation : 1;
  243. #endif
  244. #ifdef CHECK_STACKWALK_EXCEPTION
  245. BOOL ignoreStackWalkException: 1;
  246. #endif
  247. Js::ImplicitCallFlags savedImplicitCallFlags;
  248. void * returnAddrOfScriptEntryFunction;
  249. void * frameIdOfScriptExitFunction; // the frameAddres in x86, the return address in amd64/arm_soc
  250. ScriptContext * scriptContext;
  251. struct ScriptEntryExitRecord * next;
  252. #if defined(_M_IX86) && defined(DBG)
  253. void * scriptEntryFS0;
  254. #endif
  255. #ifdef EXCEPTION_CHECK
  256. ExceptionType handledExceptionType;
  257. #endif
  258. };
  259. static const unsigned int EvalMRUSize = 15;
  260. typedef JsUtil::BaseDictionary<DWORD_PTR, SourceContextInfo *, Recycler, PowerOf2SizePolicy> SourceContextInfoMap;
  261. typedef JsUtil::BaseDictionary<uint, SourceContextInfo *, Recycler, PowerOf2SizePolicy> DynamicSourceContextInfoMap;
  262. typedef JsUtil::BaseDictionary<EvalMapString, ScriptFunction*, RecyclerNonLeafAllocator, PrimeSizePolicy> SecondLevelEvalCache;
  263. typedef TwoLevelHashRecord<FastEvalMapString, ScriptFunction*, SecondLevelEvalCache, EvalMapString> EvalMapRecord;
  264. typedef JsUtil::Cache<FastEvalMapString, EvalMapRecord*, RecyclerNonLeafAllocator, PrimeSizePolicy, JsUtil::MRURetentionPolicy<FastEvalMapString, EvalMRUSize>, FastEvalMapStringComparer> EvalCacheTopLevelDictionary;
  265. typedef SList<Js::FunctionProxy*, Recycler> FunctionReferenceList;
  266. typedef JsUtil::Cache<EvalMapString, ParseableFunctionInfo*, RecyclerNonLeafAllocator, PrimeSizePolicy, JsUtil::MRURetentionPolicy<EvalMapString, EvalMRUSize>> NewFunctionCache;
  267. typedef JsUtil::BaseDictionary<ParseableFunctionInfo*, ParseableFunctionInfo*, Recycler, PrimeSizePolicy, RecyclerPointerComparer> ParseableFunctionInfoMap;
  268. // This is the dictionary used by script context to cache the eval.
  269. typedef TwoLevelHashDictionary<FastEvalMapString, ScriptFunction*, EvalMapRecord, EvalCacheTopLevelDictionary, EvalMapString> EvalCacheDictionary;
  270. struct PropertyStringMap
  271. {
  272. PropertyString* strLen2[80];
  273. __inline static uint PStrMapIndex(char16 ch)
  274. {
  275. Assert(ch >= '0' && ch <= 'z');
  276. return ch - '0';
  277. }
  278. };
  279. #ifdef ENABLE_DOM_FAST_PATH
  280. typedef JsUtil::BaseDictionary<Js::FunctionInfo*, IR::JnHelperMethod, ArenaAllocator, PowerOf2SizePolicy> DOMFastPathIRHelperMap;
  281. #endif
  282. // valid if object!= NULL
  283. struct EnumeratedObjectCache {
  284. static const int kMaxCachedPropStrings=16;
  285. DynamicObject* object;
  286. DynamicType* type;
  287. PropertyString* propertyStrings[kMaxCachedPropStrings];
  288. int validPropStrings;
  289. };
  290. // Holder for all cached pointers. These are allocated on a guest arena
  291. // ensuring they cause the related objects to be pinned.
  292. struct Cache
  293. {
  294. JavascriptString * lastNumberToStringRadix10String;
  295. EnumeratedObjectCache enumObjCache;
  296. JavascriptString * lastUtcTimeFromStrString;
  297. TypePath* rootPath;
  298. EvalCacheDictionary* evalCacheDictionary;
  299. EvalCacheDictionary* indirectEvalCacheDictionary;
  300. NewFunctionCache* newFunctionCache;
  301. RegexPatternMruMap *dynamicRegexMap;
  302. SourceContextInfoMap* sourceContextInfoMap; // maps host provided context cookie to the URL of the script buffer passed.
  303. DynamicSourceContextInfoMap* dynamicSourceContextInfoMap;
  304. SourceContextInfo* noContextSourceContextInfo;
  305. SRCINFO* noContextGlobalSourceInfo;
  306. SRCINFO const ** moduleSrcInfo;
  307. };
  308. class ScriptContext : public ScriptContextBase
  309. {
  310. friend class LowererMD;
  311. friend class RemoteScriptContext;
  312. friend class SourceTextModuleRecord; // for module bytecode gen.
  313. public:
  314. static DWORD GetThreadContextOffset() { return offsetof(ScriptContext, threadContext); }
  315. static DWORD GetOptimizationOverridesOffset() { return offsetof(ScriptContext, optimizationOverrides); }
  316. static DWORD GetRecyclerOffset() { return offsetof(ScriptContext, recycler); }
  317. static DWORD GetNumberAllocatorOffset() { return offsetof(ScriptContext, numberAllocator); }
  318. static DWORD GetAsmIntDbValOffset() { return offsetof(ScriptContext, retAsmIntDbVal); }
  319. ScriptContext *next;
  320. ScriptContext *prev;
  321. double retAsmIntDbVal; // stores the double & float result for Asm interpreter
  322. AsmJsSIMDValue retAsmSimdVal; // stores raw simd result for Asm interpreter
  323. static DWORD GetAsmSimdValOffset() { return offsetof(ScriptContext, retAsmSimdVal); }
  324. ScriptContextOptimizationOverrideInfo optimizationOverrides;
  325. Js::JavascriptMethod CurrentThunk;
  326. Js::JavascriptMethod CurrentCrossSiteThunk;
  327. Js::JavascriptMethod DeferredParsingThunk;
  328. Js::JavascriptMethod DeferredDeserializationThunk;
  329. Js::JavascriptMethod DispatchDefaultInvoke;
  330. Js::JavascriptMethod DispatchProfileInvoke;
  331. #ifdef ENABLE_SCRIPT_DEBUGGING
  332. typedef HRESULT (*GetDocumentContextFunction)(
  333. ScriptContext *pContext,
  334. Js::FunctionBody *pFunctionBody,
  335. IDebugDocumentContext **ppDebugDocumentContext);
  336. GetDocumentContextFunction GetDocumentContext;
  337. typedef HRESULT (*CleanupDocumentContextFunction)(ScriptContext *pContext);
  338. CleanupDocumentContextFunction CleanupDocumentContext;
  339. #endif // ENABLE_SCRIPT_DEBUGGING
  340. const ScriptContextBase* GetScriptContextBase() const { return static_cast<const ScriptContextBase*>(this); }
  341. bool DoUndeferGlobalFunctions() const;
  342. bool IsUndeclBlockVar(Var var) const { return this->javascriptLibrary->IsUndeclBlockVar(var); }
  343. void TrackPid(const PropertyRecord* propertyRecord);
  344. void TrackPid(PropertyId propertyId);
  345. bool IsTrackedPropertyId(Js::PropertyId propertyId);
  346. void InvalidateHostObjects()
  347. {
  348. AssertMsg(!isClosed, "Host Object invalidation should occur before the engine is fully closed. Figure our how isClosed got set beforehand.");
  349. isInvalidatedForHostObjects = true;
  350. }
  351. bool IsInvalidatedForHostObjects()
  352. {
  353. return isInvalidatedForHostObjects;
  354. }
  355. #ifdef ENABLE_JS_ETW
  356. void EmitStackTraceEvent(__in UINT64 operationID, __in USHORT maxFrameCount, bool emitV2AsyncStackEvent);
  357. #endif
  358. void SetIsDiagnosticsScriptContext(bool set) { this->isDiagnosticsScriptContext = set; }
  359. bool IsDiagnosticsScriptContext() const { return this->isDiagnosticsScriptContext; }
  360. bool IsScriptContextInNonDebugMode() const;
  361. bool IsScriptContextInDebugMode() const;
  362. bool IsScriptContextInSourceRundownOrDebugMode() const;
  363. bool IsRunningScript() const { return this->threadContext->GetScriptEntryExit() != nullptr; }
  364. typedef JsUtil::List<RecyclerWeakReference<Utf8SourceInfo>*, Recycler, false, Js::WeakRefFreeListedRemovePolicy> CalleeSourceList;
  365. RecyclerRootPtr<CalleeSourceList> calleeUtf8SourceInfoList;
  366. void AddCalleeSourceInfoToList(Utf8SourceInfo* sourceInfo);
  367. bool HaveCalleeSources() { return calleeUtf8SourceInfoList && !calleeUtf8SourceInfoList->Empty(); }
  368. template<class TMapFunction>
  369. void MapCalleeSources(TMapFunction map)
  370. {
  371. if (this->HaveCalleeSources())
  372. {
  373. calleeUtf8SourceInfoList->Map([&](uint i, RecyclerWeakReference<Js::Utf8SourceInfo>* sourceInfoWeakRef)
  374. {
  375. if (calleeUtf8SourceInfoList->IsItemValid(i))
  376. {
  377. Js::Utf8SourceInfo* sourceInfo = sourceInfoWeakRef->Get();
  378. map(sourceInfo);
  379. }
  380. });
  381. }
  382. if (calleeUtf8SourceInfoList)
  383. {
  384. calleeUtf8SourceInfoList.Unroot(this->GetRecycler());
  385. }
  386. }
  387. #ifdef ASMJS_PLAT
  388. inline AsmJsCodeGenerator* GetAsmJsCodeGenerator() const{return asmJsCodeGenerator;}
  389. AsmJsCodeGenerator* InitAsmJsCodeGenerator();
  390. #endif
  391. bool IsExceptionWrapperForBuiltInsEnabled();
  392. static bool IsExceptionWrapperForBuiltInsEnabled(ScriptContext* scriptContext);
  393. static bool IsExceptionWrapperForHelpersEnabled(ScriptContext* scriptContext);
  394. #ifdef ENABLE_SCRIPT_PROFILING
  395. bool IsEnumerateNonUserFunctionsOnly() const { return m_enumerateNonUserFunctionsOnly; }
  396. bool IsTraceDomCall() const { return !!m_fTraceDomCall; }
  397. #endif
  398. InlineCache * GetValueOfInlineCache() const { return valueOfInlineCache;}
  399. InlineCache * GetToStringInlineCache() const { return toStringInlineCache; }
  400. FunctionBody * GetFakeGlobalFuncForUndefer() const { return fakeGlobalFuncForUndefer; }
  401. void SetFakeGlobalFuncForUndefer(FunctionBody * func) { fakeGlobalFuncForUndefer.Root(func, GetRecycler()); }
  402. private:
  403. PropertyStringMap* propertyStrings[80];
  404. JavascriptFunction* GenerateRootFunction(ParseNodePtr parseTree, uint sourceIndex, Parser* parser, ulong grfscr, CompileScriptException * pse, const char16 *rootDisplayName);
  405. typedef void (*EventHandler)(ScriptContext *);
  406. ScriptContext ** entryInScriptContextWithInlineCachesRegistry;
  407. ScriptContext ** entryInScriptContextWithIsInstInlineCachesRegistry;
  408. ScriptContext ** registeredPrototypeChainEnsuredToHaveOnlyWritableDataPropertiesScriptContext;
  409. ArenaAllocator generalAllocator;
  410. #ifdef ENABLE_BASIC_TELEMETRY
  411. ArenaAllocator telemetryAllocator;
  412. #endif
  413. ArenaAllocator dynamicProfileInfoAllocator;
  414. InlineCacheAllocator inlineCacheAllocator;
  415. IsInstInlineCacheAllocator isInstInlineCacheAllocator;
  416. ArenaAllocator* interpreterArena;
  417. ArenaAllocator* guestArena;
  418. ArenaAllocator* diagnosticArena;
  419. void ** bindRefChunkCurrent;
  420. void ** bindRefChunkEnd;
  421. bool startupComplete; // Indicates if the heuristic startup phase for this script context is complete
  422. bool isInvalidatedForHostObjects; // Indicates that we've invalidate all objects in the host so stop calling them.
  423. bool isEnumeratingRecyclerObjects; // Indicates this scriptContext is enumerating recycler objects. Used by recycler enumerating callbacks to filter out other unrelated scriptContexts.
  424. bool m_enumerateNonUserFunctionsOnly; // Indicates that recycler enumeration callback will consider only non-user functions (which are built-ins, external, winrt etc).
  425. ThreadContext* threadContext;
  426. TypeId directHostTypeId;
  427. InlineCache * valueOfInlineCache;
  428. InlineCache * toStringInlineCache;
  429. typedef JsUtil::BaseHashSet<Js::PropertyId, ArenaAllocator> PropIdSetForConstProp;
  430. PropIdSetForConstProp * intConstPropsOnGlobalObject;
  431. PropIdSetForConstProp * intConstPropsOnGlobalUserObject;
  432. void * firstInterpreterFrameReturnAddress;
  433. #ifdef SEPARATE_ARENA
  434. ArenaAllocator sourceCodeAllocator;
  435. ArenaAllocator regexAllocator;
  436. #endif
  437. #ifdef NEED_MISC_ALLOCATOR
  438. ArenaAllocator miscAllocator;
  439. #endif
  440. #if DBG
  441. JsUtil::BaseHashSet<void *, ArenaAllocator> bindRef;
  442. int m_iProfileSession;
  443. #endif
  444. #ifdef PROFILE_EXEC
  445. ScriptContextProfiler * profiler;
  446. bool isProfilerCreated;
  447. bool disableProfiler;
  448. bool ensureParentInfo;
  449. Profiler * CreateProfiler();
  450. #endif
  451. #ifdef PROFILE_MEM
  452. bool profileMemoryDump;
  453. #endif
  454. #ifdef PROFILE_STRINGS
  455. StringProfiler* stringProfiler;
  456. #endif
  457. RecyclerRootPtr<FunctionBody> fakeGlobalFuncForUndefer;
  458. public:
  459. #ifdef PROFILE_TYPES
  460. int convertNullToSimpleCount;
  461. int convertNullToSimpleDictionaryCount;
  462. int convertNullToDictionaryCount;
  463. int convertDeferredToDictionaryCount;
  464. int convertDeferredToSimpleDictionaryCount;
  465. int convertSimpleToDictionaryCount;
  466. int convertSimpleToSimpleDictionaryCount;
  467. int convertPathToDictionaryCount1;
  468. int convertPathToDictionaryCount2;
  469. int convertPathToDictionaryCount3;
  470. int convertPathToDictionaryCount4;
  471. int convertPathToSimpleDictionaryCount;
  472. int convertSimplePathToPathCount;
  473. int convertSimpleDictionaryToDictionaryCount;
  474. int convertSimpleSharedDictionaryToNonSharedCount;
  475. int convertSimpleSharedToNonSharedCount;
  476. int simplePathTypeHandlerCount;
  477. int pathTypeHandlerCount;
  478. int promoteCount;
  479. int cacheCount;
  480. int branchCount;
  481. int maxPathLength;
  482. int typeCount[TypeIds_Limit];
  483. int instanceCount[TypeIds_Limit];
  484. #endif
  485. #ifdef PROFILE_BAILOUT_RECORD_MEMORY
  486. __int64 bailOutRecordBytes;
  487. __int64 bailOutOffsetBytes;
  488. __int64 codeSize;
  489. #endif
  490. #ifdef PROFILE_OBJECT_LITERALS
  491. int objectLiteralInstanceCount;
  492. int objectLiteralPathCount;
  493. int objectLiteralCount[TypePath::MaxPathTypeHandlerLength];
  494. int objectLiteralSimpleDictionaryCount;
  495. uint32 objectLiteralMaxLength;
  496. int objectLiteralPromoteCount;
  497. int objectLiteralCacheCount;
  498. int objectLiteralBranchCount;
  499. #endif
  500. #if DBG_DUMP
  501. uint byteCodeDataSize;
  502. uint byteCodeAuxiliaryDataSize;
  503. uint byteCodeAuxiliaryContextDataSize;
  504. uint byteCodeHistogram[static_cast<uint>(OpCode::ByteCodeLast)];
  505. uint32 forinCache;
  506. uint32 forinNoCache;
  507. #endif
  508. #ifdef BGJIT_STATS
  509. uint interpretedCount;
  510. uint funcJITCount;
  511. uint loopJITCount;
  512. uint bytecodeJITCount;
  513. uint interpretedCallsHighPri;
  514. uint maxFuncInterpret;
  515. uint jitCodeUsed;
  516. uint funcJitCodeUsed;
  517. uint speculativeJitCount;
  518. #endif
  519. #ifdef REJIT_STATS
  520. // Used to store bailout stats
  521. typedef JsUtil::BaseDictionary<uint, uint, ArenaAllocator> BailoutStatsMap;
  522. struct RejitStats
  523. {
  524. uint *m_rejitReasonCounts;
  525. BailoutStatsMap* m_bailoutReasonCounts;
  526. uint m_totalRejits;
  527. uint m_totalBailouts;
  528. RejitStats(ScriptContext *scriptContext) : m_totalRejits(0), m_totalBailouts(0)
  529. {
  530. m_rejitReasonCounts = AnewArrayZ(scriptContext->GeneralAllocator(), uint, NumRejitReasons);
  531. m_bailoutReasonCounts = Anew(scriptContext->GeneralAllocator(), BailoutStatsMap, scriptContext->GeneralAllocator());
  532. }
  533. };
  534. void LogDataForFunctionBody(Js::FunctionBody *body, uint idx, bool isRejit);
  535. void LogRejit(Js::FunctionBody *body, uint reason);
  536. void LogBailout(Js::FunctionBody *body, uint kind);
  537. // Used to centrally collect stats for all function bodies.
  538. typedef JsUtil::WeaklyReferencedKeyDictionary<const Js::FunctionBody, RejitStats*> RejitStatsMap;
  539. RejitStatsMap* rejitStatsMap;
  540. BailoutStatsMap *bailoutReasonCounts;
  541. uint *rejitReasonCounts;
  542. #endif
  543. #ifdef ENABLE_BASIC_TELEMETRY
  544. private:
  545. ScriptContextTelemetry* telemetry;
  546. public:
  547. ScriptContextTelemetry& GetTelemetry();
  548. bool HasTelemetry();
  549. #endif
  550. #ifdef INLINE_CACHE_STATS
  551. // Used to store inline cache stats
  552. struct CacheData
  553. {
  554. uint hits;
  555. uint misses;
  556. uint collisions;
  557. bool isGetCache;
  558. Js::PropertyId propertyId;
  559. CacheData() : hits(0), misses(0), collisions(0), isGetCache(false), propertyId(Js::PropertyIds::_none) { }
  560. };
  561. // This is a strongly referenced dictionary, since we want to know hit rates for dead caches.
  562. typedef JsUtil::BaseDictionary<const Js::PolymorphicInlineCache*, CacheData*, Recycler> CacheDataMap;
  563. CacheDataMap *cacheDataMap;
  564. void LogCacheUsage(Js::PolymorphicInlineCache *cache, bool isGet, Js::PropertyId propertyId, bool hit, bool collision);
  565. #endif
  566. #ifdef FIELD_ACCESS_STATS
  567. typedef SList<FieldAccessStatsPtr, Recycler> FieldAccessStatsList;
  568. struct FieldAccessStatsEntry
  569. {
  570. RecyclerWeakReference<FunctionBody>* functionBodyWeakRef;
  571. FieldAccessStatsList stats;
  572. FieldAccessStatsEntry(RecyclerWeakReference<FunctionBody>* functionBodyWeakRef, Recycler* recycler)
  573. : functionBodyWeakRef(functionBodyWeakRef), stats(recycler) {}
  574. };
  575. typedef JsUtil::BaseDictionary<uint, FieldAccessStatsEntry*, Recycler> FieldAccessStatsByFunctionNumberMap;
  576. FieldAccessStatsByFunctionNumberMap* fieldAccessStatsByFunctionNumber;
  577. void RecordFieldAccessStats(FunctionBody* functionBody, FieldAccessStatsPtr fieldAccessStats);
  578. #endif
  579. #ifdef MISSING_PROPERTY_STATS
  580. int missingPropertyMisses;
  581. int missingPropertyHits;
  582. int missingPropertyCacheAttempts;
  583. void RecordMissingPropertyMiss();
  584. void RecordMissingPropertyHit();
  585. void RecordMissingPropertyCacheAttempt();
  586. #endif
  587. bool IsIntConstPropertyOnGlobalObject(Js::PropertyId propId);
  588. void TrackIntConstPropertyOnGlobalObject(Js::PropertyId propId);
  589. bool IsIntConstPropertyOnGlobalUserObject(Js::PropertyId propertyId);
  590. void TrackIntConstPropertyOnGlobalUserObject(Js::PropertyId propertyId);
  591. private:
  592. //
  593. // Regex globals
  594. //
  595. #if ENABLE_REGEX_CONFIG_OPTIONS
  596. UnifiedRegex::DebugWriter* regexDebugWriter;
  597. UnifiedRegex::RegexStatsDatabase* regexStatsDatabase;
  598. #endif
  599. UnifiedRegex::TrigramAlphabet* trigramAlphabet;
  600. UnifiedRegex::RegexStacks *regexStacks;
  601. FunctionReferenceList* dynamicFunctionReference;
  602. uint dynamicFunctionReferenceDepth;
  603. JsUtil::Stack<Var>* operationStack;
  604. Recycler* recycler;
  605. RecyclerJavascriptNumberAllocator numberAllocator;
  606. ScriptConfiguration config;
  607. CharClassifier *charClassifier;
  608. // DisableJIT-TODO: Switch this to Dynamic thunk ifdef instead
  609. #if ENABLE_NATIVE_CODEGEN
  610. #if DYNAMIC_INTERPRETER_THUNK
  611. InterpreterThunkEmitter* interpreterThunkEmitter;
  612. #endif
  613. BackgroundParser *backgroundParser;
  614. #ifdef ASMJS_PLAT
  615. InterpreterThunkEmitter* asmJsInterpreterThunkEmitter;
  616. AsmJsCodeGenerator* asmJsCodeGenerator;
  617. typedef JsUtil::BaseDictionary<void *, SList<AsmJsScriptFunction *>*, ArenaAllocator> AsmFunctionMap;
  618. AsmFunctionMap* asmJsEnvironmentMap;
  619. ArenaAllocator* debugTransitionAlloc;
  620. #endif
  621. NativeCodeGenerator* nativeCodeGen;
  622. #endif
  623. #ifdef ENABLE_GLOBALIZATION
  624. TIME_ZONE_INFORMATION timeZoneInfo;
  625. uint lastTimeZoneUpdateTickCount;
  626. DaylightTimeHelper daylightTimeHelper;
  627. #endif // ENABLE_GLOBALIZATION
  628. HostScriptContext * hostScriptContext;
  629. HaltCallback* scriptEngineHaltCallback;
  630. EventHandler scriptStartEventHandler;
  631. EventHandler scriptEndEventHandler;
  632. #ifdef FAULT_INJECTION
  633. EventHandler disposeScriptByFaultInjectionEventHandler;
  634. #endif
  635. JsUtil::BaseDictionary<uint, JavascriptString *, ArenaAllocator> integerStringMap;
  636. double lastNumberToStringRadix10;
  637. double lastUtcTimeFromStr;
  638. #if ENABLE_PROFILE_INFO
  639. bool referencesSharedDynamicSourceContextInfo;
  640. #endif
  641. // We could delay the actual close after callRootLevel is 0.
  642. // this is to indicate the actual close is called once only.
  643. bool isScriptContextActuallyClosed;
  644. #if DBG
  645. bool isInitialized;
  646. bool isCloningGlobal;
  647. #endif
  648. bool fastDOMenabled;
  649. bool hasRegisteredInlineCache;
  650. bool hasRegisteredIsInstInlineCache;
  651. bool deferredBody;
  652. bool isPerformingNonreentrantWork;
  653. bool isDiagnosticsScriptContext; // mentions that current script context belongs to the diagnostics OM.
  654. size_t sourceSize;
  655. void CleanSourceListInternal(bool calledDuringMark);
  656. typedef JsUtil::List<RecyclerWeakReference<Utf8SourceInfo>*, Recycler, false, Js::FreeListedRemovePolicy> SourceList;
  657. RecyclerRootPtr<SourceList> sourceList;
  658. #ifdef ENABLE_SCRIPT_PROFILING
  659. IActiveScriptProfilerHeapEnum* heapEnum;
  660. // Profiler Probes
  661. // In future these can be list of callbacks ?
  662. // Profiler Callback information
  663. IActiveScriptProfilerCallback *m_pProfileCallback;
  664. BOOL m_fTraceFunctionCall;
  665. BOOL m_fTraceNativeFunctionCall;
  666. DWORD m_dwEventMask;
  667. IActiveScriptProfilerCallback2 *m_pProfileCallback2;
  668. BOOL m_fTraceDomCall;
  669. BOOL m_inProfileCallback;
  670. #endif // ENABLE_SCRIPT_PROFILING
  671. #if ENABLE_PROFILE_INFO
  672. #if DBG_DUMP || defined(DYNAMIC_PROFILE_STORAGE) || defined(RUNTIME_DATA_COLLECTION)
  673. RecyclerRootPtr<SListBase<DynamicProfileInfo *>> profileInfoList;
  674. #endif
  675. #endif
  676. #if DEBUG
  677. static int scriptContextCount;
  678. #endif
  679. // List of weak reference dictionaries. We'll walk through them
  680. // and clean them up post-collection
  681. // IWeakReferenceDictionary objects are added to this list by calling
  682. // RegisterWeakReferenceDictionary. If you use JsUtil::WeakReferenceDictionary,
  683. // which also exposes the IWeakReferenceDictionary interface, it'll
  684. // automatically register the dictionary on the script context
  685. SListBase<JsUtil::IWeakReferenceDictionary*> weakReferenceDictionaryList;
  686. bool isWeakReferenceDictionaryListCleared;
  687. typedef void(*RaiseMessageToDebuggerFunctionType)(ScriptContext *, DEBUG_EVENT_INFO_TYPE, LPCWSTR, LPCWSTR);
  688. RaiseMessageToDebuggerFunctionType raiseMessageToDebuggerFunctionType;
  689. typedef void(*TransitionToDebugModeIfFirstSourceFn)(ScriptContext *, Utf8SourceInfo *);
  690. TransitionToDebugModeIfFirstSourceFn transitionToDebugModeIfFirstSourceFn;
  691. #ifdef ENABLE_DOM_FAST_PATH
  692. // Theoretically we can put this in ThreadContext; don't want to keep the dictionary forever, and preserve the possibility of
  693. // using JavascriptFunction as key.
  694. DOMFastPathIRHelperMap* domFastPathIRHelperMap;
  695. #endif
  696. ScriptContext(ThreadContext* threadContext);
  697. void InitializeAllocations();
  698. void InitializePreGlobal();
  699. void InitializePostGlobal();
  700. // Source Info
  701. void EnsureSourceContextInfoMap();
  702. void EnsureDynamicSourceContextInfoMap();
  703. uint moduleSrcInfoCount;
  704. #ifdef RUNTIME_DATA_COLLECTION
  705. time_t createTime;
  706. #endif
  707. char16 const * url;
  708. void PrintStats();
  709. BOOL LeaveScriptStartCore(void * frameAddress, bool leaveForHost);
  710. void InternalClose();
  711. DebugContext* debugContext;
  712. public:
  713. static const int kArrayMatchCh=72;
  714. static const int kMaxArrayMatchIndex=8192;
  715. short arrayMatchItems[kArrayMatchCh];
  716. bool arrayMatchInit;
  717. #ifdef LEAK_REPORT
  718. LeakReport::UrlRecord * urlRecord;
  719. bool isRootTrackerScriptContext;
  720. #endif
  721. #ifdef ENABLE_GLOBALIZATION
  722. DaylightTimeHelper *GetDaylightTimeHelper() { return &daylightTimeHelper; }
  723. #endif // ENABLE_GLOBALIZATION
  724. bool IsClosed() const { return isClosed; }
  725. bool IsActuallyClosed() const { return isScriptContextActuallyClosed; }
  726. #if ENABLE_NATIVE_CODEGEN
  727. bool IsClosedNativeCodeGenerator() const
  728. {
  729. return !nativeCodeGen || ::IsClosedNativeCodeGenerator(nativeCodeGen);
  730. }
  731. #endif
  732. void SetDirectHostTypeId(TypeId typeId) {directHostTypeId = typeId; }
  733. TypeId GetDirectHostTypeId() const { return directHostTypeId; }
  734. TypePath* GetRootPath() { return cache->rootPath; }
  735. #ifdef ENABLE_DOM_FAST_PATH
  736. DOMFastPathIRHelperMap* EnsureDOMFastPathIRHelperMap();
  737. #endif
  738. char16 const * GetUrl() const { return url; }
  739. void SetUrl(BSTR bstr);
  740. #ifdef RUNTIME_DATA_COLLECTION
  741. time_t GetCreateTime() const { return createTime; }
  742. uint GetAllocId() const { return allocId; }
  743. #endif
  744. void InitializeArrayMatch()
  745. {
  746. if (!arrayMatchInit)
  747. {
  748. for (int i=0;i<kArrayMatchCh;i++)
  749. {
  750. arrayMatchItems[i]= -1;
  751. }
  752. arrayMatchInit=true;
  753. }
  754. }
  755. #ifdef HEAP_ENUMERATION_VALIDATION
  756. bool IsInitialized() { return this->isInitialized; }
  757. #endif
  758. DebugContext* GetDebugContext() const { return this->debugContext; }
  759. uint callCount;
  760. // Guest arena allocated cache holding references that need to be pinned.
  761. Cache* cache;
  762. // if the current context is for webworker
  763. DWORD webWorkerId;
  764. static ScriptContext * New(ThreadContext * threadContext);
  765. static void Delete(ScriptContext* scriptContext);
  766. ~ScriptContext();
  767. #ifdef PROFILE_TYPES
  768. void ProfileTypes();
  769. #endif
  770. #ifdef PROFILE_OBJECT_LITERALS
  771. void ProfileObjectLiteral();
  772. #endif
  773. //
  774. // Regex helpers
  775. //
  776. #if ENABLE_REGEX_CONFIG_OPTIONS
  777. UnifiedRegex::RegexStatsDatabase* GetRegexStatsDatabase();
  778. UnifiedRegex::DebugWriter* GetRegexDebugWriter();
  779. #endif
  780. RegexPatternMruMap* GetDynamicRegexMap() const;
  781. UnifiedRegex::TrigramAlphabet* GetTrigramAlphabet() { return trigramAlphabet; }
  782. void SetTrigramAlphabet(UnifiedRegex::TrigramAlphabet * trigramAlphabet);
  783. UnifiedRegex::RegexStacks *RegexStacks();
  784. UnifiedRegex::RegexStacks *AllocRegexStacks();
  785. UnifiedRegex::RegexStacks *SaveRegexStacks();
  786. void RestoreRegexStacks(UnifiedRegex::RegexStacks *const contStack);
  787. void InitializeGlobalObject();
  788. bool IsIntlEnabled();
  789. JavascriptLibrary* GetLibrary() const { return javascriptLibrary; }
  790. const JavascriptLibraryBase* GetLibraryBase() const { return javascriptLibrary->GetLibraryBase(); }
  791. #if DBG
  792. BOOL IsCloningGlobal() const { return isCloningGlobal;}
  793. #endif
  794. void PushObject(Var object);
  795. Var PopObject();
  796. BOOL CheckObject(Var object);
  797. inline bool IsHeapEnumInProgress() { return GetRecycler()->IsHeapEnumInProgress(); }
  798. bool IsInterpreted() { return config.IsNoNative(); }
  799. void ForceNoNative() { config.ForceNoNative(); }
  800. void ForceNative() { config.ForceNative(); }
  801. ScriptConfiguration const * GetConfig(void) const { return &config; }
  802. CharClassifier const * GetCharClassifier(void) const;
  803. ThreadContext * GetThreadContext() const { return threadContext; }
  804. #ifdef ENABLE_GLOBALIZATION
  805. TIME_ZONE_INFORMATION * GetTimeZoneInfo()
  806. {
  807. uint tickCount = GetTickCount();
  808. if (tickCount - lastTimeZoneUpdateTickCount > 1000)
  809. {
  810. UpdateTimeZoneInfo();
  811. lastTimeZoneUpdateTickCount = tickCount;
  812. }
  813. return &timeZoneInfo;
  814. }
  815. void UpdateTimeZoneInfo();
  816. #endif // ENABLE_GLOBALIZATION
  817. static const int MaxEvalSourceSize = 400;
  818. bool IsInEvalMap(FastEvalMapString const& key, BOOL isIndirect, ScriptFunction **ppFuncScript);
  819. void AddToEvalMap(FastEvalMapString const& key, BOOL isIndirect, ScriptFunction *pFuncScript);
  820. template <typename TCacheType>
  821. void CleanDynamicFunctionCache(TCacheType* cacheType);
  822. void CleanEvalMapCache(Js::EvalCacheTopLevelDictionary * cacheType);
  823. template <class TDelegate>
  824. void MapFunction(TDelegate mapper);
  825. template <class TDelegate>
  826. FunctionBody* FindFunction(TDelegate predicate);
  827. __inline bool EnableEvalMapCleanup() { return CONFIG_FLAG(EnableEvalMapCleanup); };
  828. void BeginDynamicFunctionReferences();
  829. void EndDynamicFunctionReferences();
  830. void RegisterDynamicFunctionReference(FunctionProxy* func);
  831. uint GetNextSourceContextId();
  832. bool IsInNewFunctionMap(EvalMapString const& key, ParseableFunctionInfo **ppFuncBody);
  833. void AddToNewFunctionMap(EvalMapString const& key, ParseableFunctionInfo *pFuncBody);
  834. SourceContextInfo * GetSourceContextInfo(DWORD_PTR hostSourceContext, IActiveScriptDataCache* profileDataCache);
  835. SourceContextInfo * GetSourceContextInfo(uint hash);
  836. SourceContextInfo * CreateSourceContextInfo(uint hash, DWORD_PTR hostSourceContext);
  837. SourceContextInfo * CreateSourceContextInfo(DWORD_PTR hostSourceContext, char16 const * url, size_t len,
  838. IActiveScriptDataCache* profileDataCache, char16 const * sourceMapUrl = nullptr, size_t sourceMapUrlLen = 0);
  839. #if defined(LEAK_REPORT) || defined(CHECK_MEMORY_LEAK)
  840. void ClearSourceContextInfoMaps()
  841. {
  842. if (this->cache != nullptr)
  843. {
  844. this->cache->sourceContextInfoMap = nullptr;
  845. this->cache->dynamicSourceContextInfoMap = nullptr;
  846. #if ENABLE_PROFILE_INFO
  847. this->referencesSharedDynamicSourceContextInfo = false;
  848. #endif
  849. }
  850. }
  851. #endif
  852. #if ENABLE_PROFILE_INFO
  853. #if DBG_DUMP || defined(DYNAMIC_PROFILE_STORAGE) || defined(RUNTIME_DATA_COLLECTION)
  854. void ClearDynamicProfileList()
  855. {
  856. if (profileInfoList)
  857. {
  858. profileInfoList->Reset();
  859. profileInfoList.Unroot(this->recycler);
  860. }
  861. }
  862. SListBase<DynamicProfileInfo *> * GetProfileInfoList() { return profileInfoList; }
  863. #endif
  864. #endif
  865. SRCINFO const * GetModuleSrcInfo(Js::ModuleID moduleID);
  866. SourceContextInfoMap* GetSourceContextInfoMap()
  867. {
  868. return (this->cache ? this->cache->sourceContextInfoMap : nullptr);
  869. }
  870. DynamicSourceContextInfoMap* GetDynamicSourceContextInfoMap()
  871. {
  872. return (this->cache ? this->cache->dynamicSourceContextInfoMap : nullptr);
  873. }
  874. void SetFirstInterpreterFrameReturnAddress(void * returnAddress) { firstInterpreterFrameReturnAddress = returnAddress;}
  875. void *GetFirstInterpreterFrameReturnAddress() { return firstInterpreterFrameReturnAddress;}
  876. void CleanupWeakReferenceDictionaries();
  877. void Initialize();
  878. bool Close(bool inDestructor);
  879. void MarkForClose();
  880. #ifdef ENABLE_PROJECTION
  881. void SetHostType(long hostType) { config.SetHostType(hostType); }
  882. void SetWinRTConstructorAllowed(bool allowed) { config.SetWinRTConstructorAllowed(allowed); }
  883. void SetProjectionTargetVersion(DWORD version) { config.SetProjectionTargetVersion(version); }
  884. #endif
  885. void SetCanOptimizeGlobalLookupFlag(BOOL f){ config.SetCanOptimizeGlobalLookupFlag(f);}
  886. BOOL CanOptimizeGlobalLookup(){ return config.CanOptimizeGlobalLookup();}
  887. bool IsClosed() { return isClosed; }
  888. bool IsFastDOMEnabled() { return fastDOMenabled; }
  889. void SetFastDOMenabled();
  890. BOOL VerifyAlive(BOOL isJSFunction = FALSE, ScriptContext* requestScriptContext = nullptr);
  891. void VerifyAliveWithHostContext(BOOL isJSFunction, HostScriptContext* requestHostScriptContext);
  892. void AddFunctionBodyToPropIdMap(FunctionBody* body);
  893. void BindReference(void* addr);
  894. void InitPropertyStringMap(int i);
  895. PropertyString* AddPropertyString2(const Js::PropertyRecord* propertyRecord);
  896. PropertyString* CachePropertyString2(const Js::PropertyRecord* propertyRecord);
  897. PropertyString* GetPropertyString2(char16 ch1, char16 ch2);
  898. void FindPropertyRecord(__in LPCWSTR pszPropertyName, __in int propertyNameLength, PropertyRecord const** propertyRecord);
  899. JsUtil::List<const RecyclerWeakReference<Js::PropertyRecord const>*>* FindPropertyIdNoCase(__in LPCWSTR pszPropertyName, __in int propertyNameLength);
  900. void FindPropertyRecord(JavascriptString* pstName, PropertyRecord const** propertyRecord);
  901. PropertyRecord const * GetPropertyName(PropertyId propertyId);
  902. PropertyRecord const * GetPropertyNameLocked(PropertyId propertyId);
  903. void GetOrAddPropertyRecord(JsUtil::CharacterBuffer<WCHAR> const& propName, PropertyRecord const** propertyRecord);
  904. template <size_t N> void GetOrAddPropertyRecord(const char16(&propertyName)[N], PropertyRecord const** propertyRecord)
  905. {
  906. GetOrAddPropertyRecord(propertyName, N - 1, propertyRecord);
  907. }
  908. PropertyId GetOrAddPropertyIdTracked(JsUtil::CharacterBuffer<WCHAR> const& propName);
  909. template <size_t N> PropertyId GetOrAddPropertyIdTracked(const char16(&propertyName)[N])
  910. {
  911. return GetOrAddPropertyIdTracked(propertyName, N - 1);
  912. }
  913. PropertyId GetOrAddPropertyIdTracked(__in_ecount(propertyNameLength) LPCWSTR pszPropertyName, __in int propertyNameLength);
  914. void GetOrAddPropertyRecord(__in_ecount(propertyNameLength) LPCWSTR pszPropertyName, __in int propertyNameLength, PropertyRecord const** propertyRecord);
  915. BOOL IsNumericPropertyId(PropertyId propertyId, uint32* value);
  916. void RegisterWeakReferenceDictionary(JsUtil::IWeakReferenceDictionary* weakReferenceDictionary);
  917. void ResetWeakReferenceDictionaryList() { weakReferenceDictionaryList.Reset(); }
  918. BOOL ReserveStaticTypeIds(__in int first, __in int last);
  919. TypeId ReserveTypeIds(int count);
  920. TypeId CreateTypeId();
  921. WellKnownHostType GetWellKnownHostType(Js::TypeId typeId) { return threadContext->GetWellKnownHostType(typeId); }
  922. void SetWellKnownHostTypeId(WellKnownHostType wellKnownType, Js::TypeId typeId) { threadContext->SetWellKnownHostTypeId(wellKnownType, typeId); }
  923. ParseNodePtr ParseScript(Parser* parser, const byte* script, size_t cb, SRCINFO const * pSrcInfo,
  924. CompileScriptException * pse, Utf8SourceInfo** ppSourceInfo, const char16 *rootDisplayName, LoadScriptFlag loadScriptFlag, uint* sourceIndex);
  925. JavascriptFunction* LoadScript(const byte* script, size_t cb, SRCINFO const * pSrcInfo,
  926. CompileScriptException * pse, Utf8SourceInfo** ppSourceInfo, const char16 *rootDisplayName, LoadScriptFlag loadScriptFlag);
  927. ArenaAllocator* GeneralAllocator() { return &generalAllocator; }
  928. #ifdef ENABLE_BASIC_TELEMETRY
  929. ArenaAllocator* TelemetryAllocator() { return &telemetryAllocator; }
  930. #endif
  931. #ifdef SEPARATE_ARENA
  932. ArenaAllocator* SourceCodeAllocator() { return &sourceCodeAllocator; }
  933. ArenaAllocator* RegexAllocator() { return &regexAllocator; }
  934. #else
  935. ArenaAllocator* SourceCodeAllocator() { return &generalAllocator; }
  936. ArenaAllocator* RegexAllocator() { return &generalAllocator; }
  937. #endif
  938. #ifdef NEED_MISC_ALLOCATOR
  939. ArenaAllocator* MiscAllocator() { return &miscAllocator; }
  940. #endif
  941. InlineCacheAllocator* GetInlineCacheAllocator() { return &inlineCacheAllocator; }
  942. IsInstInlineCacheAllocator* GetIsInstInlineCacheAllocator() { return &isInstInlineCacheAllocator; }
  943. ArenaAllocator* DynamicProfileInfoAllocator() { return &dynamicProfileInfoAllocator; }
  944. ArenaAllocator* AllocatorForDiagnostics();
  945. Js::TempArenaAllocatorObject* GetTemporaryAllocator(LPCWSTR name);
  946. void ReleaseTemporaryAllocator(Js::TempArenaAllocatorObject* tempAllocator);
  947. Js::TempGuestArenaAllocatorObject* GetTemporaryGuestAllocator(LPCWSTR name);
  948. void ReleaseTemporaryGuestAllocator(Js::TempGuestArenaAllocatorObject* tempAllocator);
  949. bool EnsureInterpreterArena(ArenaAllocator **);
  950. void ReleaseInterpreterArena();
  951. ArenaAllocator* GetGuestArena() const
  952. {
  953. return guestArena;
  954. }
  955. void ReleaseGuestArena();
  956. Recycler* GetRecycler() const { return recycler; }
  957. RecyclerJavascriptNumberAllocator * GetNumberAllocator() { return &numberAllocator; }
  958. #if ENABLE_NATIVE_CODEGEN
  959. NativeCodeGenerator * GetNativeCodeGenerator() const { return nativeCodeGen; }
  960. #endif
  961. #if ENABLE_BACKGROUND_PARSING
  962. BackgroundParser * GetBackgroundParser() const { return backgroundParser; }
  963. #endif
  964. void OnScriptStart(bool isRoot, bool isScript);
  965. void OnScriptEnd(bool isRoot, bool isForcedEnd);
  966. template <bool stackProbe, bool leaveForHost>
  967. bool LeaveScriptStart(void * frameAddress);
  968. template <bool leaveForHost>
  969. void LeaveScriptEnd(void * frameAddress);
  970. HostScriptContext * GetHostScriptContext() const { return hostScriptContext; }
  971. void SetHostScriptContext(HostScriptContext * hostScriptContext);
  972. void SetScriptEngineHaltCallback(HaltCallback* scriptEngine);
  973. void ClearHostScriptContext();
  974. IActiveScriptProfilerHeapEnum* GetHeapEnum();
  975. void SetHeapEnum(IActiveScriptProfilerHeapEnum* newHeapEnum);
  976. void ClearHeapEnum();
  977. void SetScriptStartEventHandler(EventHandler eventHandler);
  978. void SetScriptEndEventHandler(EventHandler eventHandler);
  979. #ifdef FAULT_INJECTION
  980. void DisposeScriptContextByFaultInjection();
  981. void SetDisposeDisposeByFaultInjectionEventHandler(EventHandler eventHandler);
  982. #endif
  983. EnumeratedObjectCache* GetEnumeratedObjectCache() { return &(cache->enumObjCache); }
  984. PropertyString* GetPropertyString(PropertyId propertyId);
  985. void InvalidatePropertyStringCache(PropertyId propertyId, Type* type);
  986. JavascriptString* GetIntegerString(Var aValue);
  987. JavascriptString* GetIntegerString(int value);
  988. JavascriptString* GetIntegerString(uint value);
  989. void CheckEvalRestriction();
  990. RecyclableObject* GetMissingPropertyResult();
  991. RecyclableObject* GetMissingItemResult();
  992. bool HasRecordedException() const { return threadContext->GetRecordedException() != nullptr; }
  993. Js::JavascriptExceptionObject * GetAndClearRecordedException(bool *considerPassingToDebugger = nullptr);
  994. void RecordException(Js::JavascriptExceptionObject * exceptionObject, bool propagateToDebugger = false);
  995. __declspec(noreturn) void RethrowRecordedException(JavascriptExceptionObject::HostWrapperCreateFuncType hostWrapperCreateFunc);
  996. #if ENABLE_NATIVE_CODEGEN
  997. BOOL IsNativeAddress(void * codeAddr);
  998. #endif
  999. uint SaveSourceCopy(Utf8SourceInfo* sourceInfo, int cchLength, bool isCesu8);
  1000. bool SaveSourceCopy(Utf8SourceInfo* const sourceInfo, int cchLength, bool isCesu8, uint * index);
  1001. uint SaveSourceNoCopy(Utf8SourceInfo* sourceInfo, int cchLength, bool isCesu8);
  1002. Utf8SourceInfo* CloneSourceCrossContext(Utf8SourceInfo* crossContextSourceInfo, SRCINFO const* srcInfo = nullptr);
  1003. void CloneSources(ScriptContext* sourceContext);
  1004. Utf8SourceInfo* GetSource(uint sourceIndex);
  1005. uint SourceCount() const { return (uint)sourceList->Count(); }
  1006. void CleanSourceList() { CleanSourceListInternal(false); }
  1007. SourceList* GetSourceList() const { return sourceList; }
  1008. bool IsItemValidInSourceList(int index);
  1009. template <typename TFunction>
  1010. void MapScript(TFunction mapper)
  1011. {
  1012. this->sourceList->Map([mapper] (int, RecyclerWeakReference<Utf8SourceInfo>* sourceInfoWeakReference)
  1013. {
  1014. Utf8SourceInfo* strongRef = sourceInfoWeakReference->Get();
  1015. if (strongRef)
  1016. {
  1017. mapper(strongRef);
  1018. }
  1019. });
  1020. }
  1021. #ifdef CHECK_STACKWALK_EXCEPTION
  1022. void SetIgnoreStackWalkException() {threadContext->GetScriptEntryExit()->ignoreStackWalkException = true; }
  1023. #endif
  1024. // For debugging scenarios where execution will go to debugging manager and come back to engine again, enforce the current EER to have
  1025. // 'hasCaller' property set, which will enable the stack walking across frames.
  1026. // Do not call this directly, look for ENFORCE_ENTRYEXITRECORD_HASCALLER macro.
  1027. void EnforceEERHasCaller() { threadContext->GetScriptEntryExit()->hasCaller = true; }
  1028. void SetRaiseMessageToDebuggerFunction(RaiseMessageToDebuggerFunctionType function)
  1029. {
  1030. raiseMessageToDebuggerFunctionType = function;
  1031. }
  1032. void RaiseMessageToDebugger(DEBUG_EVENT_INFO_TYPE messageType, LPCWSTR message, LPCWSTR url)
  1033. {
  1034. if (raiseMessageToDebuggerFunctionType != nullptr)
  1035. {
  1036. raiseMessageToDebuggerFunctionType(this, messageType, message, url);
  1037. }
  1038. }
  1039. void SetTransitionToDebugModeIfFirstSourceFn(TransitionToDebugModeIfFirstSourceFn function)
  1040. {
  1041. transitionToDebugModeIfFirstSourceFn = function;
  1042. }
  1043. void TransitionToDebugModeIfFirstSource(Utf8SourceInfo *sourceInfo)
  1044. {
  1045. if (transitionToDebugModeIfFirstSourceFn != nullptr)
  1046. {
  1047. transitionToDebugModeIfFirstSourceFn(this, sourceInfo);
  1048. }
  1049. }
  1050. void AddSourceSize(size_t sourceSize)
  1051. {
  1052. this->sourceSize += sourceSize;
  1053. this->threadContext->AddSourceSize(sourceSize);
  1054. }
  1055. size_t GetSourceSize()
  1056. {
  1057. return this->sourceSize;
  1058. }
  1059. BOOL SetDeferredBody(BOOL set)
  1060. {
  1061. bool old = this->deferredBody;
  1062. this->deferredBody = !!set;
  1063. return old;
  1064. }
  1065. BOOL GetDeferredBody(void) const
  1066. {
  1067. return this->deferredBody;
  1068. }
  1069. public:
  1070. void RegisterAsScriptContextWithInlineCaches();
  1071. void RegisterAsScriptContextWithIsInstInlineCaches();
  1072. bool IsRegisteredAsScriptContextWithIsInstInlineCaches();
  1073. void FreeLoopBody(void* codeAddress);
  1074. void FreeFunctionEntryPoint(Js::JavascriptMethod method);
  1075. private:
  1076. void DoRegisterAsScriptContextWithInlineCaches();
  1077. void DoRegisterAsScriptContextWithIsInstInlineCaches();
  1078. uint CloneSource(Utf8SourceInfo* info);
  1079. public:
  1080. void RegisterProtoInlineCache(InlineCache *pCache, PropertyId propId);
  1081. void InvalidateProtoCaches(const PropertyId propertyId);
  1082. void InvalidateAllProtoCaches();
  1083. void RegisterStoreFieldInlineCache(InlineCache *pCache, PropertyId propId);
  1084. void InvalidateStoreFieldCaches(const PropertyId propertyId);
  1085. void InvalidateAllStoreFieldCaches();
  1086. void RegisterIsInstInlineCache(Js::IsInstInlineCache * cache, Js::Var function);
  1087. #if DBG
  1088. bool IsIsInstInlineCacheRegistered(Js::IsInstInlineCache * cache, Js::Var function);
  1089. #endif
  1090. void ClearInlineCaches();
  1091. void ClearIsInstInlineCaches();
  1092. #ifdef PERSISTENT_INLINE_CACHES
  1093. void ClearInlineCachesWithDeadWeakRefs();
  1094. #endif
  1095. void ClearScriptContextCaches();
  1096. #if ENABLE_NATIVE_CODEGEN
  1097. void RegisterConstructorCache(Js::PropertyId propertyId, Js::ConstructorCache* cache);
  1098. #endif
  1099. public:
  1100. void RegisterPrototypeChainEnsuredToHaveOnlyWritableDataPropertiesScriptContext();
  1101. private:
  1102. void DoRegisterPrototypeChainEnsuredToHaveOnlyWritableDataPropertiesScriptContext();
  1103. public:
  1104. void ClearPrototypeChainEnsuredToHaveOnlyWritableDataPropertiesCaches();
  1105. public:
  1106. JavascriptString * GetLastNumberToStringRadix10(double value);
  1107. void SetLastNumberToStringRadix10(double value, JavascriptString * str);
  1108. bool GetLastUtcTimeFromStr(JavascriptString * str, double& dbl);
  1109. void SetLastUtcTimeFromStr(JavascriptString * str, double value);
  1110. bool IsNoContextSourceContextInfo(SourceContextInfo *sourceContextInfo) const
  1111. {
  1112. return sourceContextInfo == cache->noContextSourceContextInfo;
  1113. }
  1114. BOOL IsProfiling()
  1115. {
  1116. #ifdef ENABLE_SCRIPT_PROFILING
  1117. return (m_pProfileCallback != nullptr);
  1118. #else
  1119. return FALSE;
  1120. #endif
  1121. }
  1122. BOOL IsInProfileCallback()
  1123. {
  1124. #ifdef ENABLE_SCRIPT_PROFILING
  1125. return m_inProfileCallback;
  1126. #else
  1127. return FALSE;
  1128. #endif
  1129. }
  1130. #if DBG
  1131. SourceContextInfo const * GetNoContextSourceContextInfo() const { return cache->noContextSourceContextInfo; }
  1132. #ifdef ENABLE_SCRIPT_PROFILING
  1133. int GetProfileSession()
  1134. {
  1135. AssertMsg(m_pProfileCallback != nullptr, "Asking for profile session when we aren't in one.");
  1136. return m_iProfileSession;
  1137. }
  1138. void StartNewProfileSession()
  1139. {
  1140. AssertMsg(m_pProfileCallback != nullptr, "New Session when the profiler isn't set to any callback.");
  1141. m_iProfileSession++;
  1142. }
  1143. void StopProfileSession()
  1144. {
  1145. AssertMsg(m_pProfileCallback == nullptr, "How to stop when there is still the callback out there");
  1146. }
  1147. #endif // ENABLE_SCRIPT_PROFILING
  1148. bool hadProfiled;
  1149. bool HadProfiled() const { return hadProfiled; }
  1150. #endif
  1151. SRCINFO *AddHostSrcInfo(SRCINFO const *pSrcInfo);
  1152. #ifdef ENABLE_SCRIPT_PROFILING
  1153. inline void CoreSetProfileEventMask(DWORD dwEventMask);
  1154. typedef HRESULT (*RegisterExternalLibraryType)(Js::ScriptContext *pScriptContext);
  1155. HRESULT RegisterProfileProbe(IActiveScriptProfilerCallback *pProfileCallback, DWORD dwEventMask, DWORD dwContext, RegisterExternalLibraryType RegisterExternalLibrary, JavascriptMethod dispatchInvoke);
  1156. HRESULT SetProfileEventMask(DWORD dwEventMask);
  1157. HRESULT DeRegisterProfileProbe(HRESULT hrReason, JavascriptMethod dispatchInvoke);
  1158. HRESULT RegisterScript(Js::FunctionProxy *pFunctionBody, BOOL fRegisterScript = TRUE);
  1159. // Register static and dynamic scripts
  1160. HRESULT RegisterAllScripts();
  1161. HRESULT RegisterLibraryFunction(const char16 *pwszObjectName, const char16 *pwszFunctionName, Js::PropertyId functionPropertyId, JavascriptMethod entryPoint);
  1162. HRESULT RegisterBuiltinFunctions(RegisterExternalLibraryType RegisterExternalLibrary);
  1163. void SetFunctionInRecyclerToProfileMode(bool enumerateNonUserFunctionsOnly = false);
  1164. static void SetEntryPointToProfileThunk(JavascriptFunction* function);
  1165. static void RestoreEntryPointFromProfileThunk(JavascriptFunction* function);
  1166. #endif
  1167. #ifdef ENABLE_SCRIPT_DEBUGGING
  1168. // Iterate through utf8sourceinfo and clear debug document if they are there.
  1169. void EnsureClearDebugDocument();
  1170. // To be called directly only when the thread context is shutting down
  1171. void ShutdownClearSourceLists();
  1172. void RegisterDebugThunk(bool calledDuringAttach = true);
  1173. void UnRegisterDebugThunk();
  1174. static void RecyclerEnumClassEnumeratorCallback(void *address, size_t size);
  1175. static void RecyclerFunctionCallbackForDebugger(void *address, size_t size);
  1176. void UpdateRecyclerFunctionEntryPointsForDebugger();
  1177. #endif
  1178. static ushort ProcessNameAndGetLength(Js::StringBuilder<ArenaAllocator>* nameBuffer, const WCHAR* name);
  1179. #ifdef ASMJS_PLAT
  1180. void TransitionEnvironmentForDebugger(ScriptFunction * scriptFunction);
  1181. #endif
  1182. #if ENABLE_NATIVE_CODEGEN
  1183. HRESULT RecreateNativeCodeGenerator();
  1184. #endif
  1185. HRESULT OnDebuggerAttached();
  1186. HRESULT OnDebuggerDetached();
  1187. HRESULT OnDebuggerAttachedDetached(bool attach);
  1188. void InitializeDebugging();
  1189. bool IsForceNoNative();
  1190. bool IsEnumeratingRecyclerObjects() const { return isEnumeratingRecyclerObjects; }
  1191. private:
  1192. class AutoEnumeratingRecyclerObjects
  1193. {
  1194. public:
  1195. AutoEnumeratingRecyclerObjects(ScriptContext* scriptContext):
  1196. m_scriptContext(scriptContext)
  1197. {
  1198. Assert(!m_scriptContext->IsEnumeratingRecyclerObjects());
  1199. m_scriptContext->isEnumeratingRecyclerObjects = true;
  1200. }
  1201. ~AutoEnumeratingRecyclerObjects()
  1202. {
  1203. Assert(m_scriptContext->IsEnumeratingRecyclerObjects());
  1204. m_scriptContext->isEnumeratingRecyclerObjects = false;
  1205. }
  1206. private:
  1207. ScriptContext* m_scriptContext;
  1208. };
  1209. #ifdef EDIT_AND_CONTINUE
  1210. private:
  1211. ScriptEditQuery* activeScriptEditQuery;
  1212. void BeginScriptEditEnumFunctions(ScriptEditQuery* scriptEditQuery) { Assert(!activeScriptEditQuery); activeScriptEditQuery = scriptEditQuery; }
  1213. void EndScriptEditEnumFunctions() { Assert(activeScriptEditQuery); activeScriptEditQuery = nullptr; }
  1214. public:
  1215. ScriptEditQuery* GetActiveScriptEditQuery() const { return activeScriptEditQuery; }
  1216. class AutoScriptEditEnumFunctions
  1217. {
  1218. public:
  1219. AutoScriptEditEnumFunctions(ScriptContext* scriptContext, ScriptEditQuery* scriptEditQuery) : m_scriptContext(scriptContext)
  1220. {
  1221. scriptContext->BeginScriptEditEnumFunctions(scriptEditQuery);
  1222. }
  1223. ~AutoScriptEditEnumFunctions() { m_scriptContext->EndScriptEditEnumFunctions(); }
  1224. private:
  1225. ScriptContext* m_scriptContext;
  1226. };
  1227. #endif
  1228. private:
  1229. typedef JsUtil::BaseDictionary<JavascriptMethod, Js::PropertyId, ArenaAllocator, PrimeSizePolicy> BuiltinFunctionIdDictionary;
  1230. BuiltinFunctionIdDictionary *m_pBuiltinFunctionIdMap;
  1231. Js::PropertyId GetFunctionNumber(JavascriptMethod entryPoint);
  1232. static const char16* CopyString(const char16* str, size_t charCount, ArenaAllocator* alloc);
  1233. static charcount_t AppendWithEscapeCharacters(Js::StringBuilder<ArenaAllocator>* stringBuilder, const WCHAR* sourceString, charcount_t sourceStringLen, WCHAR escapeChar, WCHAR charToEscape);
  1234. public:
  1235. #if DYNAMIC_INTERPRETER_THUNK
  1236. JavascriptMethod GetNextDynamicAsmJsInterpreterThunk(PVOID* ppDynamicInterpreterThunk);
  1237. JavascriptMethod GetNextDynamicInterpreterThunk(PVOID* ppDynamicInterpreterThunk);
  1238. BOOL IsDynamicInterpreterThunk(void* address);
  1239. void ReleaseDynamicInterpreterThunk(BYTE* address, bool addtoFreeList);
  1240. void ReleaseDynamicAsmJsInterpreterThunk(BYTE* address, bool addtoFreeList);
  1241. #endif
  1242. static Var DebugProfileProbeThunk(RecyclableObject* function, CallInfo callInfo, ...);
  1243. static JavascriptMethod ProfileModeDeferredParse(ScriptFunction **function);
  1244. static Var ProfileModeDeferredParsingThunk(RecyclableObject* function, CallInfo callInfo, ...);
  1245. // Thunks for deferred deserialization of function bodies from the byte code cache
  1246. static JavascriptMethod ProfileModeDeferredDeserialize(ScriptFunction* function);
  1247. static Var ProfileModeDeferredDeserializeThunk(RecyclableObject* function, CallInfo callInfo, ...);
  1248. #ifdef ENABLE_SCRIPT_PROFILING
  1249. void SetProfileMode(BOOL fSet);
  1250. static JavascriptMethod GetProfileModeThunk(JavascriptMethod entryPoint);
  1251. static Var ProfileModeThunk_DebugModeWrapper(JavascriptFunction* function, ScriptContext* scriptContext, JavascriptMethod entryPoint, Arguments& args);
  1252. BOOL GetProfileInfo(
  1253. JavascriptFunction* function,
  1254. PROFILER_TOKEN &scriptId,
  1255. PROFILER_TOKEN &functionId);
  1256. HRESULT OnScriptCompiled(PROFILER_TOKEN scriptId, PROFILER_SCRIPT_TYPE type, IUnknown *pIDebugDocumentContext);
  1257. HRESULT OnFunctionCompiled(
  1258. PROFILER_TOKEN functionId,
  1259. PROFILER_TOKEN scriptId,
  1260. const WCHAR *pwszFunctionName,
  1261. const WCHAR *pwszFunctionNameHint,
  1262. IUnknown *pIDebugDocumentContext);
  1263. HRESULT OnFunctionEnter(PROFILER_TOKEN scriptId, PROFILER_TOKEN functionId);
  1264. HRESULT OnFunctionExit(PROFILER_TOKEN scriptId, PROFILER_TOKEN functionId);
  1265. static HRESULT FunctionExitSenderThunk(PROFILER_TOKEN functionId, PROFILER_TOKEN scriptId, ScriptContext *pScriptContext);
  1266. static HRESULT FunctionExitByNameSenderThunk(const char16 *pwszFunctionName, ScriptContext *pScriptContext);
  1267. #endif // ENABLE_SCRIPT_PROFILING
  1268. bool SetDispatchProfile(bool fSet, JavascriptMethod dispatchInvoke);
  1269. HRESULT OnDispatchFunctionEnter(const WCHAR *pwszFunctionName);
  1270. HRESULT OnDispatchFunctionExit(const WCHAR *pwszFunctionName);
  1271. void OnStartupComplete();
  1272. void SaveStartupProfileAndRelease(bool isSaveOnClose = false);
  1273. #if ENABLE_PROFILE_INFO
  1274. void AddDynamicProfileInfo(FunctionBody * functionBody, WriteBarrierPtr<DynamicProfileInfo>* dynamicProfileInfo);
  1275. #endif
  1276. #if DBG || defined(RUNTIME_DATA_COLLECTION)
  1277. uint allocId;
  1278. #endif
  1279. #ifdef PROFILE_EXEC
  1280. void DisableProfiler();
  1281. void SetRecyclerProfiler();
  1282. void SetProfilerFromScriptContext(ScriptContext * scriptContext);
  1283. void ProfileBegin(Js::Phase);
  1284. void ProfileEnd(Js::Phase);
  1285. void ProfileSuspend(Js::Phase, Js::Profiler::SuspendRecord * suspendRecord);
  1286. void ProfileResume(Js::Profiler::SuspendRecord * suspendRecord);
  1287. void ProfilePrint();
  1288. bool IsProfilerCreated() const { return isProfilerCreated; }
  1289. #endif
  1290. #ifdef PROFILE_MEM
  1291. void DisableProfileMemoryDumpOnDelete() { profileMemoryDump = false; }
  1292. #endif
  1293. #ifdef PROFILE_STRINGS
  1294. StringProfiler * GetStringProfiler(); // May be null if string profiling not enabled
  1295. #endif
  1296. public:
  1297. void SetBuiltInLibraryFunction(JavascriptMethod entryPoint, JavascriptFunction* function);
  1298. JavascriptFunction* GetBuiltInLibraryFunction(JavascriptMethod entryPoint);
  1299. private:
  1300. typedef JsUtil::BaseDictionary<JavascriptMethod, JavascriptFunction*, Recycler, PowerOf2SizePolicy> BuiltInLibraryFunctionMap;
  1301. BuiltInLibraryFunctionMap* builtInLibraryFunctions;
  1302. #ifdef RECYCLER_PERF_COUNTERS
  1303. size_t bindReferenceCount;
  1304. #endif
  1305. ScriptContext * nextPendingClose;
  1306. public:
  1307. void SetNextPendingClose(ScriptContext * nextPendingClose);
  1308. inline ScriptContext * GetNextPendingClose() const { return nextPendingClose; }
  1309. #ifdef ENABLE_MUTATION_BREAKPOINT
  1310. // Keep track of all breakpoints in order to properly clean up on debugger detach
  1311. bool HasMutationBreakpoints();
  1312. void InsertMutationBreakpoint(Js::MutationBreakpoint *mutationBreakpoint);
  1313. #endif
  1314. };
  1315. class AutoDynamicCodeReference
  1316. {
  1317. public:
  1318. AutoDynamicCodeReference(ScriptContext* scriptContext):
  1319. m_scriptContext(scriptContext)
  1320. {
  1321. scriptContext->BeginDynamicFunctionReferences();
  1322. }
  1323. ~AutoDynamicCodeReference()
  1324. {
  1325. m_scriptContext->EndDynamicFunctionReferences();
  1326. }
  1327. private:
  1328. ScriptContext* m_scriptContext;
  1329. };
  1330. template <typename TCacheType>
  1331. void ScriptContext::CleanDynamicFunctionCache(TCacheType* cacheType)
  1332. {
  1333. // Remove eval map functions that haven't been recently used
  1334. // TODO: Metric based on allocation size too? So don't clean if there hasn't been much allocated?
  1335. cacheType->Clean([this](const TCacheType::KeyType& key, TCacheType::ValueType value) {
  1336. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  1337. if (CONFIG_FLAG(DumpEvalStringOnRemoval))
  1338. {
  1339. Output::Print(_u("EvalMap: Removing Dynamic Function String from dynamic function cache: %s\n"), key.str.GetBuffer()); Output::Flush();
  1340. }
  1341. #endif
  1342. });
  1343. }
  1344. template <class TDelegate>
  1345. void ScriptContext::MapFunction(TDelegate mapper)
  1346. {
  1347. if (this->sourceList)
  1348. {
  1349. this->sourceList->Map([&mapper](int, RecyclerWeakReference<Js::Utf8SourceInfo>* sourceInfo)
  1350. {
  1351. Utf8SourceInfo* sourceInfoStrongRef = sourceInfo->Get();
  1352. if (sourceInfoStrongRef)
  1353. {
  1354. sourceInfoStrongRef->MapFunction(mapper);
  1355. }
  1356. });
  1357. }
  1358. }
  1359. template <class TDelegate>
  1360. FunctionBody* ScriptContext::FindFunction(TDelegate predicate)
  1361. {
  1362. FunctionBody* functionBody = nullptr;
  1363. this->sourceList->MapUntil([&functionBody, &predicate](int, RecyclerWeakReference<Js::Utf8SourceInfo>* sourceInfo) -> bool
  1364. {
  1365. Utf8SourceInfo* sourceInfoStrongRef = sourceInfo->Get();
  1366. if (sourceInfoStrongRef)
  1367. {
  1368. functionBody = sourceInfoStrongRef->FindFunction(predicate);
  1369. if (functionBody)
  1370. {
  1371. return true;
  1372. }
  1373. }
  1374. return false;
  1375. });
  1376. return functionBody;
  1377. }
  1378. }
  1379. #define BEGIN_TEMP_ALLOCATOR(allocator, scriptContext, name) \
  1380. Js::TempArenaAllocatorObject *temp##allocator = scriptContext->GetTemporaryAllocator(name); \
  1381. ArenaAllocator * allocator = temp##allocator->GetAllocator();
  1382. #define END_TEMP_ALLOCATOR(allocator, scriptContext) \
  1383. scriptContext->ReleaseTemporaryAllocator(temp##allocator);
  1384. #define DECLARE_TEMP_ALLOCATOR(allocator) \
  1385. Js::TempArenaAllocatorObject *temp##allocator = nullptr; \
  1386. ArenaAllocator * allocator = nullptr;
  1387. #define ACQUIRE_TEMP_ALLOCATOR(allocator, scriptContext, name) \
  1388. temp##allocator = scriptContext->GetTemporaryAllocator(name); \
  1389. allocator = temp##allocator->GetAllocator();
  1390. #define RELEASE_TEMP_ALLOCATOR(allocator, scriptContext) \
  1391. if (temp##allocator) \
  1392. scriptContext->ReleaseTemporaryAllocator(temp##allocator);
  1393. #define DECLARE_TEMP_GUEST_ALLOCATOR(allocator) \
  1394. Js::TempGuestArenaAllocatorObject *tempGuest##allocator = nullptr; \
  1395. ArenaAllocator * allocator = nullptr;
  1396. #define ACQUIRE_TEMP_GUEST_ALLOCATOR(allocator, scriptContext, name) \
  1397. tempGuest##allocator = scriptContext->GetTemporaryGuestAllocator(name); \
  1398. allocator = tempGuest##allocator->GetAllocator();
  1399. #define RELEASE_TEMP_GUEST_ALLOCATOR(allocator, scriptContext) \
  1400. if (tempGuest##allocator) \
  1401. scriptContext->ReleaseTemporaryGuestAllocator(tempGuest##allocator);