ConfigFlagsTable.h 37 KB

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