FunctionExecutionStateMachine.cpp 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  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 "RuntimeBasePch.h"
  6. #include "FunctionExecutionStateMachine.h"
  7. #include "Warnings.h"
  8. namespace Js
  9. {
  10. FunctionExecutionStateMachine::FunctionExecutionStateMachine() :
  11. owner(nullptr),
  12. executionState(ExecutionState::Interpreter),
  13. interpreterLimit(0),
  14. autoProfilingInterpreter0Limit(0),
  15. profilingInterpreter0Limit(0),
  16. autoProfilingInterpreter1Limit(0),
  17. simpleJitLimit(0),
  18. profilingInterpreter1Limit(0),
  19. interpretedCount(0),
  20. fullJitThreshold(0),
  21. fullJitRequeueThreshold(0),
  22. committedProfiledIterations(0),
  23. lastInterpretedCount(0)
  24. #if DBG
  25. ,initializedExecutionModeAndLimits(false)
  26. ,hasBeenReinitialized(false)
  27. #ifdef ENABLE_SCRIPT_DEBUGGING
  28. ,initDebuggerMode(DebuggerMode::NotDebugging)
  29. ,reinitDebuggerMode(DebuggerMode::NotDebugging)
  30. #endif
  31. #endif
  32. {
  33. }
  34. void FunctionExecutionStateMachine::InitializeExecutionModeAndLimits(FunctionBody* functionBody)
  35. {
  36. #if DBG
  37. #ifdef ENABLE_SCRIPT_DEBUGGING
  38. if (!initializedExecutionModeAndLimits)
  39. {
  40. initDebuggerMode = functionBody->GetDebuggerMode();
  41. }
  42. #endif
  43. initializedExecutionModeAndLimits = true;
  44. #endif
  45. // Assert we're either uninitialized, or being reinitialized on the same FunctionBody
  46. Assert(owner == nullptr || owner == functionBody);
  47. owner = functionBody;
  48. const ConfigFlagsTable &configFlags = Configuration::Global.flags;
  49. interpreterLimit = 0;
  50. autoProfilingInterpreter0Limit = static_cast<uint16>(configFlags.AutoProfilingInterpreter0Limit);
  51. profilingInterpreter0Limit = static_cast<uint16>(configFlags.ProfilingInterpreter0Limit);
  52. autoProfilingInterpreter1Limit = static_cast<uint16>(configFlags.AutoProfilingInterpreter1Limit);
  53. simpleJitLimit = static_cast<uint16>(configFlags.SimpleJitLimit);
  54. profilingInterpreter1Limit = static_cast<uint16>(configFlags.ProfilingInterpreter1Limit);
  55. // Based on which execution modes are disabled, calculate the number of additional iterations that need to be covered by
  56. // the execution mode that will scale with the full JIT threshold
  57. uint16 scale = 0;
  58. const bool doInterpreterProfile = owner->DoInterpreterProfile();
  59. if (!doInterpreterProfile)
  60. {
  61. scale +=
  62. autoProfilingInterpreter0Limit +
  63. profilingInterpreter0Limit +
  64. autoProfilingInterpreter1Limit +
  65. profilingInterpreter1Limit;
  66. autoProfilingInterpreter0Limit = 0;
  67. profilingInterpreter0Limit = 0;
  68. autoProfilingInterpreter1Limit = 0;
  69. profilingInterpreter1Limit = 0;
  70. }
  71. else if (!owner->DoInterpreterAutoProfile())
  72. {
  73. scale += autoProfilingInterpreter0Limit + autoProfilingInterpreter1Limit;
  74. autoProfilingInterpreter0Limit = 0;
  75. autoProfilingInterpreter1Limit = 0;
  76. if (!CONFIG_FLAG(NewSimpleJit))
  77. {
  78. simpleJitLimit += profilingInterpreter0Limit;
  79. profilingInterpreter0Limit = 0;
  80. }
  81. }
  82. if (!owner->DoSimpleJit())
  83. {
  84. if (!CONFIG_FLAG(NewSimpleJit) && doInterpreterProfile)
  85. {
  86. // The old simple JIT is off, but since it does profiling, it will be replaced with the profiling interpreter
  87. profilingInterpreter1Limit += simpleJitLimit;
  88. }
  89. else
  90. {
  91. scale += simpleJitLimit;
  92. }
  93. simpleJitLimit = 0;
  94. }
  95. if (PHASE_OFF(FullJitPhase, owner))
  96. {
  97. scale += profilingInterpreter1Limit;
  98. profilingInterpreter1Limit = 0;
  99. }
  100. uint16 fullJitThresholdConfig =
  101. static_cast<uint16>(
  102. configFlags.AutoProfilingInterpreter0Limit +
  103. configFlags.ProfilingInterpreter0Limit +
  104. configFlags.AutoProfilingInterpreter1Limit +
  105. configFlags.SimpleJitLimit +
  106. configFlags.ProfilingInterpreter1Limit);
  107. if (!configFlags.EnforceExecutionModeLimits)
  108. {
  109. /*
  110. Scale the full JIT threshold based on some heuristics:
  111. - If the % of code in loops is > 50, scale by 1
  112. - Byte-code size of code outside loops
  113. - If the size is < 50, scale by 1.2
  114. - If the size is < 100, scale by 1.4
  115. - If the size is >= 100, scale by 1.6
  116. */
  117. const uint loopPercentage = owner->GetByteCodeInLoopCount() * 100 / max(1u, owner->GetByteCodeCount());
  118. const int byteCodeSizeThresholdForInlineCandidate = CONFIG_FLAG(LoopInlineThreshold);
  119. bool delayFullJITThisFunc =
  120. (CONFIG_FLAG(DelayFullJITSmallFunc) > 0) && (owner->GetByteCodeWithoutLDACount() <= (uint)byteCodeSizeThresholdForInlineCandidate);
  121. if (loopPercentage <= 50 || delayFullJITThisFunc)
  122. {
  123. const uint straightLineSize = owner->GetByteCodeCount() - owner->GetByteCodeInLoopCount();
  124. double fullJitDelayMultiplier;
  125. if (delayFullJITThisFunc)
  126. {
  127. fullJitDelayMultiplier = CONFIG_FLAG(DelayFullJITSmallFunc) / 10.0;
  128. }
  129. else if (straightLineSize < 50)
  130. {
  131. fullJitDelayMultiplier = 1.2;
  132. }
  133. else if (straightLineSize < 100)
  134. {
  135. fullJitDelayMultiplier = 1.4;
  136. }
  137. else
  138. {
  139. fullJitDelayMultiplier = 1.6;
  140. }
  141. const uint16 newFullJitThreshold = static_cast<uint16>(fullJitThresholdConfig * fullJitDelayMultiplier);
  142. scale += newFullJitThreshold - fullJitThresholdConfig;
  143. fullJitThresholdConfig = newFullJitThreshold;
  144. }
  145. }
  146. Assert(fullJitThresholdConfig >= scale);
  147. fullJitThreshold = fullJitThresholdConfig - scale;
  148. SetInterpretedCount(0);
  149. SetDefaultInterpreterExecutionMode();
  150. SetFullJitThreshold(fullJitThresholdConfig);
  151. TryTransitionToNextInterpreterExecutionMode();
  152. }
  153. void FunctionExecutionStateMachine::ReinitializeExecutionModeAndLimits(FunctionBody* functionBody)
  154. {
  155. #if DBG
  156. hasBeenReinitialized = true;
  157. #ifdef ENABLE_SCRIPT_DEBUGGING
  158. reinitDebuggerMode = functionBody->GetDebuggerMode();
  159. #endif
  160. #endif
  161. // TODO: Investigate what it would take to make this invariant hold. Currently fails in AsmJS tests
  162. // Assert(initializedExecutionModeAndLimits);
  163. fullJitRequeueThreshold = 0;
  164. committedProfiledIterations = 0;
  165. InitializeExecutionModeAndLimits(functionBody);
  166. }
  167. bool FunctionExecutionStateMachine::InterpretedSinceCallCountCollection() const
  168. {
  169. return interpretedCount != lastInterpretedCount;
  170. }
  171. void FunctionExecutionStateMachine::CollectInterpretedCounts()
  172. {
  173. lastInterpretedCount = interpretedCount;
  174. }
  175. ExecutionMode FunctionExecutionStateMachine::GetExecutionMode() const
  176. {
  177. ExecutionMode executionMode = StateToMode(executionState);
  178. VerifyExecutionMode(executionMode);
  179. return executionMode;
  180. }
  181. void FunctionExecutionStateMachine::SetExecutionState(ExecutionState state)
  182. {
  183. // TODO: Investigate what it would take to make this invariant hold
  184. // Assert(state == GetDefaultInterpreterExecutionState() || IsTerminalState(state));
  185. VerifyExecutionMode(StateToMode(state));
  186. executionState = state;
  187. }
  188. void FunctionExecutionStateMachine::SetAsmJsExecutionMode()
  189. {
  190. SetExecutionState(ExecutionState::FullJit);
  191. }
  192. void FunctionExecutionStateMachine::SetDefaultInterpreterExecutionMode()
  193. {
  194. SetExecutionState(GetDefaultInterpreterExecutionState());
  195. }
  196. FunctionExecutionStateMachine::ExecutionState FunctionExecutionStateMachine::GetDefaultInterpreterExecutionState() const
  197. {
  198. if (!owner->DoInterpreterProfile())
  199. {
  200. VerifyExecutionMode(ExecutionMode::Interpreter);
  201. return ExecutionState::Interpreter;
  202. }
  203. else if (owner->DoInterpreterAutoProfile())
  204. {
  205. VerifyExecutionMode(ExecutionMode::AutoProfilingInterpreter);
  206. return ExecutionState::AutoProfilingInterpreter0;
  207. }
  208. else
  209. {
  210. VerifyExecutionMode(ExecutionMode::ProfilingInterpreter);
  211. return ExecutionState::ProfilingInterpreter0;
  212. }
  213. }
  214. ExecutionMode FunctionExecutionStateMachine::GetInterpreterExecutionMode(const bool isPostBailout)
  215. {
  216. Assert(initializedExecutionModeAndLimits);
  217. if (isPostBailout && owner->DoInterpreterProfile())
  218. {
  219. return ExecutionMode::ProfilingInterpreter;
  220. }
  221. switch (GetExecutionMode())
  222. {
  223. case ExecutionMode::Interpreter:
  224. case ExecutionMode::AutoProfilingInterpreter:
  225. case ExecutionMode::ProfilingInterpreter:
  226. return GetExecutionMode();
  227. case ExecutionMode::SimpleJit:
  228. if (CONFIG_FLAG(NewSimpleJit))
  229. {
  230. return StateToMode(GetDefaultInterpreterExecutionState());
  231. }
  232. // fall through
  233. case ExecutionMode::FullJit:
  234. {
  235. const ExecutionMode executionMode =
  236. owner->DoInterpreterProfile() ? ExecutionMode::ProfilingInterpreter : ExecutionMode::Interpreter;
  237. VerifyExecutionMode(executionMode);
  238. return executionMode;
  239. }
  240. default:
  241. Assert(false);
  242. __assume(false);
  243. }
  244. }
  245. bool FunctionExecutionStateMachine::IsInterpreterExecutionMode() const
  246. {
  247. return GetExecutionMode() <= ExecutionMode::ProfilingInterpreter;
  248. }
  249. uint16 FunctionExecutionStateMachine::GetSimpleJitExecutedIterations() const
  250. {
  251. Assert(initializedExecutionModeAndLimits);
  252. Assert(GetExecutionMode() == ExecutionMode::SimpleJit);
  253. FunctionEntryPointInfo *const simpleJitEntryPointInfo = owner->GetSimpleJitEntryPointInfo();
  254. if (!simpleJitEntryPointInfo)
  255. {
  256. return 0;
  257. }
  258. // Simple JIT counts down and transitions on overflow
  259. const uint32 callCount = simpleJitEntryPointInfo->callsCount;
  260. Assert(simpleJitLimit == 0 ? callCount == 0 : simpleJitLimit > callCount);
  261. return callCount == 0 ?
  262. static_cast<uint16>(simpleJitLimit) :
  263. static_cast<uint16>(simpleJitLimit) - static_cast<uint16>(callCount) - 1;
  264. }
  265. void FunctionExecutionStateMachine::SetSimpleJitCallCount(const uint16 simpleJitLimit) const
  266. {
  267. Assert(GetExecutionMode() == ExecutionMode::SimpleJit);
  268. Assert(owner->GetDefaultFunctionEntryPointInfo() == owner->GetSimpleJitEntryPointInfo());
  269. // Simple JIT counts down and transitions on overflow
  270. const uint8 limit = static_cast<uint8>(min(0xffui16, simpleJitLimit));
  271. owner->GetSimpleJitEntryPointInfo()->callsCount = limit == 0 ? 0 : limit - 1;
  272. }
  273. void FunctionExecutionStateMachine::SetFullJitRequeueThreshold(const uint16 newFullJitRequeueThreshold)
  274. {
  275. fullJitRequeueThreshold = newFullJitRequeueThreshold;
  276. }
  277. void FunctionExecutionStateMachine::SetFullJitThreshold(const uint16 newFullJitThreshold, const bool skipSimpleJit)
  278. {
  279. Assert(initializedExecutionModeAndLimits);
  280. Assert(GetExecutionMode() != ExecutionMode::FullJit);
  281. int scale = newFullJitThreshold - fullJitThreshold;
  282. if (scale == 0)
  283. {
  284. VerifyExecutionModeLimits();
  285. return;
  286. }
  287. fullJitThreshold = newFullJitThreshold;
  288. const auto ScaleLimit = [&](uint16 &limit) -> bool
  289. {
  290. Assert(scale != 0);
  291. const int limitScale = max(-static_cast<int>(limit), scale);
  292. const int newLimit = limit + limitScale;
  293. Assert(static_cast<int>(static_cast<uint16>(newLimit)) == newLimit);
  294. limit = static_cast<uint16>(newLimit);
  295. scale -= limitScale;
  296. Assert(limit == 0 || scale == 0);
  297. if (&limit == &simpleJitLimit)
  298. {
  299. FunctionEntryPointInfo *const simpleJitEntryPointInfo = owner->GetSimpleJitEntryPointInfo();
  300. if (owner->GetDefaultFunctionEntryPointInfo() == simpleJitEntryPointInfo)
  301. {
  302. Assert(GetExecutionMode() == ExecutionMode::SimpleJit);
  303. const int newSimpleJitCallCount = max(0, (int)simpleJitEntryPointInfo->callsCount + limitScale);
  304. Assert(static_cast<int>(static_cast<uint16>(newSimpleJitCallCount)) == newSimpleJitCallCount);
  305. SetSimpleJitCallCount(static_cast<uint16>(newSimpleJitCallCount));
  306. }
  307. }
  308. return scale == 0;
  309. };
  310. /*
  311. Determine which execution mode's limit scales with the full JIT threshold, in order of preference:
  312. - New simple JIT
  313. - Auto-profiling interpreter 1
  314. - Auto-profiling interpreter 0
  315. - Interpreter
  316. - Profiling interpreter 0 (when using old simple JIT)
  317. - Old simple JIT
  318. - Profiling interpreter 1
  319. - Profiling interpreter 0 (when using new simple JIT)
  320. */
  321. const bool doSimpleJit = owner->DoSimpleJit();
  322. const bool doInterpreterProfile = owner->DoInterpreterProfile();
  323. const bool fullyScaled =
  324. (CONFIG_FLAG(NewSimpleJit) && doSimpleJit && ScaleLimit(simpleJitLimit)) ||
  325. (
  326. doInterpreterProfile
  327. ? owner->DoInterpreterAutoProfile() &&
  328. (ScaleLimit(autoProfilingInterpreter1Limit) || ScaleLimit(autoProfilingInterpreter0Limit))
  329. : ScaleLimit(interpreterLimit)
  330. ) ||
  331. (
  332. CONFIG_FLAG(NewSimpleJit)
  333. ? doInterpreterProfile &&
  334. (ScaleLimit(profilingInterpreter1Limit) || ScaleLimit(profilingInterpreter0Limit))
  335. : (doInterpreterProfile && ScaleLimit(profilingInterpreter0Limit)) ||
  336. (doSimpleJit && ScaleLimit(simpleJitLimit)) ||
  337. (doInterpreterProfile && ScaleLimit(profilingInterpreter1Limit))
  338. );
  339. Assert(fullyScaled);
  340. Assert(scale == 0);
  341. if (GetExecutionMode() != ExecutionMode::SimpleJit)
  342. {
  343. Assert(IsInterpreterExecutionMode());
  344. if (simpleJitLimit != 0 &&
  345. (skipSimpleJit || simpleJitLimit < DEFAULT_CONFIG_MinSimpleJitIterations) &&
  346. !PHASE_FORCE(Phase::SimpleJitPhase, owner))
  347. {
  348. // Simple JIT code has not yet been generated, and was either requested to be skipped, or the limit was scaled
  349. // down too much. Skip simple JIT by moving any remaining iterations to an equivalent interpreter execution
  350. // mode.
  351. (CONFIG_FLAG(NewSimpleJit) ? autoProfilingInterpreter1Limit : profilingInterpreter1Limit) += simpleJitLimit;
  352. simpleJitLimit = 0;
  353. TryTransitionToNextInterpreterExecutionMode();
  354. }
  355. }
  356. VerifyExecutionModeLimits();
  357. }
  358. FunctionExecutionStateMachine::ExecutionState FunctionExecutionStateMachine::ModeToState(ExecutionMode mode) const
  359. {
  360. switch (mode)
  361. {
  362. case ExecutionMode::AutoProfilingInterpreter:
  363. return ExecutionState::AutoProfilingInterpreter0;
  364. case ExecutionMode::ProfilingInterpreter:
  365. return ExecutionState::ProfilingInterpreter0;
  366. case ExecutionMode::SimpleJit:
  367. return ExecutionState::SimpleJit;
  368. case ExecutionMode::FullJit:
  369. return ExecutionState::FullJit;
  370. default:
  371. Assert(!"Unexpected ExecutionMode for ExecutionState");
  372. // fall through
  373. case ExecutionMode::Interpreter:
  374. return ExecutionState::Interpreter;
  375. }
  376. }
  377. ExecutionMode FunctionExecutionStateMachine::StateToMode(ExecutionState state) const
  378. {
  379. switch (state)
  380. {
  381. case ExecutionState::AutoProfilingInterpreter0:
  382. case ExecutionState::AutoProfilingInterpreter1:
  383. return ExecutionMode::AutoProfilingInterpreter;
  384. case ExecutionState::ProfilingInterpreter0:
  385. case ExecutionState::ProfilingInterpreter1:
  386. return ExecutionMode::ProfilingInterpreter;
  387. case ExecutionState::SimpleJit:
  388. return ExecutionMode::SimpleJit;
  389. case ExecutionState::FullJit:
  390. return ExecutionMode::FullJit;
  391. default:
  392. Assert(!"Unexpected ExecutionState for ExecutionMode");
  393. // fall through
  394. case ExecutionState::Interpreter:
  395. return ExecutionMode::Interpreter;
  396. }
  397. }
  398. uint16& FunctionExecutionStateMachine::GetStateLimit(ExecutionState state)
  399. {
  400. switch (state)
  401. {
  402. case ExecutionState::Interpreter:
  403. return interpreterLimit;
  404. case ExecutionState::AutoProfilingInterpreter0:
  405. return autoProfilingInterpreter0Limit;
  406. case ExecutionState::AutoProfilingInterpreter1:
  407. return autoProfilingInterpreter1Limit;
  408. case ExecutionState::ProfilingInterpreter0:
  409. return profilingInterpreter0Limit;
  410. case ExecutionState::ProfilingInterpreter1:
  411. return profilingInterpreter1Limit;
  412. case ExecutionState::SimpleJit:
  413. return simpleJitLimit;
  414. default:
  415. Assert(!"Unexpected ExecutionState for limit");
  416. return interpreterLimit;
  417. }
  418. }
  419. // An execution state is terminal if the current FunctionExecutionStateMachine's limits
  420. // allow the state to continue to run.
  421. // FullJit is always a terminal state and is the last terminal state.
  422. bool FunctionExecutionStateMachine::IsTerminalState(ExecutionState state)
  423. {
  424. return state == ExecutionState::FullJit || GetStateLimit(state) != 0;
  425. }
  426. // Safely moves from one execution mode to another and updates appropriate class members for the next
  427. // mode. Note that there are other functions that modify execution state that do not involve this function.
  428. // This function transitions ExecutionMode as ExecutionState in the following order:
  429. //
  430. // +-- Interpreter
  431. // |
  432. // | AutoProfilingInterpreter --+
  433. // | | ^ |
  434. // | | | v
  435. // | | | SimpleJit
  436. // | v | |
  437. // | ProfilingInterpreter <----+
  438. // | |
  439. // | |
  440. // | v
  441. // +-> FullJit
  442. //
  443. // Transition to the next mode occurs when the limit for the current execution mode reaches 0.
  444. // Returns true when a transition occurs (i.e., the execution state was updated since the beginning of
  445. // this function call). Otherwise, returns false to indicate no change in state.
  446. // See more details of each mode in ExecutionModes.h
  447. bool FunctionExecutionStateMachine::TryTransitionToNextExecutionMode()
  448. {
  449. Assert(initializedExecutionModeAndLimits);
  450. bool isStateChanged = false;
  451. if (executionState != ExecutionState::FullJit)
  452. {
  453. bool isTransitionNeeded;
  454. uint16& stateLimit = GetStateLimit(executionState);
  455. FunctionEntryPointInfo *const simpleJitEntryPointInfo = owner->GetSimpleJitEntryPointInfo();
  456. // Determine if the current state should not transition when
  457. // - for non-JITed states, the interpreted count is less than the limit
  458. // - for JITed states (specifically, SimpleJIT because it can transition), the callsCount
  459. // is non-zero. CallsCount starts at the limit and decrements to 0 to indicate transition.
  460. if ((executionState != ExecutionState::SimpleJit && GetInterpretedCount() < stateLimit)
  461. || (simpleJitEntryPointInfo != nullptr && simpleJitEntryPointInfo->callsCount > 0))
  462. {
  463. // Since the current state is under its limit, no transition is needed.
  464. // Simply verify the current state's execution mode before returning.
  465. isTransitionNeeded = false;
  466. }
  467. else
  468. {
  469. // Since the current state's limit is reached, transition from this state to the next state
  470. // First, save data from the current state
  471. CommitExecutedIterations(stateLimit, stateLimit);
  472. // Then, reset data for the next state
  473. SetInterpretedCount(0);
  474. isTransitionNeeded = true;
  475. }
  476. if (isTransitionNeeded)
  477. {
  478. // Keep advancing the state until a terminal state is found or until there are no more
  479. // states to reach. The path of advancement is described in the banner comment above.
  480. ExecutionState newState = executionState;
  481. while (isTransitionNeeded && !IsTerminalState(newState))
  482. {
  483. if (newState != ExecutionState::Interpreter)
  484. {
  485. // Most states simply advance to the next state
  486. newState = static_cast<ExecutionState>(static_cast<uint8>(newState) + 1);
  487. }
  488. else
  489. {
  490. // Interpreter advances straight to FullJit
  491. newState = ExecutionState::FullJit;
  492. }
  493. // If FullJit is the next state, but FullJit is disabled, then no transition
  494. // is needed.
  495. if (newState == ExecutionState::FullJit && PHASE_OFF(FullJitPhase, owner))
  496. {
  497. isTransitionNeeded = false;
  498. }
  499. else
  500. {
  501. // Otherwise, transition is needed because there is new state available
  502. isTransitionNeeded = true;
  503. }
  504. }
  505. // Only update the execution state when the new state is a terminal state
  506. if (isTransitionNeeded && IsTerminalState(newState))
  507. {
  508. Assert(newState != executionState);
  509. SetExecutionState(newState);
  510. isStateChanged = true;
  511. }
  512. }
  513. }
  514. return isStateChanged;
  515. }
  516. void FunctionExecutionStateMachine::TryTransitionToNextInterpreterExecutionMode()
  517. {
  518. Assert(IsInterpreterExecutionMode());
  519. TryTransitionToNextExecutionMode();
  520. SetExecutionState(ModeToState(GetInterpreterExecutionMode(false)));
  521. }
  522. bool FunctionExecutionStateMachine::TryTransitionToJitExecutionMode()
  523. {
  524. const ExecutionMode previousExecutionMode = GetExecutionMode();
  525. TryTransitionToNextExecutionMode();
  526. switch (GetExecutionMode())
  527. {
  528. case ExecutionMode::SimpleJit:
  529. break;
  530. case ExecutionMode::FullJit:
  531. if (fullJitRequeueThreshold == 0)
  532. {
  533. break;
  534. }
  535. --fullJitRequeueThreshold;
  536. return false;
  537. default:
  538. return false;
  539. }
  540. if (GetExecutionMode() != previousExecutionMode)
  541. {
  542. owner->TraceExecutionMode();
  543. }
  544. return true;
  545. }
  546. void FunctionExecutionStateMachine::TransitionToSimpleJitExecutionMode()
  547. {
  548. CommitExecutedIterations();
  549. interpreterLimit = 0;
  550. autoProfilingInterpreter0Limit = 0;
  551. profilingInterpreter0Limit = 0;
  552. autoProfilingInterpreter1Limit = 0;
  553. fullJitThreshold = simpleJitLimit + profilingInterpreter1Limit;
  554. VerifyExecutionModeLimits();
  555. SetExecutionState(ExecutionState::SimpleJit);
  556. }
  557. void FunctionExecutionStateMachine::TransitionToFullJitExecutionMode()
  558. {
  559. CommitExecutedIterations();
  560. interpreterLimit = 0;
  561. autoProfilingInterpreter0Limit = 0;
  562. profilingInterpreter0Limit = 0;
  563. autoProfilingInterpreter1Limit = 0;
  564. simpleJitLimit = 0;
  565. profilingInterpreter1Limit = 0;
  566. fullJitThreshold = 0;
  567. VerifyExecutionModeLimits();
  568. SetExecutionState(ExecutionState::FullJit);
  569. }
  570. void FunctionExecutionStateMachine::SetIsSpeculativeJitCandidate()
  571. {
  572. // This function is a candidate for speculative JIT. Ensure that it is profiled immediately by transitioning out of the
  573. // auto-profiling interpreter mode.
  574. if (GetExecutionMode() != ExecutionMode::AutoProfilingInterpreter || GetProfiledIterations() != 0)
  575. {
  576. return;
  577. }
  578. owner->TraceExecutionMode("IsSpeculativeJitCandidate (before)");
  579. if (autoProfilingInterpreter0Limit != 0)
  580. {
  581. (profilingInterpreter0Limit == 0 ? profilingInterpreter0Limit : autoProfilingInterpreter1Limit) +=
  582. autoProfilingInterpreter0Limit;
  583. autoProfilingInterpreter0Limit = 0;
  584. }
  585. else if (profilingInterpreter0Limit == 0)
  586. {
  587. profilingInterpreter0Limit += autoProfilingInterpreter1Limit;
  588. autoProfilingInterpreter1Limit = 0;
  589. }
  590. owner->TraceExecutionMode("IsSpeculativeJitCandidate");
  591. TryTransitionToNextInterpreterExecutionMode();
  592. }
  593. void FunctionExecutionStateMachine::ResetSimpleJitLimit()
  594. {
  595. Assert(initializedExecutionModeAndLimits);
  596. SetExecutionState(ExecutionState::SimpleJit);
  597. const uint16 simpleJitNewLimit = static_cast<uint8>(Configuration::Global.flags.SimpleJitLimit);
  598. if (simpleJitLimit < simpleJitNewLimit)
  599. {
  600. fullJitThreshold += simpleJitNewLimit - simpleJitLimit;
  601. simpleJitLimit = simpleJitNewLimit;
  602. }
  603. SetInterpretedCount(0);
  604. }
  605. uint16 FunctionExecutionStateMachine::GetProfiledIterations() const
  606. {
  607. Assert(initializedExecutionModeAndLimits);
  608. uint16 profiledIterations = committedProfiledIterations;
  609. switch (GetExecutionMode())
  610. {
  611. case ExecutionMode::ProfilingInterpreter:
  612. {
  613. uint32 interpretedCount = GetInterpretedCount();
  614. const uint16 clampedInterpretedCount =
  615. interpretedCount <= UINT16_MAX
  616. ? static_cast<uint16>(interpretedCount)
  617. : UINT16_MAX;
  618. const uint16 newProfiledIterations = profiledIterations + clampedInterpretedCount;
  619. profiledIterations = newProfiledIterations >= profiledIterations ? newProfiledIterations : UINT16_MAX;
  620. break;
  621. }
  622. case ExecutionMode::SimpleJit:
  623. if (!CONFIG_FLAG(NewSimpleJit))
  624. {
  625. const uint16 newProfiledIterations = profiledIterations + GetSimpleJitExecutedIterations();
  626. profiledIterations = newProfiledIterations >= profiledIterations ? newProfiledIterations : UINT16_MAX;
  627. }
  628. break;
  629. }
  630. return profiledIterations;
  631. }
  632. void FunctionExecutionStateMachine::CommitExecutedIterations()
  633. {
  634. Assert(initializedExecutionModeAndLimits);
  635. switch (GetExecutionMode())
  636. {
  637. case ExecutionMode::Interpreter:
  638. CommitExecutedIterations(interpreterLimit, GetInterpretedCount());
  639. break;
  640. case ExecutionMode::AutoProfilingInterpreter:
  641. CommitExecutedIterations(
  642. autoProfilingInterpreter0Limit == 0 && profilingInterpreter0Limit == 0
  643. ? autoProfilingInterpreter1Limit
  644. : autoProfilingInterpreter0Limit,
  645. GetInterpretedCount());
  646. break;
  647. case ExecutionMode::ProfilingInterpreter:
  648. CommitExecutedIterations(
  649. owner->GetSimpleJitEntryPointInfo()
  650. ? profilingInterpreter1Limit
  651. : profilingInterpreter0Limit,
  652. GetInterpretedCount());
  653. break;
  654. case ExecutionMode::SimpleJit:
  655. CommitExecutedIterations(simpleJitLimit, GetSimpleJitExecutedIterations());
  656. break;
  657. case ExecutionMode::FullJit:
  658. break;
  659. default:
  660. Assert(false);
  661. __assume(false);
  662. }
  663. }
  664. void FunctionExecutionStateMachine::CommitExecutedIterations(uint16 &limit, const uint executedIterations)
  665. {
  666. Assert(initializedExecutionModeAndLimits);
  667. Assert(
  668. &limit == &interpreterLimit ||
  669. &limit == &autoProfilingInterpreter0Limit ||
  670. &limit == &profilingInterpreter0Limit ||
  671. &limit == &autoProfilingInterpreter1Limit ||
  672. &limit == &simpleJitLimit ||
  673. &limit == &profilingInterpreter1Limit);
  674. const uint16 clampedExecutedIterations = executedIterations >= limit ? limit : static_cast<uint16>(executedIterations);
  675. Assert(fullJitThreshold >= clampedExecutedIterations);
  676. fullJitThreshold -= clampedExecutedIterations;
  677. limit -= clampedExecutedIterations;
  678. VerifyExecutionModeLimits();
  679. if (&limit == &profilingInterpreter0Limit ||
  680. (!CONFIG_FLAG(NewSimpleJit) && &limit == &simpleJitLimit) ||
  681. &limit == &profilingInterpreter1Limit)
  682. {
  683. const uint16 newCommittedProfiledIterations = committedProfiledIterations + clampedExecutedIterations;
  684. committedProfiledIterations =
  685. newCommittedProfiledIterations >= committedProfiledIterations ? newCommittedProfiledIterations : UINT16_MAX;
  686. }
  687. }
  688. void FunctionExecutionStateMachine::VerifyExecutionModeLimits() const
  689. {
  690. Assert(initializedExecutionModeAndLimits);
  691. Assert(
  692. (
  693. interpreterLimit +
  694. autoProfilingInterpreter0Limit +
  695. profilingInterpreter0Limit +
  696. autoProfilingInterpreter1Limit +
  697. simpleJitLimit +
  698. profilingInterpreter1Limit
  699. ) == fullJitThreshold);
  700. }
  701. void FunctionExecutionStateMachine::VerifyExecutionMode(const ExecutionMode executionMode) const
  702. {
  703. #if DBG
  704. Assert(initializedExecutionModeAndLimits);
  705. Assert(executionMode < ExecutionMode::Count);
  706. switch (executionMode)
  707. {
  708. case ExecutionMode::Interpreter:
  709. Assert(!owner->DoInterpreterProfile());
  710. break;
  711. case ExecutionMode::AutoProfilingInterpreter:
  712. Assert(owner->DoInterpreterProfile());
  713. Assert(owner->DoInterpreterAutoProfile());
  714. break;
  715. case ExecutionMode::ProfilingInterpreter:
  716. Assert(owner->DoInterpreterProfile());
  717. break;
  718. case ExecutionMode::SimpleJit:
  719. Assert(owner->DoSimpleJit());
  720. break;
  721. case ExecutionMode::FullJit:
  722. Assert(!PHASE_OFF(FullJitPhase, owner));
  723. break;
  724. default:
  725. Assert(false);
  726. __assume(false);
  727. }
  728. #else
  729. UNREFERENCED_PARAMETER(executionMode);
  730. #endif
  731. }
  732. void FunctionExecutionStateMachine::PrintLimits() const
  733. {
  734. Output::Print(
  735. _u("limits: %hu.%hu.%hu.%hu.%hu = %hu"),
  736. interpreterLimit + autoProfilingInterpreter0Limit,
  737. profilingInterpreter0Limit,
  738. autoProfilingInterpreter1Limit,
  739. simpleJitLimit,
  740. profilingInterpreter1Limit,
  741. fullJitThreshold);
  742. }
  743. void FunctionExecutionStateMachine::AssertIsInitialized() const
  744. {
  745. #if DBG
  746. Assert(initializedExecutionModeAndLimits);
  747. Assert(owner != nullptr);
  748. #endif
  749. }
  750. }