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