blob: a70b09d73b61a7ccba0c3ab04bb9f96955cdc28d [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#pragma once
namespace Js
{
struct InterpreterHaltState;
class DebugManager
{
friend class RecyclableObjectDisplay;
friend class RecyclableArrayWalker;
template <typename TData> friend class RecyclableCollectionObjectWalker;
template <typename TData> friend class RecyclableCollectionObjectDisplay;
friend class RecyclableKeyValueDisplay;
friend class ProbeContainer;
private:
InterpreterHaltState* pCurrentInterpreterLocation; // NULL if not Halted at a Probe
DWORD_PTR secondaryCurrentSourceContext; // For resolving ambiguity among generated files, e.g. eval, anonymous, etc.
uint32 debugSessionNumber; // A unique number, which will be used to sync all probecontainer when on break
RecyclerRootPtr<Js::DynamicObject> pConsoleScope;
ThreadContext* pThreadContext;
bool isAtDispatchHalt;
PageAllocator diagnosticPageAllocator;
int evalCodeRegistrationCount;
int anonymousCodeRegistrationCount;
int jscriptBlockRegistrationCount;
bool isDebuggerAttaching;
DebuggingFlags debuggingFlags;
UINT nextBreakPointId;
DWORD localsDisplayFlags;
void * dispatchHaltFrameAddress;
public:
StepController stepController;
AsyncBreakController asyncBreakController;
PropertyId mutationNewValuePid; // Holds the property id of $newValue$ property for object mutation breakpoint
PropertyId mutationPropertyNamePid; // Holds the property id of $propertyName$ property for object mutation breakpoint
PropertyId mutationTypePid; // Holds the property id of $mutationType$ property for object mutation breakpoint
DebugManager(ThreadContext* _pThreadContext, AllocationPolicyManager * allocationPolicyManager);
~DebugManager();
void Close();
DebuggingFlags* GetDebuggingFlags();
intptr_t GetDebuggingFlagsAddr() const;
bool IsAtDispatchHalt() const { return this->isAtDispatchHalt; }
void SetDispatchHalt(bool set) { this->isAtDispatchHalt = set; }
ReferencedArenaAdapter* GetDiagnosticArena();
DWORD_PTR AllocateSecondaryHostSourceContext();
void SetCurrentInterpreterLocation(InterpreterHaltState* pHaltState);
void UnsetCurrentInterpreterLocation();
bool IsMatchTopFrameStackAddress(DiagStackFrame* frame) const;
uint32 GetDebugSessionNumber() const { return debugSessionNumber; }
#ifdef ENABLE_MUTATION_BREAKPOINT
MutationBreakpoint* GetActiveMutationBreakpoint() const;
#endif
DynamicObject* GetConsoleScope(ScriptContext* scriptContext);
FrameDisplay *GetFrameDisplay(ScriptContext* scriptContext, DynamicObject* scopeAtZero, DynamicObject* scopeAtOne);
void UpdateConsoleScope(DynamicObject* copyFromScope, ScriptContext* scriptContext);
PageAllocator * GetDiagnosticPageAllocator() { return &this->diagnosticPageAllocator; }
void SetDispatchHaltFrameAddress(void * returnAddress) { this->dispatchHaltFrameAddress = returnAddress; }
DWORD_PTR GetDispatchHaltFrameAddress() const { return (DWORD_PTR)this->dispatchHaltFrameAddress; }
#if DBG
void ValidateDebugAPICall();
#endif
void SetDebuggerAttaching(bool attaching) { this->isDebuggerAttaching = attaching; }
bool IsDebuggerAttaching() const { return this->isDebuggerAttaching; }
enum DynamicFunctionType
{
DFT_EvalCode,
DFT_AnonymousCode,
DFT_JScriptBlock
};
int GetNextId(DynamicFunctionType eFunc)
{
switch (eFunc)
{
case DFT_EvalCode: return ++evalCodeRegistrationCount;
case DFT_AnonymousCode: return ++anonymousCodeRegistrationCount;
case DFT_JScriptBlock: return ++jscriptBlockRegistrationCount;
}
return -1;
}
UINT GetNextBreakpointId()
{
return ++nextBreakPointId;
}
enum LocalsDisplayFlags
{
LocalsDisplayFlags_None = 0x0,
LocalsDisplayFlags_NoGroupMethods = 0x1
};
void SetLocalsDisplayFlags(LocalsDisplayFlags localsDisplayFlags)
{
this->localsDisplayFlags |= localsDisplayFlags;
}
bool IsLocalsDisplayFlagsSet(LocalsDisplayFlags localsDisplayFlags)
{
return (this->localsDisplayFlags & localsDisplayFlags) == (DWORD)localsDisplayFlags;
}
};
}
class AutoSetDispatchHaltFlag
{
public:
AutoSetDispatchHaltFlag(Js::ScriptContext *scriptContext, ThreadContext *threadContext);
~AutoSetDispatchHaltFlag();
private:
// Primary reason for caching both because once we break to debugger our engine is open for re-entrancy. That means the
// connection to scriptcontet to threadcontext can go away (imagine the GC is called when we are broken)
Js::ScriptContext * m_scriptContext;
ThreadContext * m_threadContext;
};