ConfigFlagsTable.cpp 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270
  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. #include "CommonCorePch.h"
  6. #include "Memory/PageHeapBlockTypeFilter.h"
  7. #include <initguid.h>
  8. #undef DebugBreak
  9. // Initialization order
  10. // AB AutoSystemInfo
  11. // AD PerfCounter
  12. // AE PerfCounterSet
  13. // AM Output/Configuration
  14. // AN MemProtectHeap
  15. // AP DbgHelpSymbolManager
  16. // AQ CFGLogger
  17. // AR LeakReport
  18. // AS JavascriptDispatch/RecyclerObjectDumper
  19. // AT HeapAllocator/RecyclerHeuristic
  20. // AU RecyclerWriteBarrierManager
  21. #pragma warning(disable:4075) // initializers put in unrecognized initialization area on purpose
  22. #pragma init_seg(".CRT$XCAM")
  23. namespace Js
  24. {
  25. NumberSet::NumberSet() : set(&NoCheckHeapAllocator::Instance) {}
  26. void NumberSet::Add(uint32 x)
  27. {
  28. set.Item(x);
  29. }
  30. bool NumberSet::Contains(uint32 x)
  31. {
  32. return set.Contains(x);
  33. }
  34. NumberPairSet::NumberPairSet() : set(&NoCheckHeapAllocator::Instance) {}
  35. void NumberPairSet::Add(uint32 x, uint32 y)
  36. {
  37. set.Item(NumberPair(x, y));
  38. }
  39. bool NumberPairSet::Contains(uint32 x, uint32 y)
  40. {
  41. return set.Contains(NumberPair(x, y));
  42. }
  43. NumberTrioSet::NumberTrioSet() : set(&NoCheckHeapAllocator::Instance) {}
  44. void NumberTrioSet::Add(uint32 x, uint32 y, uint32 z)
  45. {
  46. set.Item(NumberTrio(x, y, z));
  47. }
  48. bool NumberTrioSet::Contains(uint32 x, uint32 y, uint32 z)
  49. {
  50. return set.Contains(NumberTrio(x, y, z));
  51. }
  52. ///----------------------------------------------------------------------------
  53. ///----------------------------------------------------------------------------
  54. ///
  55. /// class String
  56. ///
  57. ///----------------------------------------------------------------------------
  58. ///----------------------------------------------------------------------------
  59. String::String()
  60. {
  61. this->pszValue = NULL;
  62. }
  63. String::String(__in_z_opt const char16* psz)
  64. {
  65. this->pszValue = NULL;
  66. Set(psz);
  67. }
  68. String::~String()
  69. {
  70. if(NULL != this->pszValue)
  71. {
  72. NoCheckHeapDeleteArray(wcslen(this->pszValue) + 1, this->pszValue);
  73. }
  74. }
  75. ///----------------------------------------------------------------------------
  76. ///
  77. /// String::Set
  78. ///
  79. /// Frees the existing string if any
  80. /// allocates a new buffer to copy the new string
  81. ///
  82. ///----------------------------------------------------------------------------
  83. void
  84. String::Set(__in_z_opt const char16* pszValue)
  85. {
  86. if(NULL != this->pszValue)
  87. {
  88. NoCheckHeapDeleteArray(wcslen(this->pszValue) + 1, this->pszValue);
  89. }
  90. if(NULL != pszValue)
  91. {
  92. size_t size = 1 + wcslen(pszValue);
  93. this->pszValue = NoCheckHeapNewArray(char16, size);
  94. wcscpy_s(this->pszValue, size, pszValue);
  95. }
  96. else
  97. {
  98. this->pszValue = NULL;
  99. }
  100. }
  101. template <>
  102. bool RangeUnitContains<SourceFunctionNode>(RangeUnit<SourceFunctionNode> unit, SourceFunctionNode n)
  103. {
  104. Assert(n.functionId != (uint32)-1);
  105. if ((n.sourceContextId >= unit.i.sourceContextId) &&
  106. (n.sourceContextId <= unit.j.sourceContextId)
  107. )
  108. {
  109. if ((n.sourceContextId == unit.j.sourceContextId && -2 == unit.j.functionId) || //#.#-#.* case
  110. (n.sourceContextId == unit.i.sourceContextId && -2 == unit.i.functionId) //#.*-#.# case
  111. )
  112. {
  113. return true;
  114. }
  115. if ((n.sourceContextId == unit.j.sourceContextId && -1 == unit.j.functionId) || //#.#-#.+ case
  116. (n.sourceContextId == unit.i.sourceContextId && -1 == unit.i.functionId) //#.+-#.# case
  117. )
  118. {
  119. return n.functionId != 0;
  120. }
  121. if ((n.sourceContextId == unit.i.sourceContextId && n.functionId < unit.i.functionId) || //excludes all values less than functionId LHS
  122. (n.sourceContextId == unit.j.sourceContextId && n.functionId > unit.j.functionId)) ////excludes all values greater than functionId RHS
  123. {
  124. return false;
  125. }
  126. return true;
  127. }
  128. return false;
  129. }
  130. template <>
  131. Js::RangeUnit<Js::SourceFunctionNode> GetFullRange()
  132. {
  133. RangeUnit<SourceFunctionNode> unit;
  134. unit.i.sourceContextId = 0;
  135. unit.j.sourceContextId = UINT_MAX;
  136. unit.i.functionId = 0;
  137. unit.j.functionId = (uint)-3;
  138. return unit;
  139. }
  140. template <>
  141. SourceFunctionNode GetPrevious(SourceFunctionNode unit)
  142. {
  143. SourceFunctionNode prevUnit = unit;
  144. prevUnit.functionId--;
  145. if (prevUnit.functionId == UINT_MAX)
  146. {
  147. prevUnit.sourceContextId--;
  148. }
  149. return prevUnit;
  150. }
  151. template <>
  152. SourceFunctionNode GetNext(SourceFunctionNode unit)
  153. {
  154. SourceFunctionNode nextUnit = unit;
  155. nextUnit.functionId++;
  156. if (nextUnit.functionId == 0)
  157. {
  158. nextUnit.sourceContextId++;
  159. }
  160. return nextUnit;
  161. }
  162. ///----------------------------------------------------------------------------
  163. ///----------------------------------------------------------------------------
  164. ///
  165. /// class Phases
  166. ///
  167. ///----------------------------------------------------------------------------
  168. ///----------------------------------------------------------------------------
  169. bool
  170. Phases::IsEnabled(Phase phase)
  171. {
  172. return this->phaseList[(int)phase].valid;
  173. }
  174. bool
  175. Phases::IsEnabled(Phase phase, uint sourceContextId, Js::LocalFunctionId functionId)
  176. {
  177. return this->phaseList[(int)phase].valid &&
  178. this->phaseList[(int)phase].range.InRange(SourceFunctionNode(sourceContextId, functionId));
  179. }
  180. bool
  181. Phases::IsEnabledForAll(Phase phase)
  182. {
  183. return this->phaseList[(int)phase].valid &&
  184. this->phaseList[(int)phase].range.ContainsAll();
  185. }
  186. Range *
  187. Phases::GetRange(Phase phase)
  188. {
  189. return &this->phaseList[(int)phase].range;
  190. }
  191. void
  192. Phases::Enable(Phase phase)
  193. {
  194. this->phaseList[(int)phase].valid = true;
  195. }
  196. void
  197. Phases::Disable(Phase phase)
  198. {
  199. this->phaseList[(int)phase].valid = false;
  200. this->phaseList[(int)phase].range.Clear();
  201. }
  202. Phase
  203. Phases::GetFirstPhase()
  204. {
  205. int i= -1;
  206. while(!this->phaseList[++i].valid)
  207. {
  208. if(i >= PhaseCount - 1)
  209. {
  210. return InvalidPhase;
  211. }
  212. }
  213. return Phase(i);
  214. }
  215. //
  216. // List of names of all the flags
  217. //
  218. const char16* const FlagNames[FlagCount + 1] =
  219. {
  220. #define FLAG(type, name, ...) _u(#name),
  221. #include "ConfigFlagsList.h"
  222. NULL
  223. #undef FLAG
  224. };
  225. //
  226. // List of names of all the Phases
  227. //
  228. const char16* const PhaseNames[PhaseCount + 1] =
  229. {
  230. #define PHASE(name) _u(#name),
  231. #include "ConfigFlagsList.h"
  232. NULL
  233. #undef PHASE
  234. };
  235. //
  236. // Description of flags
  237. //
  238. const char16* const FlagDescriptions[FlagCount + 1] =
  239. {
  240. #define FLAG(type, name, description, ...) _u(description),
  241. #include "ConfigFlagsList.h"
  242. NULL
  243. #undef FLAG
  244. };
  245. //
  246. // Parent flag categorization of flags
  247. //
  248. const Flag FlagParents[FlagCount + 1] =
  249. {
  250. #define FLAG(type, name, description, defaultValue, parentName, ...) parentName##Flag,
  251. #include "ConfigFlagsList.h"
  252. InvalidFlag
  253. #undef FLAG
  254. };
  255. ///
  256. ///----------------------------------------------------------------------------
  257. ///----------------------------------------------------------------------------
  258. ///
  259. /// class ConfigFlagsTable
  260. ///
  261. ///----------------------------------------------------------------------------
  262. ///----------------------------------------------------------------------------
  263. ///----------------------------------------------------------------------------
  264. ///
  265. /// ConfigFlagsTable::ConfigFlagsTable
  266. ///
  267. /// Constructor initializes all the flags with their default values. The nDummy
  268. /// variable is used to prevent the compiler error due to the trailing comma
  269. /// when we generate the list of flags.
  270. ///
  271. ///----------------------------------------------------------------------------
  272. #define FLAG(type, name, description, defaultValue, ...) \
  273. \
  274. name ## ( ## defaultValue ##), \
  275. ConfigFlagsTable::ConfigFlagsTable():
  276. #include "ConfigFlagsList.h"
  277. #undef FLAG
  278. nDummy(0)
  279. {
  280. for(int i=0; i < FlagCount; flagPresent[i++] = false);
  281. // set mark for parent flags
  282. ZeroMemory(this->flagIsParent, sizeof(this->flagIsParent));
  283. #define FLAG(type, name, description, defaultValue, parentName, ...) \
  284. if ((int)parentName##Flag < FlagCount) this->flagIsParent[(int) parentName##Flag] = true;
  285. #include "ConfigFlagsList.h"
  286. #undef FLAG
  287. // set all parent flags to their default (setting all child flags to their right values)
  288. this->SetAllParentFlagsAsDefaultValue();
  289. #if defined(ENABLE_DEBUG_CONFIG_OPTIONS) && CONFIG_PARSE_CONFIG_FILE
  290. rawInputFromConfigFileIndex = 0;
  291. memset(rawInputFromConfigFile, 0, sizeof(rawInputFromConfigFile));
  292. #endif
  293. }
  294. ///----------------------------------------------------------------------------
  295. ///
  296. /// ConfigFlagsTable::SetAllParentFlagsAsDefaultValue
  297. ///
  298. /// Iterate through all parent flags and set their default value
  299. ///
  300. /// Note: only Boolean type supported for now
  301. ///----------------------------------------------------------------------------
  302. String *
  303. ConfigFlagsTable::GetAsString(Flag flag) const
  304. {
  305. return reinterpret_cast<String* >(GetProperty(flag));
  306. }
  307. Phases *
  308. ConfigFlagsTable::GetAsPhase(Flag flag) const
  309. {
  310. return reinterpret_cast<Phases*>(GetProperty(flag));
  311. }
  312. Flag
  313. ConfigFlagsTable::GetOppositePhaseFlag(Flag flag) const
  314. {
  315. #if ENABLE_DEBUG_CONFIG_OPTIONS
  316. switch (flag)
  317. {
  318. case OnFlag: return OffFlag;
  319. case OffFlag: return OnFlag;
  320. }
  321. #endif
  322. return InvalidFlag;
  323. }
  324. Boolean *
  325. ConfigFlagsTable::GetAsBoolean(Flag flag) const
  326. {
  327. return reinterpret_cast<Boolean*>(GetProperty(flag));
  328. }
  329. Number *
  330. ConfigFlagsTable::GetAsNumber(Flag flag) const
  331. {
  332. return reinterpret_cast<Number* >(GetProperty(flag));
  333. }
  334. NumberSet *
  335. ConfigFlagsTable::GetAsNumberSet(Flag flag) const
  336. {
  337. return reinterpret_cast<NumberSet* >(GetProperty(flag));
  338. }
  339. NumberPairSet *
  340. ConfigFlagsTable::GetAsNumberPairSet(Flag flag) const
  341. {
  342. return reinterpret_cast<NumberPairSet* >(GetProperty(flag));
  343. }
  344. NumberTrioSet *
  345. ConfigFlagsTable::GetAsNumberTrioSet(Flag flag) const
  346. {
  347. return reinterpret_cast<NumberTrioSet*>(GetProperty(flag));
  348. }
  349. NumberRange *
  350. ConfigFlagsTable::GetAsNumberRange(Flag flag) const
  351. {
  352. return reinterpret_cast<NumberRange* >(GetProperty(flag));
  353. }
  354. void
  355. ConfigFlagsTable::Enable(Flag flag)
  356. {
  357. this->flagPresent[flag] = true;
  358. }
  359. void
  360. ConfigFlagsTable::Disable(Flag flag)
  361. {
  362. this->flagPresent[flag] = false;
  363. }
  364. bool
  365. ConfigFlagsTable::IsEnabled(Flag flag)
  366. {
  367. return this->flagPresent[flag];
  368. }
  369. bool
  370. ConfigFlagsTable::IsParentFlag(Flag flag) const
  371. {
  372. return this->flagIsParent[flag];
  373. }
  374. void
  375. ConfigFlagsTable::SetAllParentFlagsAsDefaultValue()
  376. {
  377. for (int i = 0; i < FlagCount; i++)
  378. {
  379. Flag currentFlag = (Flag) i;
  380. if (this->IsParentFlag(currentFlag))
  381. {
  382. // only supporting Boolean for now
  383. AssertMsg(this->GetFlagType(currentFlag) == FlagBoolean, "only supporting boolean flags as parent flags");
  384. Boolean defaultParentValue = this->GetDefaultValueAsBoolean(currentFlag);
  385. this->SetAsBoolean(currentFlag, defaultParentValue);
  386. }
  387. }
  388. }
  389. void ConfigFlagsTable::FinalizeConfiguration()
  390. {
  391. TransferAcronymFlagConfiguration();
  392. TranslateFlagConfiguration();
  393. }
  394. void ConfigFlagsTable::TransferAcronymFlagConfiguration()
  395. {
  396. // Transfer acronym flag configuration into the corresponding actual flag
  397. #define FLAG(...)
  398. #define FLAGNRA(Type, Name, Acronym, ...) \
  399. if(!IsEnabled(Name##Flag) && IsEnabled(Acronym##Flag)) \
  400. { \
  401. Enable(Name##Flag); \
  402. Name = Acronym; \
  403. }
  404. #if ENABLE_DEBUG_CONFIG_OPTIONS
  405. #define FLAGPRA(Type, ParentName, Name, Acronym, ...) \
  406. if(!IsEnabled(Name##Flag) && IsEnabled(Acronym##Flag)) \
  407. { \
  408. Enable(Name##Flag); \
  409. Name = Acronym; \
  410. }
  411. #define FLAGRA(Type, Name, Acronym, ...) FLAGNRA(Type, Name, Acronym, __VA_ARGS__)
  412. #endif
  413. #include "ConfigFlagsList.h"
  414. }
  415. void ConfigFlagsTable::TranslateFlagConfiguration()
  416. {
  417. const auto VerifyExecutionModeLimits = [this]()
  418. {
  419. const Number zero = static_cast<Number>(0);
  420. const Number maxUint8 = static_cast<Number>(static_cast<uint8>(-1)); // entry point call count is uint8
  421. const Number maxUint16 = static_cast<Number>(static_cast<uint16>(-1));
  422. #if ENABLE_DEBUG_CONFIG_OPTIONS
  423. Assert(MinInterpretCount >= zero);
  424. Assert(MinInterpretCount <= maxUint16);
  425. Assert(MaxInterpretCount >= zero);
  426. Assert(MaxInterpretCount <= maxUint16);
  427. Assert(MinSimpleJitRunCount >= zero);
  428. Assert(MinSimpleJitRunCount <= maxUint8);
  429. Assert(MaxSimpleJitRunCount >= zero);
  430. Assert(MaxSimpleJitRunCount <= maxUint8);
  431. Assert(SimpleJitAfter >= zero);
  432. Assert(SimpleJitAfter <= maxUint8);
  433. Assert(FullJitAfter >= zero);
  434. Assert(FullJitAfter <= maxUint16);
  435. #endif
  436. Assert(AutoProfilingInterpreter0Limit >= zero);
  437. Assert(AutoProfilingInterpreter0Limit <= maxUint16);
  438. Assert(ProfilingInterpreter0Limit >= zero);
  439. Assert(ProfilingInterpreter0Limit <= maxUint16);
  440. Assert(AutoProfilingInterpreter1Limit >= zero);
  441. Assert(AutoProfilingInterpreter1Limit <= maxUint16);
  442. Assert(SimpleJitLimit >= zero);
  443. Assert(SimpleJitLimit <= maxUint8);
  444. Assert(ProfilingInterpreter1Limit >= zero);
  445. Assert(ProfilingInterpreter1Limit <= maxUint16);
  446. Assert(
  447. (
  448. AutoProfilingInterpreter0Limit +
  449. ProfilingInterpreter0Limit +
  450. AutoProfilingInterpreter1Limit +
  451. SimpleJitLimit +
  452. ProfilingInterpreter1Limit
  453. ) <= maxUint16);
  454. };
  455. VerifyExecutionModeLimits();
  456. #if ENABLE_DEBUG_CONFIG_OPTIONS
  457. #if !DISABLE_JIT
  458. if(ForceDynamicProfile)
  459. {
  460. Force.Enable(DynamicProfilePhase);
  461. }
  462. if(ForceJITLoopBody)
  463. {
  464. Force.Enable(JITLoopBodyPhase);
  465. }
  466. #endif
  467. if(NoDeferParse)
  468. {
  469. Off.Enable(DeferParsePhase);
  470. }
  471. #endif
  472. #if ENABLE_DEBUG_CONFIG_OPTIONS && !DISABLE_JIT
  473. bool dontEnforceLimitsForSimpleJitAfterOrFullJitAfter = false;
  474. if((IsEnabled(MinInterpretCountFlag) || IsEnabled(MaxInterpretCountFlag)) &&
  475. !(IsEnabled(SimpleJitAfterFlag) || IsEnabled(FullJitAfterFlag)))
  476. {
  477. if(Off.IsEnabled(SimpleJitPhase))
  478. {
  479. Enable(FullJitAfterFlag);
  480. if(IsEnabled(MaxInterpretCountFlag))
  481. {
  482. FullJitAfter = MaxInterpretCount;
  483. }
  484. else
  485. {
  486. FullJitAfter = MinInterpretCount;
  487. dontEnforceLimitsForSimpleJitAfterOrFullJitAfter = true;
  488. }
  489. }
  490. else
  491. {
  492. Enable(SimpleJitAfterFlag);
  493. if(IsEnabled(MaxInterpretCountFlag))
  494. {
  495. SimpleJitAfter = MaxInterpretCount;
  496. }
  497. else
  498. {
  499. SimpleJitAfter = MinInterpretCount;
  500. dontEnforceLimitsForSimpleJitAfterOrFullJitAfter = true;
  501. }
  502. if((IsEnabled(MinInterpretCountFlag) && IsEnabled(MinSimpleJitRunCountFlag)) ||
  503. IsEnabled(MaxSimpleJitRunCountFlag))
  504. {
  505. Enable(FullJitAfterFlag);
  506. FullJitAfter = SimpleJitAfter;
  507. if(IsEnabled(MaxSimpleJitRunCountFlag))
  508. {
  509. FullJitAfter += MaxSimpleJitRunCount;
  510. }
  511. else
  512. {
  513. FullJitAfter += MinSimpleJitRunCount;
  514. Assert(dontEnforceLimitsForSimpleJitAfterOrFullJitAfter);
  515. }
  516. }
  517. }
  518. }
  519. // Configure execution mode limits
  520. do
  521. {
  522. if(IsEnabled(AutoProfilingInterpreter0LimitFlag) ||
  523. IsEnabled(ProfilingInterpreter0LimitFlag) ||
  524. IsEnabled(AutoProfilingInterpreter1LimitFlag) ||
  525. IsEnabled(SimpleJitLimitFlag) ||
  526. IsEnabled(ProfilingInterpreter1LimitFlag))
  527. {
  528. break;
  529. }
  530. if(IsEnabled(ExecutionModeLimitsFlag))
  531. {
  532. uint autoProfilingInterpreter0Limit;
  533. uint profilingInterpreter0Limit;
  534. uint autoProfilingInterpreter1Limit;
  535. uint simpleJitLimit;
  536. uint profilingInterpreter1Limit;
  537. const int scannedCount =
  538. swscanf_s(
  539. static_cast<LPCWSTR>(ExecutionModeLimits),
  540. _u("%u.%u.%u.%u.%u"),
  541. &autoProfilingInterpreter0Limit,
  542. &profilingInterpreter0Limit,
  543. &autoProfilingInterpreter1Limit,
  544. &simpleJitLimit,
  545. &profilingInterpreter1Limit);
  546. Assert(scannedCount == 5);
  547. Enable(AutoProfilingInterpreter0LimitFlag);
  548. Enable(ProfilingInterpreter0LimitFlag);
  549. Enable(AutoProfilingInterpreter1LimitFlag);
  550. Enable(SimpleJitLimitFlag);
  551. Enable(ProfilingInterpreter1LimitFlag);
  552. AutoProfilingInterpreter0Limit = autoProfilingInterpreter0Limit;
  553. ProfilingInterpreter0Limit = profilingInterpreter0Limit;
  554. AutoProfilingInterpreter1Limit = autoProfilingInterpreter1Limit;
  555. SimpleJitLimit = simpleJitLimit;
  556. ProfilingInterpreter1Limit = profilingInterpreter1Limit;
  557. break;
  558. }
  559. if(!NewSimpleJit)
  560. {
  561. // Use the defaults for old simple JIT. The flags are not enabled here because the values can be changed later
  562. // based on other flags, only the defaults values are adjusted here.
  563. AutoProfilingInterpreter0Limit = DEFAULT_CONFIG_AutoProfilingInterpreter0Limit;
  564. ProfilingInterpreter0Limit = DEFAULT_CONFIG_ProfilingInterpreter0Limit;
  565. CompileAssert(
  566. DEFAULT_CONFIG_AutoProfilingInterpreter0Limit <= DEFAULT_CONFIG_AutoProfilingInterpreterLimit_OldSimpleJit);
  567. AutoProfilingInterpreter1Limit =
  568. DEFAULT_CONFIG_AutoProfilingInterpreterLimit_OldSimpleJit - DEFAULT_CONFIG_AutoProfilingInterpreter0Limit;
  569. CompileAssert(DEFAULT_CONFIG_ProfilingInterpreter0Limit <= DEFAULT_CONFIG_SimpleJitLimit_OldSimpleJit);
  570. SimpleJitLimit = DEFAULT_CONFIG_SimpleJitLimit_OldSimpleJit - DEFAULT_CONFIG_ProfilingInterpreter0Limit;
  571. ProfilingInterpreter1Limit = 0;
  572. VerifyExecutionModeLimits();
  573. }
  574. if (IsEnabled(SimpleJitAfterFlag))
  575. {
  576. Enable(AutoProfilingInterpreter0LimitFlag);
  577. Enable(ProfilingInterpreter0LimitFlag);
  578. Enable(AutoProfilingInterpreter1LimitFlag);
  579. Enable(EnforceExecutionModeLimitsFlag);
  580. {
  581. Js::Number iterationsNeeded = SimpleJitAfter;
  582. ProfilingInterpreter0Limit = min(ProfilingInterpreter0Limit, iterationsNeeded);
  583. iterationsNeeded -= ProfilingInterpreter0Limit;
  584. AutoProfilingInterpreter0Limit = iterationsNeeded;
  585. AutoProfilingInterpreter1Limit = 0;
  586. }
  587. if(IsEnabled(FullJitAfterFlag))
  588. {
  589. Enable(SimpleJitLimitFlag);
  590. Enable(ProfilingInterpreter1LimitFlag);
  591. Assert(SimpleJitAfter <= FullJitAfter);
  592. Js::Number iterationsNeeded = FullJitAfter - SimpleJitAfter;
  593. Js::Number profilingIterationsNeeded =
  594. min(NewSimpleJit
  595. ? DEFAULT_CONFIG_MinProfileIterations
  596. : DEFAULT_CONFIG_MinProfileIterations_OldSimpleJit,
  597. FullJitAfter) -
  598. ProfilingInterpreter0Limit;
  599. if(NewSimpleJit)
  600. {
  601. ProfilingInterpreter1Limit = min(ProfilingInterpreter1Limit, iterationsNeeded);
  602. iterationsNeeded -= ProfilingInterpreter1Limit;
  603. profilingIterationsNeeded -= ProfilingInterpreter1Limit;
  604. SimpleJitLimit = iterationsNeeded;
  605. }
  606. else
  607. {
  608. SimpleJitLimit = iterationsNeeded;
  609. profilingIterationsNeeded -= min(SimpleJitLimit, profilingIterationsNeeded);
  610. ProfilingInterpreter1Limit = 0;
  611. }
  612. if(profilingIterationsNeeded != 0)
  613. {
  614. Js::Number iterationsToMove = min(AutoProfilingInterpreter1Limit, profilingIterationsNeeded);
  615. AutoProfilingInterpreter1Limit -= iterationsToMove;
  616. ProfilingInterpreter0Limit += iterationsToMove;
  617. profilingIterationsNeeded -= iterationsToMove;
  618. iterationsToMove = min(AutoProfilingInterpreter0Limit, profilingIterationsNeeded);
  619. AutoProfilingInterpreter0Limit -= iterationsToMove;
  620. ProfilingInterpreter0Limit += iterationsToMove;
  621. profilingIterationsNeeded -= iterationsToMove;
  622. Assert(profilingIterationsNeeded == 0);
  623. }
  624. Assert(
  625. (
  626. AutoProfilingInterpreter0Limit +
  627. ProfilingInterpreter0Limit +
  628. AutoProfilingInterpreter1Limit +
  629. SimpleJitLimit +
  630. ProfilingInterpreter1Limit
  631. ) == FullJitAfter);
  632. }
  633. Assert(
  634. (
  635. AutoProfilingInterpreter0Limit +
  636. ProfilingInterpreter0Limit +
  637. AutoProfilingInterpreter1Limit
  638. ) == SimpleJitAfter);
  639. EnforceExecutionModeLimits = true;
  640. break;
  641. }
  642. if(IsEnabled(FullJitAfterFlag))
  643. {
  644. Enable(AutoProfilingInterpreter0LimitFlag);
  645. Enable(ProfilingInterpreter0LimitFlag);
  646. Enable(AutoProfilingInterpreter1LimitFlag);
  647. Enable(SimpleJitLimitFlag);
  648. Enable(ProfilingInterpreter1LimitFlag);
  649. Enable(EnforceExecutionModeLimitsFlag);
  650. Js::Number iterationsNeeded = FullJitAfter;
  651. if(NewSimpleJit)
  652. {
  653. ProfilingInterpreter1Limit = min(ProfilingInterpreter1Limit, iterationsNeeded);
  654. iterationsNeeded -= ProfilingInterpreter1Limit;
  655. }
  656. else
  657. {
  658. ProfilingInterpreter1Limit = 0;
  659. SimpleJitLimit = min(SimpleJitLimit, iterationsNeeded);
  660. iterationsNeeded -= SimpleJitLimit;
  661. }
  662. ProfilingInterpreter0Limit = min(ProfilingInterpreter0Limit, iterationsNeeded);
  663. iterationsNeeded -= ProfilingInterpreter0Limit;
  664. if(NewSimpleJit)
  665. {
  666. SimpleJitLimit = min(SimpleJitLimit, iterationsNeeded);
  667. iterationsNeeded -= SimpleJitLimit;
  668. }
  669. AutoProfilingInterpreter0Limit = min(AutoProfilingInterpreter0Limit, iterationsNeeded);
  670. iterationsNeeded -= AutoProfilingInterpreter0Limit;
  671. AutoProfilingInterpreter1Limit = iterationsNeeded;
  672. Assert(
  673. (
  674. AutoProfilingInterpreter0Limit +
  675. ProfilingInterpreter0Limit +
  676. AutoProfilingInterpreter1Limit +
  677. SimpleJitLimit +
  678. ProfilingInterpreter1Limit
  679. ) == FullJitAfter);
  680. EnforceExecutionModeLimits = true;
  681. break;
  682. }
  683. if (IsEnabled(MaxTemplatizedJitRunCountFlag))
  684. {
  685. if (MaxTemplatizedJitRunCount >= 0)
  686. {
  687. MinTemplatizedJitRunCount = MaxTemplatizedJitRunCount;
  688. }
  689. }
  690. if (IsEnabled(MaxAsmJsInterpreterRunCountFlag))
  691. {
  692. if (MaxAsmJsInterpreterRunCount >= 0)
  693. {
  694. MinAsmJsInterpreterRunCount = MaxAsmJsInterpreterRunCount;
  695. }
  696. }
  697. } while(false);
  698. #endif
  699. if( (
  700. #ifdef ENABLE_PREJIT
  701. Prejit ||
  702. #endif
  703. ForceNative
  704. ) &&
  705. !NoNative)
  706. {
  707. Enable(AutoProfilingInterpreter0LimitFlag);
  708. Enable(ProfilingInterpreter0LimitFlag);
  709. Enable(AutoProfilingInterpreter1LimitFlag);
  710. Enable(EnforceExecutionModeLimitsFlag);
  711. // Override any relevant automatic configuration above
  712. AutoProfilingInterpreter0Limit = 0;
  713. ProfilingInterpreter0Limit = 0;
  714. AutoProfilingInterpreter1Limit = 0;
  715. #if ENABLE_DEBUG_CONFIG_OPTIONS
  716. if(Off.IsEnabled(SimpleJitPhase))
  717. {
  718. Enable(SimpleJitLimitFlag);
  719. Enable(ProfilingInterpreter1LimitFlag);
  720. SimpleJitLimit = 0;
  721. ProfilingInterpreter1Limit = 0;
  722. }
  723. #endif
  724. EnforceExecutionModeLimits = true;
  725. }
  726. VerifyExecutionModeLimits();
  727. }
  728. ///----------------------------------------------------------------------------
  729. ///
  730. /// ConfigFlagsTable::GetFlag
  731. ///
  732. /// Given a string finds the corresponding enum Flag. The comparison is case
  733. /// in-sensitive
  734. ///
  735. ///----------------------------------------------------------------------------
  736. Flag
  737. ConfigFlagsTable::GetFlag(__in LPCWSTR str)
  738. {
  739. for(int i=0; i < FlagCount; i++)
  740. {
  741. if(0 == _wcsicmp(str, FlagNames[i]))
  742. {
  743. return Flag(i);
  744. }
  745. }
  746. return InvalidFlag;
  747. }
  748. ///----------------------------------------------------------------------------
  749. ///
  750. /// ConfigFlagsTable::GetPhase
  751. ///
  752. /// Given a string finds the corresponding enum Phase. The comparison is case
  753. /// in-sensitive
  754. ///
  755. ///----------------------------------------------------------------------------
  756. Phase
  757. ConfigFlagsTable::GetPhase(__in LPCWSTR str)
  758. {
  759. for(int i=0; i < PhaseCount; i++)
  760. {
  761. if(0 == _wcsicmp(str, PhaseNames[i]))
  762. {
  763. return Phase(i);
  764. }
  765. }
  766. return InvalidPhase;
  767. }
  768. void
  769. ConfigFlagsTable::PrintUsageString()
  770. {
  771. Output::Print(_u("List of Phases:\n"));
  772. for(int i = 0; i < PhaseCount; i++)
  773. {
  774. if (i % 4 == 0)
  775. {
  776. Output::Print(_u("\n "));
  777. }
  778. Output::Print(_u("%-40ls "), PhaseNames[i]);
  779. }
  780. Output::Print(_u("\n\nList of flags:\n\n"));
  781. for(int i = 0; i < FlagCount; i++)
  782. {
  783. Output::Print(_u("%60ls "), FlagNames[i]);
  784. switch(GetFlagType(Flag(i)))
  785. {
  786. case InvalidFlagType:
  787. break;
  788. case FlagString:
  789. Output::Print(_u("[:String] "));
  790. break;
  791. case FlagPhases:
  792. Output::Print(_u("[:Phase] "));
  793. break;
  794. case FlagNumber:
  795. Output::Print(_u("[:Number] "));
  796. break;
  797. case FlagBoolean:
  798. Output::Print(_u(" "));
  799. break;
  800. case FlagNumberSet:
  801. Output::Print(_u("[:NumberSet] "));
  802. break;
  803. case FlagNumberPairSet:
  804. Output::Print(_u("[:NumberPairSet] "));
  805. break;
  806. case FlagNumberTrioSet:
  807. Output::Print(_u("[:NumberTrioSet] "));
  808. break;
  809. case FlagNumberRange:
  810. Output::Print(_u("[:NumberRange] "));
  811. break;
  812. default:
  813. Assert(false);
  814. __assume(false);
  815. }
  816. Output::Print(_u("%ls\n"), FlagDescriptions[i]);
  817. }
  818. }
  819. ///----------------------------------------------------------------------------
  820. ///
  821. /// ConfigFlagsTable::GetFlagType
  822. ///
  823. /// Given a flag it returns the type (PhaseFlag, StringFlag ...). This could
  824. /// easily have been a lookup table like FlagNames and PhaseNames but this
  825. /// seems more concise
  826. ///
  827. ///----------------------------------------------------------------------------
  828. FlagTypes
  829. ConfigFlagsTable::GetFlagType(Flag flag)
  830. {
  831. switch(flag)
  832. {
  833. #define FLAG(type, name, ...) \
  834. case name##Flag : \
  835. return Flag##type; \
  836. #include "ConfigFlagsList.h"
  837. default:
  838. return InvalidFlagType;
  839. }
  840. }
  841. ///----------------------------------------------------------------------------
  842. ///
  843. /// ConfigFlagsTable::GetProperty
  844. ///
  845. /// Get the field corresponding to the flag. used as an internal method for
  846. /// the various GetAs* methods.
  847. ///
  848. ///----------------------------------------------------------------------------
  849. void *
  850. ConfigFlagsTable::GetProperty(Flag flag) const
  851. {
  852. switch(flag)
  853. {
  854. #define FLAG(type, name, ...) \
  855. \
  856. case name##Flag : \
  857. return reinterpret_cast<void*>(const_cast<type*>(&##name)); \
  858. #include "ConfigFlagsList.h"
  859. default:
  860. return NULL;
  861. }
  862. }
  863. void
  864. ConfigFlagsTable::VerboseDump()
  865. {
  866. #define FLAG(type, name, ...) \
  867. if (IsEnabled(name##Flag)) \
  868. { \
  869. Output::Print(_u("-%s"), _u(#name)); \
  870. switch (Flag##type) \
  871. { \
  872. case FlagBoolean: \
  873. if (!*GetAsBoolean(name##Flag)) \
  874. { \
  875. Output::Print(_u("-")); \
  876. } \
  877. break; \
  878. case FlagString: \
  879. if (GetAsString(name##Flag) != nullptr) \
  880. { \
  881. Output::Print(_u(":%s"), (LPCWSTR)*GetAsString(name##Flag)); \
  882. } \
  883. break; \
  884. case FlagNumber: \
  885. Output::Print(_u(":%d"), *GetAsNumber(name##Flag)); \
  886. break; \
  887. default: \
  888. break; \
  889. }; \
  890. Output::Print(_u("\n")); \
  891. }
  892. #include "ConfigFlagsList.h"
  893. #undef FLAG
  894. }
  895. ///----------------------------------------------------------------------------
  896. ///
  897. /// ConfigFlagsTable::GetDefaultValueAsBoolean
  898. ///
  899. /// Get the default value of a given boolean flag. If the flag is not of boolean
  900. /// type, will assert on CHK or return FALSE on FRE.
  901. ///
  902. ///----------------------------------------------------------------------------
  903. Boolean
  904. ConfigFlagsTable::GetDefaultValueAsBoolean(Flag flag) const
  905. {
  906. Boolean retValue = FALSE;
  907. switch (flag)
  908. {
  909. #define FLAG(type, name, description, defaultValue, ...) FLAGDEFAULT##type(name, defaultValue)
  910. // define an overload for each FlagTypes - type
  911. // * all defaults we don't care about
  912. #define FLAGDEFAULTPhases(name, defaultValue)
  913. #define FLAGDEFAULTString(name, defaultValue)
  914. #define FLAGDEFAULTNumber(name, defaultValue)
  915. #define FLAGDEFAULTNumberSet(name, defaultValue)
  916. #define FLAGDEFAULTNumberRange(name, defaultValue)
  917. #define FLAGDEFAULTNumberPairSet(name, defaultValue)
  918. #define FLAGDEFAULTNumberTrioSet(name, defaultValue)
  919. // * and those we do care about
  920. #define FLAGDEFAULTBoolean(name, defaultValue) \
  921. case name##Flag: \
  922. retValue = (Boolean) defaultValue; \
  923. break; \
  924. #include "ConfigFlagsList.h"
  925. #undef FLAGDEFAULTBoolean
  926. #undef FLAGDEFAULTNumberRange
  927. #undef FLAGDEFAULTNumberPairSet
  928. #undef FLAGDEFAULTNumberTrioSet
  929. #undef FLAGDEFAULTNumberSet
  930. #undef FLAGDEFAULTNumber
  931. #undef FLAGDEFAULTString
  932. #undef FLAGDEFAULTPhases
  933. #undef FLAG
  934. #undef FLAGREGOVREXPBoolean
  935. #undef FLAGREGOVREXPNumberRange
  936. #undef FLAGREGOVREXPNumberPairSet
  937. #undef FLAGREGOVREXPNumberTrioSet
  938. #undef FLAGREGOVREXPNumberSet
  939. #undef FLAGREGOVREXPNumber
  940. #undef FLAGREGOVREXPString
  941. #undef FLAGREGOVREXPPhases
  942. #undef FLAGREGOVRBoolean
  943. #undef FLAGREGOVRNumberRange
  944. #undef FLAGREGOVRNumberPairSet
  945. #undef FLAGREGOVRNumberTrioSet
  946. #undef FLAGREGOVRNumberSet
  947. #undef FLAGREGOVRNumber
  948. #undef FLAGREGOVRString
  949. #undef FLAGREGOVRPhases
  950. default:
  951. // not found - or not a boolean flag
  952. Assert(false);
  953. }
  954. return retValue;
  955. }
  956. ///----------------------------------------------------------------------------
  957. ///
  958. /// ConfigFlagsTable::SetAsBoolean
  959. ///
  960. /// Set the value of a boolean flag. If the flag is a parent flag, all children flag
  961. // will be set accordingly.
  962. ///
  963. ///----------------------------------------------------------------------------
  964. void
  965. ConfigFlagsTable::SetAsBoolean(Flag flag, Boolean value)
  966. {
  967. AssertMsg(this->GetFlagType(flag) == FlagBoolean, "flag not a boolean type");
  968. Boolean* settingAsBoolean = this->GetAsBoolean(flag);
  969. Assert(settingAsBoolean != nullptr);
  970. Output::VerboseNote(_u("FLAG %s = %d\n"), FlagNames[(int) flag], value);
  971. *settingAsBoolean = value;
  972. // check if parent flag
  973. if (this->IsParentFlag(flag))
  974. {
  975. // parent flag, will iterate through all child flags
  976. Flag childFlag = GetNextChildFlag(flag, /* no currentChildFlag */ InvalidFlag);
  977. while (childFlag != InvalidFlag)
  978. {
  979. Boolean childDefaultValue = GetDefaultValueAsBoolean(childFlag);
  980. // if the parent flag is TRUE, the children flag values are based on their default values
  981. // if the parent flag is FALSE, the children flag values are FALSE (always - as disabled)
  982. Boolean childValue = value == TRUE ? childDefaultValue : FALSE;
  983. Output::VerboseNote(_u("FLAG %s = %d - setting child flag %s = %d\n"), FlagNames[(int) flag], value, FlagNames[(int) childFlag], childValue);
  984. this->SetAsBoolean(childFlag, childValue);
  985. // get next child flag
  986. childFlag = GetNextChildFlag(flag, /* currentChildFlag */ childFlag);
  987. }
  988. }
  989. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  990. // in case the flag is marked as 'callback' - to call the method
  991. #define FLAG(type, name, description, defaultValue, parentName, hasCallback) FLAGCALLBACK##hasCallback(type, name)
  992. #define FLAGCALLBACKFALSE(type, name)
  993. #define FLAGCALLBACKTRUE(type, name) FLAGDOCALLBACK##type(name)
  994. // define an overload for each FlagTypes - type
  995. // * all defaults we don't care about - should assert
  996. #define FLAGDOCALLBACKNumberRange(name) Assert(false);
  997. #define FLAGDOCALLBACKPhases(name) Assert(false);
  998. #define FLAGDOCALLBACKString(name) Assert(false);
  999. #define FLAGDOCALLBACKNumber(name) Assert(false);
  1000. #define FLAGDOCALLBACKNumberSet(name) Assert(false);
  1001. #define FLAGDOCALLBACKNumberPairSet(name) Assert(false);
  1002. #define FLAGDOCALLBACKNumberTrioSet(name) Assert(false);
  1003. // * and those we do care about
  1004. #define FLAGDOCALLBACKBoolean(name) if( flag == name##Flag ) this->FlagSetCallback_##name(value);
  1005. #include "ConfigFlagsList.h"
  1006. #undef FLAGDOCALLBACKBoolean
  1007. #undef FLAGDOCALLBACKNumberRange
  1008. #undef FLAGDOCALLBACKNumberPairSet
  1009. #undef FLAGDOCALLBACKNumberTrioSet
  1010. #undef FLAGDOCALLBACKNumberSet
  1011. #undef FLAGDOCALLBACKNumber
  1012. #undef FLAGDOCALLBACKString
  1013. #undef FLAGDOCALLBACKPhases
  1014. #undef FLAGCALLBACKTRUE
  1015. #undef FLAGCALLBACKFALSE
  1016. #undef FLAG
  1017. #endif
  1018. }
  1019. ///----------------------------------------------------------------------------
  1020. ///
  1021. /// ConfigFlagsTable::GetParentFlag
  1022. ///
  1023. /// Get the parent flag corresponding to the flag, if any, otherwise returns NoParentFlag
  1024. ///
  1025. ///----------------------------------------------------------------------------
  1026. Flag
  1027. ConfigFlagsTable::GetParentFlag(Flag flag) const
  1028. {
  1029. Flag parentFlag = FlagParents[(int)flag];
  1030. return parentFlag;
  1031. }
  1032. ///----------------------------------------------------------------------------
  1033. ///
  1034. /// ConfigFlagsTable::GetNextChildFlag
  1035. ///
  1036. /// Get the next child flag for a given parent flag. If no currentChildFlag, use
  1037. /// InvalidFlag or NoParentFlag as start iterator.
  1038. ///
  1039. ///----------------------------------------------------------------------------
  1040. Flag
  1041. ConfigFlagsTable::GetNextChildFlag(Flag parentFlag, Flag currentChildFlag) const
  1042. {
  1043. // start at the current+1
  1044. int startIndex = (int)currentChildFlag + 1;
  1045. // otherwise start from beginning
  1046. if (currentChildFlag == InvalidFlag || currentChildFlag == NoParentFlag)
  1047. {
  1048. // reset the start index
  1049. startIndex = 0;
  1050. }
  1051. for(int i=startIndex; i < FlagCount; i++)
  1052. {
  1053. Flag currentFlag = (Flag)i;
  1054. Flag parentFlagForCurrentFlag = GetParentFlag(currentFlag);
  1055. if(parentFlagForCurrentFlag == parentFlag)
  1056. {
  1057. // found a match
  1058. return currentFlag;
  1059. }
  1060. }
  1061. // no more
  1062. return InvalidFlag;
  1063. }
  1064. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  1065. //
  1066. // Special overrides for flags being set
  1067. //
  1068. void
  1069. ConfigFlagsTable::FlagSetCallback_ES6All(Boolean value)
  1070. {
  1071. // iterate through all ES6 flags - and set them explicitly (except ES6Verbose)
  1072. Flag parentFlag = ES6Flag;
  1073. // parent ES6 flag, will iterate through all child ES6 flags
  1074. Flag childFlag = GetNextChildFlag(parentFlag, /* no currentChildFlag */ InvalidFlag);
  1075. while (childFlag != InvalidFlag)
  1076. {
  1077. // skip verbose
  1078. if (childFlag != ES6VerboseFlag)
  1079. {
  1080. Boolean childValue = value;
  1081. Output::VerboseNote(_u("FLAG %s = %d - setting child flag %s = %d\n"), FlagNames[(int) parentFlag], value, FlagNames[(int) childFlag], childValue);
  1082. this->SetAsBoolean(childFlag, childValue);
  1083. }
  1084. // get next child flag
  1085. childFlag = GetNextChildFlag(parentFlag, /* currentChildFlag */ childFlag);
  1086. }
  1087. }
  1088. void
  1089. ConfigFlagsTable::FlagSetCallback_ES6Experimental(Boolean value)
  1090. {
  1091. if (value)
  1092. {
  1093. EnableExperimentalFlag();
  1094. }
  1095. }
  1096. #endif
  1097. void
  1098. ConfigFlagsTable::EnableExperimentalFlag()
  1099. {
  1100. AutoCriticalSection autocs(&csExperimentalFlags);
  1101. #define FLAG_EXPERIMENTAL(type, name, ...) this->SetAsBoolean(Js::Flag::name##Flag, true);
  1102. #include "ConfigFlagsList.h"
  1103. }
  1104. //
  1105. // Configuration options
  1106. //
  1107. Configuration::Configuration()
  1108. {
  1109. }
  1110. Configuration Configuration::Global;
  1111. } //namespace Js