ConfigFlagsTable.h 37 KB

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