DiagProbe.h 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  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. class MutationBreakpoint;
  9. enum StopType
  10. {
  11. STOP_BREAKPOINT,
  12. STOP_INLINEBREAKPOINT,
  13. STOP_STEPCOMPLETE,
  14. STOP_EXCEPTIONTHROW,
  15. STOP_ASYNCBREAK,
  16. STOP_MUTATIONBREAKPOINT,
  17. STOP_DOMMUTATIONBREAKPOINT
  18. };
  19. struct ReturnedValue
  20. {
  21. ReturnedValue() {}
  22. ReturnedValue(Js::Var _returnedValue, Js::JavascriptFunction * _calledFunction, bool _isValueOfReturnStatement)
  23. : returnedValue(_returnedValue), calledFunction(_calledFunction), isValueOfReturnStatement(_isValueOfReturnStatement)
  24. {
  25. if (isValueOfReturnStatement)
  26. {
  27. Assert(returnedValue == nullptr);
  28. Assert(calledFunction == nullptr);
  29. }
  30. }
  31. Field(Js::Var) returnedValue;
  32. Field(Js::JavascriptFunction *) calledFunction;
  33. Field(bool) isValueOfReturnStatement;
  34. };
  35. typedef JsUtil::List<ReturnedValue*> ReturnedValueList;
  36. class DiagStackFrame;
  37. typedef JsUtil::Stack<DiagStackFrame*> DiagStack;
  38. typedef WeakArenaReference<DiagStack> WeakDiagStack;
  39. struct InterpreterHaltState
  40. {
  41. StopType stopType;
  42. const FunctionBody* executingFunction;
  43. DiagStackFrame* topFrame;
  44. DiagStack* framePointers;
  45. ReferencedArenaAdapter* referencedDiagnosticArena;
  46. JavascriptExceptionObject* exceptionObject;
  47. StringBuilder<ArenaAllocator>* stringBuilder;
  48. MutationBreakpoint* activeMutationBP;
  49. InterpreterHaltState(StopType _stopType, const FunctionBody* _executingFunction, MutationBreakpoint* _activeMutationBP = nullptr);
  50. FunctionBody* GetFunction();
  51. int GetCurrentOffset();
  52. void SetCurrentOffset(int offset);
  53. bool IsValid() const;
  54. };
  55. struct HaltCallback
  56. {
  57. virtual bool CanHalt(InterpreterHaltState* pHaltState) = 0;
  58. virtual void DispatchHalt(InterpreterHaltState* pHaltState) = 0;
  59. virtual void CleanupHalt() = 0;
  60. virtual bool IsInClosedState() { return false; }
  61. // Mentions the policy if the hitting a breakpoint is allowed (based on the fact whether we are at callback from the breakpoint)
  62. virtual bool CanAllowBreakpoints() { return false; }
  63. };
  64. struct Probe : HaltCallback
  65. {
  66. virtual bool Install(Js::ScriptContext* pScriptContext) = 0;
  67. virtual bool Uninstall(Js::ScriptContext* pScriptContext) = 0;
  68. };
  69. enum StepType : BYTE
  70. {
  71. STEP_NONE,
  72. STEP_IN = 0x01,
  73. STEP_OVER = 0x02,
  74. STEP_OUT = 0x04,
  75. STEP_DOCUMENT = 0x08,
  76. // On entry of a jitted function, need to bailout to handle stepping if in STEP_IN mode,
  77. // or STEP_OVER (e.g. STEP_OVER at the end of this function, and it is called again by a
  78. // library caller).
  79. STEP_BAILOUT = STEP_IN | STEP_OVER,
  80. };
  81. struct DebuggerOptionsCallback
  82. {
  83. virtual bool IsExceptionReportingEnabled() { return true; }
  84. virtual bool IsFirstChanceExceptionEnabled() { return false; }
  85. virtual bool IsNonUserCodeSupportEnabled() { return false; }
  86. virtual bool IsLibraryStackFrameSupportEnabled() { return false; }
  87. };
  88. class StepController
  89. {
  90. friend class ProbeManager;
  91. friend class ProbeContainer;
  92. StepType stepType;
  93. int byteOffset;
  94. RecyclerRootPtr<FunctionBody> body;
  95. FunctionBody::StatementMap* statementMap;
  96. int frameCountWhenSet;
  97. int returnedValueRecordingDepth;
  98. DWORD_PTR frameAddrWhenSet;
  99. uint scriptIdWhenSet;
  100. bool stepCompleteOnInlineBreakpoint;
  101. ScriptContext *pActivatedContext;
  102. ReturnedValueList *returnedValueList;
  103. public:
  104. StepController();
  105. ~StepController()
  106. {
  107. this->Deactivate();
  108. }
  109. bool IsActive();
  110. void Activate(StepType stepType, InterpreterHaltState* haltState);
  111. void Deactivate(InterpreterHaltState* haltState = nullptr);
  112. bool IsStepComplete_AllowingFalsePositives(InterpreterStackFrame * stackFrame);
  113. bool IsStepComplete(InterpreterHaltState* haltState, HaltCallback *haltCallback, OpCode originalOpcode);
  114. bool ContinueFromInlineBreakpoint();
  115. ScriptContext* GetActivatedContext() const
  116. {
  117. return this->pActivatedContext;
  118. }
  119. const StepType* GetAddressOfStepType() const
  120. {
  121. return &stepType;
  122. }
  123. void* GetAddressOfScriptIdWhenSet() const
  124. {
  125. return (void*)&scriptIdWhenSet;
  126. }
  127. void* GetAddressOfFrameAddress() const
  128. {
  129. return (void*)&frameAddrWhenSet;
  130. }
  131. void SetFrameAddr(DWORD_PTR value)
  132. {
  133. this->frameAddrWhenSet = value;
  134. }
  135. void AddToReturnedValueContainer(Js::Var returnValue, Js::JavascriptFunction * function, bool isValueOfReturnStatement);
  136. void AddReturnToReturnedValueContainer();
  137. void StartRecordingCall();
  138. void EndRecordingCall(Js::Var returnValue, Js::JavascriptFunction * function);
  139. ReturnedValueList* GetReturnedValueList() const { return this->returnedValueList; }
  140. void ResetReturnedValueList();
  141. void HandleResumeAction(Js::InterpreterHaltState* haltState, BREAKRESUMEACTION resumeAction);
  142. private:
  143. uint GetScriptId(_In_ FunctionBody* body);
  144. };
  145. // This is separate from the step controller because it is the only case where activation
  146. // happens while the script is running.
  147. class AsyncBreakController
  148. {
  149. private:
  150. HaltCallback* haltCallback;
  151. public:
  152. AsyncBreakController();
  153. void Activate(HaltCallback* haltCallback);
  154. void Deactivate();
  155. bool IsBreak();
  156. bool IsAtStoppingLocation(InterpreterHaltState* haltState);
  157. void DispatchAndReset(InterpreterHaltState* haltState);
  158. };
  159. typedef JsUtil::List<Probe*, ArenaAllocator> ProbeList;
  160. }