ConfigFlagsTable.h 32 KB

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