InliningDecider.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. class InliningDecider
  7. {
  8. private:
  9. Js::FunctionBody *const topFunc;
  10. InliningHeuristics inliningHeuristics;
  11. bool isLoopBody; // We don't support inlining on jit loop bodies as of now.
  12. bool isInDebugMode;
  13. // These variables capture the temporary state
  14. uint32 bytecodeInlinedCount;
  15. uint32 numberOfInlineesWithLoop;
  16. public:
  17. const ExecutionMode jitMode; // Disable certain parts for certain JIT modes
  18. public:
  19. InliningDecider(Js::FunctionBody *const topFunc, bool isLoopBody, bool isInDebugMode, const ExecutionMode jitMode);
  20. ~InliningDecider();
  21. public:
  22. bool InlineIntoTopFunc() const;
  23. bool InlineIntoInliner(Js::FunctionBody *const inliner) const;
  24. Js::FunctionInfo *Inline(Js::FunctionBody *const inliner, Js::FunctionInfo* functionInfo, bool isConstructorCall, bool isPolymorphicCall, uint16 constantArgInfo, Js::ProfileId callSiteId, uint recursiveInlineDepth, bool allowRecursiveInline);
  25. Js::FunctionInfo *InlineCallSite(Js::FunctionBody *const inliner, const Js::ProfileId profiledCallSiteId, uint recursiveInlineDepth = 0);
  26. Js::FunctionInfo *GetCallSiteFuncInfo(Js::FunctionBody *const inliner, const Js::ProfileId profiledCallSiteId, bool* isConstructorCall, bool* isPolymorphicCall);
  27. uint16 GetConstantArgInfo(Js::FunctionBody *const inliner, const Js::ProfileId profiledCallSiteId);
  28. bool HasCallSiteInfo(Js::FunctionBody *const inliner, const Js::ProfileId profiledCallSiteId);
  29. uint InlinePolymorhicCallSite(Js::FunctionBody *const inliner, const Js::ProfileId profiledCallSiteId, Js::FunctionBody** functionBodyArray, uint functionBodyArrayLength, bool* canInlineArray, uint recursiveInlineDepth = 0);
  30. bool GetIsLoopBody() { return isLoopBody;};
  31. void SetAggressiveHeuristics() { inliningHeuristics.threshold.SetAggressiveHeuristics(); }
  32. void ResetInlineHeuristics() { inliningHeuristics.threshold.Reset(); }
  33. void SetLimitOnInlineesWithLoop(uint countOfInlineesWithLoops)
  34. {
  35. // If we have determined in TryAggressiveInlining phase there are too many inlinees with loop, just set the limit such that we don't inline them.
  36. if ((uint)inliningHeuristics.threshold.maxNumberOfInlineesWithLoop <= countOfInlineesWithLoops)
  37. {
  38. inliningHeuristics.threshold.maxNumberOfInlineesWithLoop = 0;
  39. }
  40. return;
  41. }
  42. void ResetState()
  43. {
  44. bytecodeInlinedCount = 0;
  45. numberOfInlineesWithLoop = 0;
  46. }
  47. uint32 getNumberOfInlineesWithLoop() { return numberOfInlineesWithLoop; }
  48. void incrementNumberOfInlineesWithLoop() { numberOfInlineesWithLoop++; }
  49. static bool GetBuiltInInfo(
  50. Js::FunctionInfo *const funcInfo,
  51. Js::OpCode *const inlineCandidateOpCode,
  52. ValueType *const returnType,
  53. Js::ScriptContext *const scriptContext = nullptr);
  54. #if defined(ENABLE_DEBUG_CONFIG_OPTIONS)
  55. static void TraceInlining(Js::FunctionBody *const inliner, const wchar_t* inlineeName, const wchar_t* inlineeFunctionIdandNumberString, uint inlineeByteCodeCount,
  56. Js::FunctionBody* topFunc, uint inlinedByteCodeCount, Js::FunctionBody *const inlinee, uint callSiteId, uint builtIn = -1);
  57. #endif
  58. PREVENT_COPY(InliningDecider)
  59. };
  60. #if ENABLE_DEBUG_CONFIG_OPTIONS
  61. #define INLINE_VERBOSE_TRACE(...) \
  62. if (Js::Configuration::Global.flags.Verbose && Js::Configuration::Global.flags.Trace.IsEnabled(Js::InlinePhase, this->topFunc->GetSourceContextId(), this->topFunc->GetLocalFunctionId())) \
  63. { \
  64. Output::Print(__VA_ARGS__); \
  65. }
  66. #define INLINE_TRACE(...) \
  67. if (Js::Configuration::Global.flags.Trace.IsEnabled(Js::InlinePhase, topFunc->GetSourceContextId(), topFunc->GetLocalFunctionId())) \
  68. { \
  69. Output::Print(__VA_ARGS__); \
  70. }
  71. #define INLINE_TESTTRACE(...) \
  72. if (Js::Configuration::Global.flags.TestTrace.IsEnabled(Js::InlinePhase, topFunc->GetSourceContextId(), topFunc->GetLocalFunctionId())) \
  73. { \
  74. Output::Print(__VA_ARGS__); \
  75. Output::Flush(); \
  76. }
  77. #define INLINE_TESTTRACE_VERBOSE(...) \
  78. if (Js::Configuration::Global.flags.Verbose && Js::Configuration::Global.flags.TestTrace.IsEnabled(Js::InlinePhase, topFunc->GetSourceContextId(), topFunc->GetLocalFunctionId())) \
  79. { \
  80. Output::Print(__VA_ARGS__); \
  81. Output::Flush(); \
  82. }
  83. #define POLYMORPHIC_INLINE_TESTTRACE(...) \
  84. if (Js::Configuration::Global.flags.TestTrace.IsEnabled(Js::PolymorphicInlinePhase)) \
  85. { \
  86. Output::Print(__VA_ARGS__); \
  87. Output::Flush(); \
  88. }
  89. #define POLYMORPHIC_INLINE_FIXEDMETHODS_TESTTRACE(...) \
  90. if (Js::Configuration::Global.flags.TestTrace.IsEnabled(Js::PolymorphicInlineFixedMethodsPhase)) \
  91. { \
  92. Output::Print(__VA_ARGS__); \
  93. Output::Flush(); \
  94. }
  95. #define INLINE_FLUSH() \
  96. if (Js::Configuration::Global.flags.Trace.IsEnabled(Js::InlinePhase,this->topFunc->GetSourceContextId() ,this->topFunc->GetLocalFunctionId()) || Js::Configuration::Global.flags.TestTrace.IsEnabled(Js::InlinePhase)) \
  97. { \
  98. Output::Flush(); \
  99. }
  100. #else
  101. #define INLINE_VERBOSE_TRACE(...)
  102. #define POLYMORPHIC_INLINE_TESTTRACE(...)
  103. #define POLYMORPHIC_INLINE_FIXEDMETHODS_TESTTRACE(...)
  104. #define INLINE_TRACE(...)
  105. #define INLINE_FLUSH()
  106. #define INLINE_TESTTRACE(...)
  107. #define INLINE_TESTTRACE_VERBOSE(...)
  108. #endif