ConfigFlagsTable.h 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023
  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. ///----------------------------------------------------------------------------
  9. ///----------------------------------------------------------------------------
  10. ///
  11. /// enum FlagTypes
  12. ///
  13. /// Different types of flags supported by the debug table
  14. ///
  15. ///----------------------------------------------------------------------------
  16. ///----------------------------------------------------------------------------
  17. enum FlagTypes
  18. {
  19. InvalidFlagType,
  20. FlagString,
  21. FlagPhases,
  22. FlagNumber,
  23. FlagBoolean,
  24. FlagNumberSet,
  25. FlagNumberPairSet,
  26. FlagNumberTrioSet,
  27. FlagNumberRange
  28. };
  29. // Shadow of enum SCRIPTHOSTTYPE defined in activscp.idl.
  30. enum HostType
  31. {
  32. HostTypeDefault = 0, // Used to detect engines with uninitialized host type.
  33. HostTypeBrowser = 1, // Currently this implies enabled legacy language features, use it for IE.
  34. HostTypeApplication = 2, // Currently this implies legacy-free language features, use it for WWA.
  35. HostTypeWebview = 3, // Webview in a WWA/XAML app with WinRT access.
  36. HostTypeMin = HostTypeBrowser,
  37. HostTypeMax = HostTypeWebview
  38. };
  39. ///----------------------------------------------------------------------------
  40. ///----------------------------------------------------------------------------
  41. ///
  42. /// enum Flag
  43. ///
  44. /// All the flags available. The list of flags are described in the file
  45. /// ConfigFlagsList.h
  46. ///
  47. ///----------------------------------------------------------------------------
  48. ///----------------------------------------------------------------------------
  49. enum Flag: unsigned short
  50. {
  51. #define FLAG(type, name, ...) name##Flag,
  52. #include "ConfigFlagsList.h"
  53. FlagCount,
  54. InvalidFlag,
  55. NoParentFlag,
  56. FlagMax = NoParentFlag
  57. } ;
  58. ///----------------------------------------------------------------------------
  59. ///----------------------------------------------------------------------------
  60. ///
  61. /// enum Phase
  62. ///
  63. /// Different Phases/Subphases of the backend. The list of phases is described
  64. /// in the file ConfigFlagsList.h
  65. ///
  66. ///----------------------------------------------------------------------------
  67. ///----------------------------------------------------------------------------
  68. enum Phase: unsigned short
  69. {
  70. #define PHASE(name) name##Phase,
  71. #include "ConfigFlagsList.h"
  72. PhaseCount,
  73. InvalidPhase
  74. #undef PHASE
  75. };
  76. extern const char16* const FlagNames[FlagCount + 1];
  77. extern const char16* const PhaseNames[PhaseCount + 1];
  78. extern const Flag FlagParents[FlagCount + 1];
  79. typedef int Number;
  80. typedef bool Boolean;
  81. ///----------------------------------------------------------------------------
  82. ///----------------------------------------------------------------------------
  83. ///
  84. /// class String
  85. ///
  86. /// A simple string wrapper for storing strings for the flags. It creates a
  87. /// copy of the string which it releases in the destructor. Simple operator
  88. /// fiddling to make this class as interoperable with strings as possible :-
  89. ///
  90. /// 1. Single argument constructor takes care of initialization
  91. /// 2. Assignment operator overloaded for char16*
  92. /// 3. JavascriptConversion to const char16 * is defined. Making this constant ensures
  93. /// that a non constant char16 * does not point to our buffer which can
  94. /// potentially corrupt it.
  95. ///
  96. ///----------------------------------------------------------------------------
  97. ///----------------------------------------------------------------------------
  98. class String
  99. {
  100. PREVENT_COPYCONSTRUCT(String)
  101. // Data
  102. private:
  103. char16* pszValue;
  104. // Construction
  105. public:
  106. inline String();
  107. inline String(__in_z_opt const char16* psz);
  108. inline ~String();
  109. // Methods
  110. public:
  111. ///----------------------------------------------------------------------------
  112. ///
  113. /// Assignment operator defined for easy access
  114. ///
  115. ///----------------------------------------------------------------------------
  116. String& operator=(__in_z_opt const char16* psz)
  117. {
  118. Set(psz);
  119. return *this;
  120. }
  121. String &operator =(const String &other)
  122. {
  123. return (*this = other.pszValue);
  124. }
  125. ///----------------------------------------------------------------------------
  126. ///
  127. /// Typecast operator defined so we can directly use it with strings
  128. ///
  129. ///----------------------------------------------------------------------------
  130. operator const char16* () const
  131. {
  132. return this->pszValue;
  133. }
  134. // Implementation
  135. private:
  136. void Set(__in_z_opt const char16* pszValue);
  137. };
  138. class NumberSet
  139. {
  140. public:
  141. NumberSet();
  142. void Add(uint32 x);
  143. bool Contains(uint32 x);
  144. bool Empty() const { return set.Count() == 0; }
  145. private:
  146. JsUtil::BaseHashSet<uint32, NoCheckHeapAllocator, PrimeSizePolicy> set;
  147. };
  148. class NumberPair
  149. {
  150. public:
  151. NumberPair(uint32 x, uint32 y) : x(x), y(y) {}
  152. NumberPair() : x((uint32)-1), y((uint32)-1) {}
  153. operator hash_t() const { return (x << 16) + y; }
  154. bool operator ==(const NumberPair &other) const { return x == other.x && y == other.y; }
  155. private:
  156. uint32 x;
  157. uint32 y;
  158. };
  159. class NumberPairSet
  160. {
  161. public:
  162. NumberPairSet();
  163. void Add(uint32 x, uint32 y);
  164. bool Contains(uint32 x, uint32 y);
  165. bool Empty() const { return set.Count() == 0; }
  166. private:
  167. JsUtil::BaseHashSet<NumberPair, NoCheckHeapAllocator, PrimeSizePolicy> set;
  168. };
  169. class NumberTrio
  170. {
  171. public:
  172. NumberTrio(uint32 x, uint32 y, uint32 z) : x(x), y(y), z(z) {}
  173. NumberTrio() : x((uint32)-1), y((uint32)-1) {}
  174. operator hash_t() const { return (x << 20) + (y << 10) + z; }
  175. bool operator ==(const NumberTrio &other) const { return x == other.x && y == other.y && z == other.z; }
  176. private:
  177. uint32 x;
  178. uint32 y;
  179. uint32 z;
  180. };
  181. class NumberTrioSet
  182. {
  183. public:
  184. NumberTrioSet();
  185. void Add(uint32 x, uint32 y, uint32 z);
  186. bool Contains(uint32 x, uint32 y, uint32 z);
  187. bool Empty() const { return set.Count() == 0; }
  188. private:
  189. JsUtil::BaseHashSet<NumberTrio, NoCheckHeapAllocator, PrimeSizePolicy> set;
  190. };
  191. struct SourceFunctionNode
  192. {
  193. uint sourceContextId;
  194. Js::LocalFunctionId functionId;
  195. SourceFunctionNode(uint sourceContextId, Js::LocalFunctionId functionId) : sourceContextId(sourceContextId), functionId(functionId) {}
  196. SourceFunctionNode() : sourceContextId(0), functionId(0){}
  197. };
  198. ///----------------------------------------------------------------------------
  199. ///----------------------------------------------------------------------------
  200. ///
  201. /// struct RangeUnit
  202. ///
  203. /// Used to store a pair of bounds
  204. ///----------------------------------------------------------------------------
  205. ///----------------------------------------------------------------------------
  206. template <typename TRangeUnitData>
  207. struct RangeUnit
  208. {
  209. TRangeUnitData i, j;
  210. RangeUnit() {}
  211. RangeUnit(TRangeUnitData x, TRangeUnitData y) :
  212. i(x),
  213. j(y)
  214. {}
  215. };
  216. template <typename TRangeUnitData>
  217. bool RangeUnitContains(RangeUnit<TRangeUnitData> unit, TRangeUnitData item)
  218. {
  219. return (item >= unit.i && item <= unit.j);
  220. }
  221. template <>
  222. bool RangeUnitContains<SourceFunctionNode>(RangeUnit<SourceFunctionNode> unit, SourceFunctionNode n);
  223. template <typename TRangeUnitData>
  224. RangeUnit<TRangeUnitData> GetFullRange()
  225. {
  226. RangeUnit<TRangeUnitData> unit;
  227. unit.i = INT_MIN;
  228. unit.j = INT_MAX;
  229. return unit;
  230. }
  231. template <>
  232. RangeUnit<SourceFunctionNode> GetFullRange();
  233. template <typename TRangeUnitData>
  234. TRangeUnitData GetPrevious(TRangeUnitData unit)
  235. {
  236. return unit - 1;
  237. }
  238. template <>
  239. SourceFunctionNode GetPrevious(SourceFunctionNode unit);
  240. template <typename TRangeUnitData>
  241. TRangeUnitData GetNext(TRangeUnitData unit)
  242. {
  243. return unit + 1;
  244. }
  245. template <>
  246. SourceFunctionNode GetNext(SourceFunctionNode unit);
  247. ///----------------------------------------------------------------------------
  248. ///----------------------------------------------------------------------------
  249. ///
  250. /// class Range
  251. ///
  252. /// Data structure to store a range of integers. (Can trivially be templatized
  253. /// but resisting the temptation for the sake of simplicity.)
  254. ///
  255. /// Sample: 1,3-11,15,20
  256. ///
  257. ///----------------------------------------------------------------------------
  258. ///----------------------------------------------------------------------------
  259. template <typename TRangeUnitData>
  260. class RangeBase
  261. {
  262. // Nested Classes
  263. public:
  264. typedef RangeUnit<TRangeUnitData> Unit;
  265. // Data
  266. protected:
  267. SList<Unit, NoCheckHeapAllocator> range;
  268. // Construction
  269. public:
  270. RangeBase() : range(&NoCheckHeapAllocator::Instance) {}
  271. // Methods
  272. public:
  273. inline bool InRange(TRangeUnitData i);
  274. inline bool ContainsAll();
  275. inline void Add(TRangeUnitData i, RangeBase<TRangeUnitData>* oppositeRange = nullptr);
  276. inline void Add(TRangeUnitData i, TRangeUnitData j, RangeBase<TRangeUnitData>* oppositeRange = nullptr);
  277. inline void Clear();
  278. #if DBG_RANGE
  279. template <typename TFunction>
  280. void Map(TFunction fn) const
  281. {
  282. range.Map(fn);
  283. }
  284. #endif
  285. };
  286. class Range : public RangeBase<SourceFunctionNode> {};
  287. class NumberRange : public RangeBase<int> {};
  288. ///----------------------------------------------------------------------------
  289. ///----------------------------------------------------------------------------
  290. ///
  291. /// class Phases
  292. ///
  293. /// Maintains the list of all the phases. Each individual phase can be enabled
  294. /// and an optional range of numbers can be added to it
  295. ///
  296. ///----------------------------------------------------------------------------
  297. ///----------------------------------------------------------------------------
  298. class Phases
  299. {
  300. // Nested Types
  301. private:
  302. ///----------------------------------------------------------------------------
  303. ///----------------------------------------------------------------------------
  304. ///
  305. /// struct UnitPhase
  306. ///
  307. /// Stores information about a particular phase. Current information is :
  308. /// 1. Is the phase enabled/disabled?
  309. /// 2. A range of numbers for the given phase. This range can represent a
  310. /// variety of information. For example, this range can be the function
  311. /// numbers of all the functions where a particular optimization is
  312. /// enabled or where opcode dump is enabled.
  313. ///
  314. ///
  315. /// Its a tiny private struct used by Phases for simply storing data. So
  316. /// making this a struct with all members public.
  317. ///
  318. ///----------------------------------------------------------------------------
  319. ///----------------------------------------------------------------------------
  320. struct UnitPhase
  321. {
  322. // Construction
  323. public:
  324. UnitPhase() : valid(false) { }
  325. // Data
  326. public:
  327. bool valid;
  328. Range range;
  329. };
  330. // Data
  331. private:
  332. UnitPhase phaseList[PhaseCount];
  333. // Constructors
  334. public:
  335. Phases() {}
  336. // Methods
  337. public:
  338. void Enable(Phase phase);
  339. void Disable(Phase phase);
  340. bool IsEnabled(Phase phase);
  341. bool IsEnabled(Phase phase, uint sourceContextId, Js::LocalFunctionId functionId);
  342. bool IsEnabledForAll(Phase phase);
  343. Range * GetRange(Phase phase);
  344. Phase GetFirstPhase();
  345. };
  346. ///----------------------------------------------------------------------------
  347. ///----------------------------------------------------------------------------
  348. ///
  349. /// class ConfigFlagsTable
  350. ///
  351. /// Maintains the list of all the flags. Individual flags can be accessed by :-
  352. ///
  353. /// 1. flagTable->verbose; // here verbose is the name of the flag
  354. /// // It will be strongly typed with the
  355. /// // type of the flag is as described in
  356. /// // ConfigFlagsTable.h
  357. ///
  358. /// 2. flagTable->GetAsBoolean(verboseFlag);
  359. /// // this access is weekly typed. Even if the
  360. /// // flag is not of type Boolean, it will be
  361. /// // reinterpret_cast to Boolean *
  362. ///
  363. /// The former access should be used in the code for reading the flag values
  364. /// while the later is useful for adding values into the table.
  365. ///
  366. ///----------------------------------------------------------------------------
  367. ///----------------------------------------------------------------------------
  368. class ConfigFlagsTable
  369. {
  370. // Constructor
  371. public:
  372. ConfigFlagsTable();
  373. // Methods
  374. public:
  375. static Flag GetFlag(__in LPCWSTR str);
  376. static Phase GetPhase(__in LPCWSTR str);
  377. static void PrintUsageString();
  378. static FlagTypes GetFlagType(Flag flag);
  379. String* GetAsString(Flag flag) const;
  380. Phases* GetAsPhase(Flag flag) const;
  381. Flag GetOppositePhaseFlag(Flag flag) const;
  382. Boolean* GetAsBoolean(Flag flag) const;
  383. Number* GetAsNumber(Flag flag) const;
  384. NumberSet* GetAsNumberSet(Flag flag) const;
  385. NumberPairSet * GetAsNumberPairSet(Flag flag) const;
  386. NumberTrioSet * GetAsNumberTrioSet(Flag flag) const;
  387. NumberRange * GetAsNumberRange(Flag flag) const;
  388. void SetAsBoolean(Flag flag, Boolean value);
  389. Boolean GetDefaultValueAsBoolean(Flag flag) const;
  390. // indicates whether a flag is a parent flag
  391. bool IsParentFlag(Flag flag) const;
  392. // get the parent flag of a given flag, if any, otherwise returns InvalidFlag.
  393. Flag GetParentFlag(Flag flag) const;
  394. // get the next child flag of a given parent flag, if any, otherwise returns InvalidFlag. Pass InvalidFlag as currentChildFlag if no current child flag to iterate from.
  395. Flag GetNextChildFlag(Flag parentFlag, Flag currentChildFlag) const;
  396. void Enable(Flag flag);
  397. bool IsEnabled(Flag flag);
  398. void Disable(Flag flag);
  399. void VerboseDump();
  400. // Data
  401. public:
  402. ///----------------------------------------------------------------------------
  403. ///
  404. /// Declaration of each flag as a member variable of the corresponding type.
  405. /// These variables are made public because get/set are too ugly for simple
  406. /// flags. Besides there are flags like phase lists which are not simple and
  407. /// its better to have a uniform way to access them.
  408. ///
  409. /// if(ConfigFlag->dump) is much better than
  410. /// if(ConfigFlag->GetDump())
  411. ///
  412. ///----------------------------------------------------------------------------
  413. #define FLAG(type, name, ...) \
  414. \
  415. type name; \
  416. #include "ConfigFlagsList.h"
  417. bool flagPresent[FlagCount];
  418. #if defined(ENABLE_DEBUG_CONFIG_OPTIONS) && CONFIG_PARSE_CONFIG_FILE
  419. // save the jscript.config for easier to get the raw input while analyzing dump file
  420. char16 rawInputFromConfigFile[512];
  421. int rawInputFromConfigFileIndex;
  422. #endif
  423. private:
  424. //
  425. // This variable is defined for the constructor
  426. //
  427. int nDummy;
  428. // indicates whether a flag is a parent flag
  429. bool flagIsParent[FlagMax + 1];
  430. // Implementation
  431. private:
  432. void * GetProperty(Flag flag) const;
  433. void SetAllParentFlagsAsDefaultValue();
  434. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  435. // special callback logic
  436. void FlagSetCallback_ES6All(Js::Boolean value);
  437. void FlagSetCallback_ES6Experimental(Js::Boolean value);
  438. #endif
  439. public:
  440. void FinalizeConfiguration();
  441. void EnableExperimentalFlag();
  442. // Some config flags are expected to be constant during the lifetime of
  443. // a ScriptContext object. However, some other flags can change,
  444. // possibly multiple times.
  445. //
  446. // To keep the flags constant during the lifetime of a ScriptContext
  447. // object, we copy the ones that it needs into ThreadContext and have
  448. // it fetch them from ThreadContext instead of here. Given that a
  449. // ScriptContext object is bound to a ThreadContext object and never
  450. // gets reassigned, this keeps the flags constant while the
  451. // ScriptContext object is alive.
  452. //
  453. // Currently, among the flags used by ScriptContext, only the
  454. // experimental flags are altered after initialization. Therefore, only
  455. // access to these flags are serialized.
  456. //
  457. // Note that this lock is acquired automatically only when the
  458. // experimental flags are initialized via the EnableExperimentalFlag()
  459. // method. It should be manually acquired anywhere else where these
  460. // flags are accessed.
  461. CriticalSection csExperimentalFlags;
  462. private:
  463. void TransferAcronymFlagConfiguration();
  464. void TranslateFlagConfiguration();
  465. };
  466. class Profiler;
  467. class Configuration
  468. {
  469. public:
  470. ConfigFlagsTable flags;
  471. static Configuration Global;
  472. bool EnableJitInDebugMode();
  473. // Public in case the client wants to have
  474. // a separate config from the global one
  475. Configuration();
  476. };
  477. //Create macros for a useful subset of the config options that either get the value from the configuration (if the option is enabled) or
  478. //just use the hard coded default value (if not). All the ...IsEnabled(...) default to false.
  479. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  480. #define CONFIG_ISENABLED(flag) (Js::Configuration::Global.flags.IsEnabled(flag))
  481. #define CUSTOM_CONFIG_ISENABLED(flags, flag) (flags.IsEnabled(flag))
  482. #define CONFIG_FLAG(flag) (Js::Configuration::Global.flags.##flag)
  483. #define CUSTOM_CONFIG_FLAG(flags, flag) (flags.##flag)
  484. #define CONFIG_FLAG_RELEASE(flag) CONFIG_FLAG(flag)
  485. #define CONFIG_FLAG_CONTAINS(flag, func) (Js::Configuration::Global.flags.##flag.Contains((func)->GetLocalFunctionId()))
  486. #define PHASE_OFF_PROFILED_BYTE_CODE(phase, func) Js::Configuration::Global.flags.OffProfiledByteCode.IsEnabled((phase),(func)->GetSourceContextId(),(func)->GetLocalFunctionId())
  487. #define PHASE_OFF_PROFILED_BYTE_CODE_ALL(phase) Js::Configuration::Global.flags.OffProfiledByteCode.IsEnabledForAll((phase))
  488. #define PHASE_OFF_PROFILED_BYTE_CODE_OPTFUNC(phase, func) ((func) ? PHASE_OFF_PROFILED_BYTE_CODE(phase, func) : PHASE_OFF_PROFILED_BYTE_CODE_ALL(phase))
  489. #define PHASE_OFF1(phase) Js::Configuration::Global.flags.Off.IsEnabled((phase))
  490. #define CUSTOM_PHASE_OFF1(flags, phase) flags.Off.IsEnabled((phase))
  491. #define PHASE_OFF_ALL(phase) Js::Configuration::Global.flags.Off.IsEnabledForAll((phase))
  492. #define PHASE_OFF(phase, func) PHASE_OFF_RAW((phase), (func)->GetSourceContextId(), (func)->GetLocalFunctionId())
  493. #define PHASE_OFF_OPTFUNC(phase, func) ((func) ? PHASE_OFF(phase, func) : PHASE_OFF_ALL(phase))
  494. #define PHASE_OFF_RAW(phase, sourceId, functionId) \
  495. Js::Configuration::Global.flags.Off.IsEnabled((phase), (sourceId), (functionId))
  496. #define PHASE_ON1(phase) Js::Configuration::Global.flags.On.IsEnabled((phase))
  497. #define CUSTOM_PHASE_ON1(flags, phase) flags.On.IsEnabled((phase))
  498. #define PHASE_ON(phase, func) PHASE_ON_RAW((phase), (func)->GetSourceContextId(), (func)->GetLocalFunctionId())
  499. #define PHASE_ON_RAW(phase, sourceId, functionId) \
  500. Js::Configuration::Global.flags.On.IsEnabled((phase), (sourceId), (functionId))
  501. #define PHASE_FORCE1(phase) Js::Configuration::Global.flags.Force.IsEnabled((phase))
  502. #define CUSTOM_PHASE_FORCE1(flags, phase) flags.Force.IsEnabled((phase))
  503. #define PHASE_FORCE(phase, func) PHASE_FORCE_RAW((phase), (func)->GetSourceContextId(), (func)->GetLocalFunctionId())
  504. #define PHASE_FORCE_OPTFUNC(phase, func) ((func) ? PHASE_FORCE(phase, func) : PHASE_FORCE1(phase))
  505. #define PHASE_FORCE_RAW(phase, sourceId, functionId) \
  506. Js::Configuration::Global.flags.Force.IsEnabled((phase), (sourceId), (functionId))
  507. #define PHASE_STRESS1(phase) Js::Configuration::Global.flags.Stress.IsEnabled((phase))
  508. #define PHASE_STRESS(phase, func) PHASE_STRESS_RAW((phase), (func)->GetSourceContextId(), (func)->GetLocalFunctionId())
  509. #define PHASE_STRESS_RAW(phase, sourceId, functionId) \
  510. Js::Configuration::Global.flags.Stress.IsEnabled((phase), (sourceId), (functionId))
  511. #define PHASE_TRACE1(phase) Js::Configuration::Global.flags.Trace.IsEnabled((phase))
  512. #define CUSTOM_PHASE_TRACE1(flags, phase) flags.Trace.IsEnabled((phase))
  513. #define PHASE_TRACE(phase, func) PHASE_TRACE_RAW((phase), (func)->GetSourceContextId(), (func)->GetLocalFunctionId())
  514. #define PHASE_TRACE_RAW(phase, sourceId, functionId) \
  515. Js::Configuration::Global.flags.Trace.IsEnabled((phase), (sourceId), (functionId))
  516. #if DBG
  517. // Enabling the ability to trace the StringConcat phase only in debug builds due to performance impact
  518. #define PHASE_TRACE_StringConcat PHASE_TRACE1(Js::StringConcatPhase)
  519. #else
  520. #define PHASE_TRACE_StringConcat (false)
  521. #endif
  522. #define PHASE_VERBOSE_TRACE1(phase) \
  523. ((PHASE_TRACE1((phase))) && Js::Configuration::Global.flags.Verbose)
  524. #define CUSTOM_PHASE_VERBOSE_TRACE1(flags, phase) \
  525. ((CUSTOM_PHASE_TRACE1((flags), (phase))) && flags.Verbose)
  526. #define PHASE_VERBOSE_TRACE(phase, func) \
  527. ((PHASE_TRACE((phase), (func))) && Js::Configuration::Global.flags.Verbose)
  528. #define PHASE_VERBOSE_TRACE_RAW(phase, sourceId, functionId) \
  529. ((PHASE_TRACE_RAW((phase), (sourceId), (functionId))) && Js::Configuration::Global.flags.Verbose)
  530. #define PHASE_DUMP1(phase) Js::Configuration::Global.flags.Dump.IsEnabled((phase))
  531. #define PHASE_DUMP(phase, func) Js::Configuration::Global.flags.Dump.IsEnabled((phase), (func)->GetSourceContextId(),(func)->GetLocalFunctionId())
  532. #define PHASE_DEBUGBREAK_ON_PHASE_BEGIN(phase, func) Js::Configuration::Global.flags.DebugBreakOnPhaseBegin.IsEnabled((phase), (func)->GetSourceContextId(), (func)->GetLocalFunctionId())
  533. #define PHASE_STATS1(phase) Js::Configuration::Global.flags.Stats.IsEnabled((phase))
  534. #define CUSTOM_PHASE_STATS1(flags, phase) flags.Stats.IsEnabled((phase))
  535. #define PHASE_VERBOSE_STATS1(phase) \
  536. ((PHASE_STATS1(phase)) && Js::Configuration::Global.flags.Verbose)
  537. #define PHASE_STATS_ALL(phase) Js::Configuration::Global.flags.Stats.IsEnabledForAll((phase))
  538. #define PHASE_STATS(phase, func) PHASE_STATS_RAW((phase), (func)->GetSourceContextId(), (func)->GetLocalFunctionId())
  539. #define PHASE_STATS_RAW(phase, sourceId, functionId) \
  540. Js::Configuration::Global.flags.Stats.IsEnabled((phase), (sourceId), (functionId))
  541. #define PHASE_VERBOSE_STATS(phase, func) \
  542. ((PHASE_STATS(phase, func)) && Js::Configuration::Global.flags.Verbose)
  543. #define PHASE_VERBOSE_STATS_RAW(phase, sourceId, functionId) \
  544. ((PHASE_STATS_RAW(phase, sourceId, functionId)) && Js::Configuration::Global.flags.Verbose)
  545. #define PHASE_TESTTRACE1(phase) Js::Configuration::Global.flags.TestTrace.IsEnabled((phase))
  546. #define PHASE_TESTTRACE(phase, func) PHASE_TESTTRACE_RAW((phase), (func)->GetSourceContextId(), (func)->GetLocalFunctionId())
  547. #define PHASE_TESTTRACE_RAW(phase, sourceId, functionId) \
  548. Js::Configuration::Global.flags.TestTrace.IsEnabled((phase), (sourceId), (functionId))
  549. #ifdef ENABLE_BASIC_TELEMETRY
  550. #define PHASE_TESTTRACE1_TELEMETRY(phase) PHASE_TESTTRACE1((phase))
  551. #else
  552. #define PHASE_TESTTRACE1_TELEMETRY(phase) (false)
  553. #endif
  554. #define PHASE_PRINT_TRACE1(phase, ...) \
  555. if (PHASE_TRACE1(phase)) \
  556. { \
  557. Output::Print(__VA_ARGS__); \
  558. Output::Flush(); \
  559. }
  560. #define CUSTOM_PHASE_PRINT_TRACE1(flags, phase, ...) \
  561. if (CUSTOM_PHASE_TRACE1(flags, phase)) \
  562. { \
  563. Output::Print(__VA_ARGS__); \
  564. Output::Flush(); \
  565. }
  566. #define PHASE_PRINT_TRACE(phase, func, ...) \
  567. if (PHASE_TRACE(phase, func)) \
  568. { \
  569. Output::Print(__VA_ARGS__); \
  570. Output::Flush(); \
  571. }
  572. #define PHASE_PRINT_TRACE_RAW(phase, sourceId, functionId, ...) \
  573. if (PHASE_TRACE_RAW(phase, sourceId, functionId)) \
  574. { \
  575. Output::Print(__VA_ARGS__); \
  576. Output::Flush(); \
  577. }
  578. #define PHASE_PRINT_VERBOSE_TRACE1(phase, ...) \
  579. if (PHASE_VERBOSE_TRACE1(phase)) \
  580. { \
  581. Output::Print(__VA_ARGS__); \
  582. Output::Flush(); \
  583. }
  584. #define CUSTOM_PHASE_PRINT_VERBOSE_TRACE1(flags, phase, ...) \
  585. if (CUSTOM_PHASE_VERBOSE_TRACE1(flags, phase)) \
  586. { \
  587. Output::Print(__VA_ARGS__); \
  588. Output::Flush(); \
  589. }
  590. #define PHASE_PRINT_VERBOSE_TRACE(phase, func, ...) \
  591. if (PHASE_VERBOSE_TRACE(phase, func)) \
  592. { \
  593. Output::Print(__VA_ARGS__); \
  594. Output::Flush(); \
  595. }
  596. #define PHASE_PRINT_VERBOSE_TRACE_RAW(phase, sourceId, functionId, ...) \
  597. if (PHASE_VERBOSE_TRACE_RAW(phase, sourceId, functionId)) \
  598. { \
  599. Output::Print(__VA_ARGS__); \
  600. Output::Flush(); \
  601. }
  602. #define PHASE_VERBOSE_TESTTRACE1(phase) (PHASE_TESTTRACE1(phase) && Js::Configuration::Global.flags.Verbose)
  603. #define PHASE_VERBOSE_TESTTRACE(phase, func) \
  604. (PHASE_TESTTRACE(phase, func) && Js::Configuration::Global.flags.Verbose)
  605. #define PHASE_VERBOSE_TESTTRACE_RAW(phase, sourceId, functionId) \
  606. (PHASE_TESTTRACE_RAW(phase, sourceId, functionId) && Js::Configuration::Global.flags.Verbose)
  607. #define PHASE_PRINT_TESTTRACE1(phase, ...) \
  608. if (PHASE_TESTTRACE1(phase)) \
  609. { \
  610. Output::Print(__VA_ARGS__); \
  611. Output::Flush(); \
  612. }
  613. #define PHASE_PRINT_TESTTRACE(phase, func, ...) \
  614. if (PHASE_TESTTRACE(phase, func)) \
  615. { \
  616. Output::Print(__VA_ARGS__); \
  617. Output::Flush(); \
  618. }
  619. #define PHASE_PRINT_TESTTRACE_RAW(phase, sourceId, functionId, ...) \
  620. if (PHASE_TESTTRACE_RAW(phase, sourceId, functionId)) \
  621. { \
  622. Output::Print(__VA_ARGS__); \
  623. Output::Flush(); \
  624. }
  625. #define PHASE_PRINT_VERBOSE_TESTTRACE1(phase, ...) \
  626. if (PHASE_VERBOSE_TESTTRACE1(phase)) \
  627. { \
  628. Output::Print(__VA_ARGS__); \
  629. Output::Flush(); \
  630. }
  631. #define PHASE_PRINT_VERBOSE_TESTTRACE(phase, func, ...) \
  632. if (PHASE_VERBOSE_TESTTRACE(phase, func)) \
  633. { \
  634. Output::Print(__VA_ARGS__); \
  635. Output::Flush(); \
  636. }
  637. #define PHASE_PRINT_VERBOSE_TESTTRACE_RAW(phase, sourceId, functionId, ...) \
  638. if (PHASE_VERBOSE_TESTTRACE_RAW(phase, sourceId, functionId)) \
  639. { \
  640. Output::Print(__VA_ARGS__); \
  641. Output::Flush(); \
  642. }
  643. #else
  644. #define CONFIG_ISENABLED(flag) (false) //All flags.IsEnabled(foo) are false by default.
  645. #define CUSTOM_CONFIG_ISENABLED(flags, flag) (false) //All flags.IsEnabled(foo) are false by default.
  646. #define CONFIG_FLAG(flag) (DEFAULT_CONFIG_##flag)
  647. #define CUSTOM_CONFIG_FLAG(flags, flag) (DEFAULT_CONFIG_##flag)
  648. #define CONFIG_FLAG_RELEASE(flag) (Js::Configuration::Global.flags.##flag)
  649. #define CONFIG_FLAG_CONTAINS(flag, func) (false)
  650. #define PHASE_OFF_PROFILED_BYTE_CODE(phase, func) (false)
  651. #define PHASE_OFF_PROFILED_BYTE_CODE_ALL(phase) (false)
  652. #define PHASE_OFF_PROFILED_BYTE_CODE_OPTFUNC(phase, func) (false)
  653. #define PHASE_OFF1(phase) (false) //All flags.Off.IsEnabled(foo) are false by default
  654. #define CUSTOM_PHASE_OFF1(flags, phase) (false) //All flags.Off.IsEnabled(foo) are false by default
  655. #define PHASE_OFF_ALL(phase) (false)
  656. #define PHASE_OFF(phase, func) (false)
  657. #define PHASE_OFF_RAW(phase, sourceId, functionId) (false)
  658. #define PHASE_OFF_OPTFUNC(phase, func) (false)
  659. #define PHASE_ON1(phase) (false)
  660. #define CUSTOM_PHASE_ON1(flags, phase) (false)
  661. #define PHASE_ON(phase, func) (false)
  662. #define PHASE_ON_RAW(phase, sourceId, functionId) (false)
  663. #define PHASE_FORCE1(phase) (false)
  664. #define CUSTOM_PHASE_FORCE1(flags, phase) (false)
  665. #define PHASE_FORCE(phase, func) (false)
  666. #define PHASE_FORCE_RAW(phase, sourceId, functionId) (false)
  667. #define PHASE_FORCE_OPTFUNC(phase, func) (false)
  668. #define PHASE_STRESS1(phase) (false)
  669. #define PHASE_STRESS(phase, func) (false)
  670. #define PHASE_STRESS_RAW(phase, sourceId, functionId) (false)
  671. #define PHASE_TRACE1(phase) (false)
  672. #define CUSTOM_PHASE_TRACE1(phase) (false)
  673. #define PHASE_TRACE(phase, func) (false)
  674. #define PHASE_TRACE_RAW(phase, sourceId, functionId) (false)
  675. #define PHASE_TRACE_StringConcat (false)
  676. #define PHASE_VERBOSE_TRACE1(phase) (false)
  677. #define CUSTOM_PHASE_VERBOSE_TRACE1(flags, phase) (false)
  678. #define PHASE_VERBOSE_TRACE(phase, func) (false)
  679. #define PHASE_VERBOSE_TRACE_RAW(phase, sourceId, functionId) (false)
  680. #define PHASE_TESTTRACE1(phase) (false)
  681. #define PHASE_TESTTRACE(phase, func) (false)
  682. #define PHASE_TESTTRACE_RAW(phase, sourceId, functionId) (false)
  683. #define PHASE_TESTTRACE1_TELEMETRY(phase) (false)
  684. #define PHASE_PRINT_TRACE1(phase, ...)
  685. #define CUSTOM_PHASE_PRINT_TRACE1(phase, ...)
  686. #define PHASE_PRINT_TRACE(phase, func, ...)
  687. #define PHASE_PRINT_TRACE_RAW(phase, sourceId, functionId, ...)
  688. #define PHASE_PRINT_VERBOSE_TRACE1(phase, ...)
  689. #define CUSTOM_PHASE_PRINT_VERBOSE_TRACE1(phase, ...)
  690. #define PHASE_PRINT_VERBOSE_TRACE(phase, func, ...)
  691. #define PHASE_PRINT_VERBOSE_TRACE_RAW(phase, sourceId, functionId, ...)
  692. #define PHASE_VERBOSE_TESTTRACE1(phase) (false)
  693. #define PHASE_VERBOSE_TESTTRACE(phase, func) (false)
  694. #define PHASE_VERBOSE_TESTTRACE_RAW(phase, sourceId, functionId) (false)
  695. #define PHASE_VERBOSE_TRACE1(phase) (false)
  696. #define PHASE_VERBOSE_TRACE(phase, func) (false)
  697. #define PHASE_VERBOSE_TRACE_RAW(phase, sourceId, functionId) (false)
  698. #define PHASE_PRINT_TESTTRACE1(phase, ...)
  699. #define PHASE_PRINT_TESTTRACE(phase, func, ...)
  700. #define PHASE_PRINT_TESTTRACE_RAW(phase, sourceId, functionId, ...)
  701. #define PHASE_PRINT_VERBOSE_TESTTRACE1(phase, ...)
  702. #define PHASE_PRINT_VERBOSE_TESTTRACE(phase, func, ...)
  703. #define PHASE_PRINT_VERBOSE_TESTTRACE_RAW(phase, sourceId, functionId, ...)
  704. #define PHASE_DUMP(phase, func) (false) //All flags.Dump.IsEnabled(foo) are false by default
  705. #define PHASE_STATS1(phase) (false)
  706. #define CUSTOM_PHASE_STATS1(flags, phase) (false)
  707. #define PHASE_VERBOSE_STATS1(phase) (false)
  708. #define PHASE_STATS_ALL(phase) (false)
  709. #define PHASE_STATS(phase, func) (false)
  710. #define PHASE_STATS_RAW(phase, sourceId, functionId) (false)
  711. #define PHASE_VERBOSE_STATS(phase, func) (false)
  712. #define PHASE_VERBOSE_STATS_RAW(phase, sourceId, functionId) (false)
  713. #endif
  714. #ifdef ENABLE_REGEX_CONFIG_OPTIONS
  715. #define REGEX_CONFIG_FLAG(flag) (Js::Configuration::Global.flags.##flag)
  716. #else
  717. #define REGEX_CONFIG_FLAG(flag) (DEFAULT_CONFIG_##flag)
  718. #endif
  719. #ifdef SUPPORT_INTRUSIVE_TESTTRACES
  720. #define PHASE_PRINT_INTRUSIVE_TESTTRACE1(phase, ...) \
  721. PHASE_PRINT_TESTTRACE1(phase, __VA_ARGS__)
  722. #else
  723. #define PHASE_PRINT_INTRUSIVE_TESTTRACE1(phase, ...) (false)
  724. #endif
  725. #define PHASE_ENABLED1(phase) (Js::PhaseIsEnabled::phase())
  726. #define PHASE_ENABLED(phase, func) (Js::PhaseIsEnabled::phase(func))
  727. #define PHASE_ENABLED_RAW(phase, sourceId, functionId) \
  728. (Js::PhaseIsEnabled::phase(sourceId, functionId))
  729. struct PhaseIsEnabled
  730. {
  731. #define PHASE_DEFAULT_ON(name) \
  732. static bool name##Phase() { return !PHASE_OFF1(Js::name##Phase); } \
  733. template<typename FUNC> static bool name##Phase(FUNC func) { return !PHASE_OFF(Js::name##Phase, func); } \
  734. static bool name##Phase(uint sourceId, Js::LocalFunctionId functionId) { return !PHASE_OFF_RAW(Js::name##Phase, sourceId, functionId); }
  735. #define PHASE_DEFAULT_OFF(name) \
  736. static bool name##Phase() { return PHASE_ON1(Js::name##Phase); } \
  737. template<typename FUNC> static bool name##Phase(FUNC func) { return PHASE_ON(Js::name##Phase, func); } \
  738. static bool name##Phase(uint sourceId, Js::LocalFunctionId functionId) { return PHASE_ON_RAW(Js::name##Phase, sourceId, functionId); }
  739. #include "ConfigFlagsList.h"
  740. };
  741. ///----------------------------------------------------------------------------
  742. ///----------------------------------------------------------------------------
  743. ///
  744. /// class RangeBase
  745. ///
  746. ///----------------------------------------------------------------------------
  747. ///----------------------------------------------------------------------------
  748. template <typename TRangeUnitData>
  749. void
  750. RangeBase<TRangeUnitData>::Add(TRangeUnitData i, RangeBase<TRangeUnitData>* oppositeRange)
  751. {
  752. Add(i, i, oppositeRange);
  753. }
  754. template <typename TRangeUnitData>
  755. void
  756. RangeBase<TRangeUnitData>::Add(TRangeUnitData i, TRangeUnitData j, RangeBase<TRangeUnitData>* oppositeRange)
  757. {
  758. RangeUnit<TRangeUnitData> a(i, j);
  759. range.Prepend(a);
  760. if (oppositeRange)
  761. {
  762. if (oppositeRange->range.Empty())
  763. {
  764. oppositeRange->range.Prepend(GetFullRange<TRangeUnitData>());
  765. }
  766. // Do an intersection
  767. auto it = oppositeRange->range.GetEditingIterator();
  768. while (it.Next())
  769. {
  770. Unit& unit = it.Data();
  771. bool c1 = RangeUnitContains(unit, i);
  772. bool c2 = RangeUnitContains(unit, j);
  773. bool c3 = RangeUnitContains(a, unit.i);
  774. bool c4 = RangeUnitContains(a, unit.j);
  775. enum IntersectionCase
  776. {
  777. NoIntersection = 0,
  778. AddedFullyContained = 3, // [ u [a] ]
  779. IntersectionAdded_Unit = 6, // [ a [ ] u ]
  780. CommonLowBound_Unit = 7, // [[ a ] u ]
  781. IntersectionUnit_Added = 9, // [ u [ ] a ]
  782. CommonTopBound_Unit = 11, // [ u [ a ]]
  783. UnitFullyContained = 12, // [ a [u] ]
  784. CommonLowBound_Added = 13, // [[ u ] a ]
  785. CommonTopBound_Added = 14, // [ a [ u ]]
  786. FullIntersection = 15 // [[a, u]]
  787. };
  788. IntersectionCase intersectionCase = (IntersectionCase)((int)c1 | (c2 << 1) | (c3 << 2) | (c4 << 3));
  789. switch (intersectionCase)
  790. {
  791. case NoIntersection:
  792. // Nothing to do
  793. break;
  794. case AddedFullyContained:
  795. {
  796. // Need to break the current in 2
  797. Unit lowUnit = unit;
  798. Unit topUnit = unit;
  799. lowUnit.j = GetPrevious(a.i);
  800. topUnit.i = GetNext(a.j);
  801. it.InsertBefore(lowUnit);
  802. it.InsertBefore(topUnit);
  803. it.RemoveCurrent();
  804. break;
  805. }
  806. case IntersectionAdded_Unit:
  807. case CommonLowBound_Unit:
  808. // Move the unit lower bound after the added upper bound
  809. unit.i = GetNext(a.j);
  810. break;
  811. case IntersectionUnit_Added:
  812. case CommonTopBound_Unit:
  813. // Move the unit upper bound before the added lower bound
  814. unit.j = GetPrevious(a.i);
  815. break;
  816. case CommonTopBound_Added:
  817. case CommonLowBound_Added:
  818. case UnitFullyContained:
  819. case FullIntersection:
  820. // Remove the unit
  821. it.RemoveCurrent();
  822. break;
  823. default:
  824. Assert(UNREACHED);
  825. break;
  826. }
  827. }
  828. }
  829. }
  830. template <typename TRangeUnitData>
  831. bool
  832. RangeBase<TRangeUnitData>::ContainsAll()
  833. {
  834. return range.Empty();
  835. }
  836. template <typename TRangeUnitData>
  837. void
  838. Js::RangeBase<TRangeUnitData>::Clear()
  839. {
  840. range.Clear();
  841. }
  842. ///----------------------------------------------------------------------------
  843. ///
  844. /// RangeBase::InRange
  845. ///
  846. /// Searches for each element in the list of UnitRanges. If the given integer
  847. /// is between the 2 values, then return true; If no element is present in range
  848. /// then, then we return true
  849. ///
  850. ///----------------------------------------------------------------------------
  851. template <typename TRangeUnitData>
  852. bool RangeBase<TRangeUnitData>::InRange(TRangeUnitData n)
  853. {
  854. if (range.Empty())
  855. {
  856. return true;
  857. }
  858. else
  859. {
  860. return range.MapUntil([n](RangeUnit<TRangeUnitData> const& unit)
  861. {
  862. return RangeUnitContains(unit, n);
  863. });
  864. }
  865. }
  866. } // namespace Js