DebuggingFlags.h 5.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  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. //
  7. // Flags for Fast F12 which are used at run time/by jitted code for conditional bailouts, etc.
  8. //
  9. // Summary on how these are used.
  10. // Place Scenario Flag BailOutKind Comment
  11. // ---------------------------------------------------------------------------------------------------------------------------------------
  12. // Begin Function Async Break DebuggingFlags::m_forceInterpreter BailOutForceByFlag 'Async Break' is when the user hits Pause button.
  13. // Step In stepController::StepType BailOutStep
  14. // F has BP FunctionBody::SourceInfo::m_probeCount BailOutBreakPointInFunction
  15. //
  16. // Return From F Step any/out of F stepController::frameAddrWhenSet > ebp BailOutStackFrameBase
  17. // F has BP FunctionBody::m_hasBreakPoint BailOutBreakPointInFunction When we return to jitted F that has BP,
  18. // we need to bail out.
  19. // Local val changed Inplace stack addr check BailOutLocalValueChanged Check 1 byte on stack specified by
  20. // Func::GetHasLocalVarChangedOffset().
  21. // Return from helper Continue after ex DebuggingFlags::ContinueAfterException BailOutIgnoreException We wrap the call in jitted code with try-catch wrapper.
  22. // or lib Func Continue after ex DebuggingFlags::ContinueAfterException BailOutIgnoreException We wrap the call in jitted code with try-catch wrapper.
  23. // Async Break DebuggingFlags::m_forceInterpreter Async Break is important to Hybrid Debugging.
  24. //
  25. // Loop back edge Async Break DebuggingFlags::m_forceInterpreter BailOutForceByFlag 'Async Break' is when the user hits Pause button.
  26. // F gets new BP FunctionBody::SourceInfo::m_probeCount BailOutBreakPointInFunction For scenario when BP is defined inside loop while loop is running.
  27. //
  28. // 'debugger' stmt 'debugger' stmt None (inplace explicit bailout) BailOutExplicit Insert explicit unconditional b/o.
  29. //
  30. // How it all works:
  31. // - F12 Debugger controls the flags (set/clear)
  32. // - JIT:
  33. // - When inserting a bailout, we use appropriate set of BailoutKind's (see BailoutKind.h).
  34. // - Then when lowering we do multiple condition checks (how many BailoutKind's are in the b/o instr)
  35. // and one bailout if any of conditions triggers.
  36. // - Runtime: bailout happens, we break into debug interpreter thunk and F12 Debugger catches up,
  37. // now we can debug the frame that was originally jitted.
  38. //
  39. class DebuggingFlags
  40. {
  41. private:
  42. bool m_forceInterpreter; // If true/non-zero, break into debug interpreter thunk (we check only in places where this flag is applicable).
  43. bool m_isIgnoringException; // If true/non-zero, we are processing ignore exception scenario. Redundant, as m_byteCodeOffsetAfterIgnoreException
  44. // would be != -1 but for lower it's faster to check both flags at once, that's the reason to have this flag.
  45. int m_byteCodeOffsetAfterIgnoreException;
  46. uint m_funcNumberAfterIgnoreException; // Comes from FunctionBody::GetFunctionNumber(), 0 is default/invalid.
  47. // Whether try-catch wrapper for built-ins for "continue after exception scenarios" is present on current thread (below in call stack).
  48. // If one is registered, we don't wrap with try-catch all subsequent calls.
  49. // All built-ins have entryPoint = ProfileEntryThunk which does the try-catch.
  50. // The idea is that one built-in can call another, etc, but we want to try-catch on 1st built-in called from jitted code,
  51. // otherwise if we don't throw above, some other built-ins in the chain may continue doing something after exception in bad state.
  52. // What we want is that top-most built-in throws, but bottom-most right above jitted code catches the ex.
  53. bool m_isBuiltInWrapperPresent;
  54. public:
  55. static const int InvalidByteCodeOffset = -1;
  56. static const uint InvalidFuncNumber = 0;
  57. DebuggingFlags();
  58. bool GetForceInterpreter() const;
  59. void SetForceInterpreter(bool value);
  60. static size_t GetForceInterpreterOffset();
  61. int GetByteCodeOffsetAfterIgnoreException() const;
  62. uint GetFuncNumberAfterIgnoreException() const;
  63. void SetByteCodeOffsetAfterIgnoreException(int offset);
  64. void SetByteCodeOffsetAndFuncAfterIgnoreException(int offset, uint functionNumber);
  65. void ResetByteCodeOffsetAndFuncAfterIgnoreException();
  66. static size_t GetByteCodeOffsetAfterIgnoreExceptionOffset();
  67. bool IsBuiltInWrapperPresent() const;
  68. void SetIsBuiltInWrapperPresent(bool value = true);
  69. };