ProbeContainer.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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. #ifdef ENABLE_MUTATION_BREAKPOINT
  9. class MutationBreakpoint;
  10. #endif
  11. class DebugManager;
  12. struct Probe;
  13. struct DebuggerPropertyDisplayInfo;
  14. typedef JsUtil::List<Probe*, ArenaAllocator> ProbeList;
  15. class DiagStackFrame;
  16. typedef JsUtil::Stack<DiagStackFrame*> DiagStack;
  17. typedef WeakArenaReference<DiagStack> WeakDiagStack;
  18. struct InterpreterHaltState;
  19. // This class contains the probes and list of function bodies.
  20. // The object of this class is maintained by ScriptContext.
  21. class ProbeContainer
  22. {
  23. friend class RecyclableObjectDisplay;
  24. friend class RecyclableArrayWalker;
  25. private:
  26. ProbeList* diagProbeList;
  27. ProbeList* pendingProbeList;
  28. ScriptContext* pScriptContext;
  29. DebugManager *debugManager;
  30. // Stack for a current scriptcontext
  31. DiagStack* framePointers;
  32. HaltCallback* haltCallbackProbe;
  33. DebuggerOptionsCallback* debuggerOptionsCallback;
  34. // Refer to the callback which is responsible for making async break
  35. HaltCallback* pAsyncHaltCallback;
  36. Var jsExceptionObject;
  37. // Used for synchronizing with ProbeManager
  38. uint32 debugSessionNumber;
  39. uint32 tmpRegCount; // Mentions the temp register count for the current statement (this will be used to determine if SetNextStatement can be applied)
  40. // Used when SetNextStatement is applied.
  41. int bytecodeOffset;
  42. bool IsNextStatementChanged;
  43. // Used when the throw is internal and engine does not want to be broken at exception.
  44. bool isThrowInternal;
  45. // This variable will be set true when we don't want to check for debug script engine being initialized.
  46. bool forceBypassDebugEngine;
  47. bool isPrimaryBrokenToDebuggerContext;
  48. JsUtil::List<DWORD_PTR, ArenaAllocator> *registeredFuncContextList;
  49. JsUtil::List<const Js::PropertyRecord*> *pinnedPropertyRecords;
  50. void UpdateFramePointers(bool fMatchWithCurrentScriptContext, DWORD_PTR dispatchHaltFrameAddress = 0);
  51. bool InitializeLocation(InterpreterHaltState* pHaltState, bool fMatchWithCurrentScriptContext = true);
  52. void DestroyLocation();
  53. bool GetNextUserStatementOffsetHelper(
  54. Js::FunctionBody* functionBody, int currentOffset, FunctionBody::StatementAdjustmentType adjType, int* nextStatementOffset);
  55. #ifdef ENABLE_MUTATION_BREAKPOINT
  56. void InitMutationBreakpointListIfNeeded();
  57. void ClearMutationBreakpoints();
  58. void RemoveMutationBreakpointListIfNeeded();
  59. #endif
  60. static bool FetchTmpRegCount(Js::FunctionBody * functionBody, Js::ByteCodeReader * reader, int atOffset, uint32 *pTmpRegCount, Js::OpCode *pOp);
  61. public:
  62. bool isForcedToEnterScriptStart;
  63. ProbeContainer();
  64. ~ProbeContainer();
  65. void StartRecordingCall();
  66. void EndRecordingCall(Js::Var returnValue, Js::JavascriptFunction * function);
  67. ReturnedValueList* GetReturnedValueList() const;
  68. void ResetReturnedValueList();
  69. void Initialize(ScriptContext* pScriptContext);
  70. void Close();
  71. WeakDiagStack* GetFramePointers(DWORD_PTR dispatchHaltFrameAddress = 0);
  72. // A break engine responsible for breaking at iniline statement and error statement.
  73. void InitializeInlineBreakEngine(HaltCallback* pProbe);
  74. void InitializeDebuggerScriptOptionCallback(DebuggerOptionsCallback* debuggerOptionsCallback);
  75. void UninstallInlineBreakpointProbe(HaltCallback* pProbe);
  76. void UninstallDebuggerScriptOptionCallback();
  77. void AddProbe(Probe* pProbe);
  78. void RemoveProbe(Probe* pProbe);
  79. template<class TMapFunction>
  80. void MapProbes(TMapFunction map)
  81. {
  82. this->diagProbeList->Map(map);
  83. }
  84. template<class TMapFunction>
  85. void MapProbesUntil(TMapFunction map)
  86. {
  87. this->diagProbeList->MapUntil(map);
  88. }
  89. void RemoveAllProbes();
  90. bool CanDispatchHalt(InterpreterHaltState* pHaltState);
  91. // When on breakpoint hit
  92. void DispatchProbeHandlers(InterpreterHaltState* pHaltState);
  93. // When on step in, step out and step over
  94. void DispatchStepHandler(InterpreterHaltState* pHaltState, OpCode* pOriginalOpcode);
  95. // When on break-all
  96. void DispatchAsyncBreak(InterpreterHaltState* pHaltState);
  97. // When executing 'debugger' statement
  98. void DispatchInlineBreakpoint(InterpreterHaltState* pHaltState);
  99. // When encountered and exception
  100. bool DispatchExceptionBreakpoint(InterpreterHaltState* pHaltState);
  101. // When on mutation breakpoint hit
  102. void DispatchMutationBreakpoint(InterpreterHaltState* pHaltState);
  103. void UpdateStep(bool fDuringSetupDebugApp = false);
  104. void DeactivateStep();
  105. bool GetNextUserStatementOffsetForSetNext(Js::FunctionBody* functionBody, int currentOffset, int* nextStatementOffset);
  106. bool GetNextUserStatementOffsetForAdvance(Js::FunctionBody* functionBody, ByteCodeReader* reader, int currentOffset, int* nextStatementOffset);
  107. bool AdvanceToNextUserStatement(Js::FunctionBody* functionBody, ByteCodeReader* reader);
  108. void SetNextStatementAt(int bytecodeOffset);
  109. bool IsSetNextStatementCalled() const { return IsNextStatementChanged; }
  110. int GetByteCodeOffset() const { Assert(IsNextStatementChanged); return bytecodeOffset; }
  111. void AsyncActivate(HaltCallback* haltCallback);
  112. void AsyncDeactivate();
  113. bool IsAsyncActivate() const;
  114. void PrepDiagForEnterScript();
  115. void RegisterContextToDiag(DWORD_PTR context, ArenaAllocator *alloc);
  116. bool IsContextRegistered(DWORD_PTR context);
  117. FunctionBody * GetGlobalFunc(ScriptContext* scriptContext, DWORD_PTR secondaryHostSourceContext);
  118. Var GetExceptionObject() { return jsExceptionObject; }
  119. bool HasAllowedForException(__in JavascriptExceptionObject* exceptionObject);
  120. void SetThrowIsInternal(bool set) { isThrowInternal = set; }
  121. bool IsExceptionReportingEnabled();
  122. bool IsFirstChanceExceptionEnabled();
  123. bool IsNonUserCodeSupportEnabled();
  124. bool IsLibraryStackFrameSupportEnabled();
  125. void SetCurrentTmpRegCount(uint32 set) { tmpRegCount = set; }
  126. uint32 GetCurrentTmpRegCount() const { return tmpRegCount; }
  127. void PinPropertyRecord(const Js::PropertyRecord *propertyRecord);
  128. bool IsPrimaryBrokenToDebuggerContext() const { return isPrimaryBrokenToDebuggerContext; }
  129. void SetIsPrimaryBrokenToDebuggerContext(bool set) { isPrimaryBrokenToDebuggerContext = set; }
  130. DebugManager *GetDebugManager() const { return this->debugManager; }
  131. #ifdef ENABLE_MUTATION_BREAKPOINT
  132. typedef JsUtil::List<RecyclerWeakReference<Js::MutationBreakpoint>*, Recycler, false, Js::WeakRefFreeListedRemovePolicy> MutationBreakpointList;
  133. RecyclerRootPtr<MutationBreakpointList> mutationBreakpointList;
  134. bool HasMutationBreakpoints();
  135. void InsertMutationBreakpoint(MutationBreakpoint *mutationBreakpoint);
  136. #endif
  137. static bool IsTmpRegCountIncreased(Js::FunctionBody* functionBody, ByteCodeReader* reader, int currentOffset, int nextStmOffset, bool restoreOffset);
  138. };
  139. } // namespace Js.