OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/debug/debug.h" | 5 #include "src/debug/debug.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 | 8 |
9 #include "src/api.h" | 9 #include "src/api.h" |
10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
(...skipping 15 matching lines...) Expand all Loading... | |
26 #include "src/messages.h" | 26 #include "src/messages.h" |
27 #include "src/snapshot/natives.h" | 27 #include "src/snapshot/natives.h" |
28 #include "src/wasm/wasm-debug.h" | 28 #include "src/wasm/wasm-debug.h" |
29 #include "src/wasm/wasm-module.h" | 29 #include "src/wasm/wasm-module.h" |
30 | 30 |
31 #include "include/v8-debug.h" | 31 #include "include/v8-debug.h" |
32 | 32 |
33 namespace v8 { | 33 namespace v8 { |
34 namespace internal { | 34 namespace internal { |
35 | 35 |
36 namespace { | |
37 | |
38 inline int CallOffsetFromCodeOffset(int code_offset, bool is_interpreted) { | |
39 // Code offset points to the instruction after the call. Subtract 1 to | |
40 // exclude that instruction from the search. For bytecode, the code offset | |
41 // still points to the call. | |
42 return is_interpreted ? code_offset : code_offset - 1; | |
43 } | |
44 | |
45 } // namespace | |
46 | |
47 Debug::Debug(Isolate* isolate) | 36 Debug::Debug(Isolate* isolate) |
48 : debug_context_(Handle<Context>()), | 37 : debug_context_(Handle<Context>()), |
49 event_listener_(Handle<Object>()), | 38 event_listener_(Handle<Object>()), |
50 event_listener_data_(Handle<Object>()), | 39 event_listener_data_(Handle<Object>()), |
51 message_handler_(NULL), | 40 message_handler_(NULL), |
52 command_received_(0), | 41 command_received_(0), |
53 command_queue_(isolate->logger(), kQueueInitialSize), | 42 command_queue_(isolate->logger(), kQueueInitialSize), |
54 is_active_(false), | 43 is_active_(false), |
55 is_suppressed_(false), | 44 is_suppressed_(false), |
56 live_edit_enabled_(true), // TODO(yangguo): set to false by default. | 45 live_edit_enabled_(true), // TODO(yangguo): set to false by default. |
57 break_disabled_(false), | 46 break_disabled_(false), |
58 break_points_active_(true), | 47 break_points_active_(true), |
59 in_debug_event_listener_(false), | 48 in_debug_event_listener_(false), |
60 break_on_exception_(false), | 49 break_on_exception_(false), |
61 break_on_uncaught_exception_(false), | 50 break_on_uncaught_exception_(false), |
62 debug_info_list_(NULL), | 51 debug_info_list_(NULL), |
63 feature_tracker_(isolate), | 52 feature_tracker_(isolate), |
64 isolate_(isolate) { | 53 isolate_(isolate) { |
65 ThreadInit(); | 54 ThreadInit(); |
66 } | 55 } |
67 | 56 |
68 | 57 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, |
69 static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { | 58 JavaScriptFrame* frame) { |
70 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); | 59 FrameSummary summary = FrameSummary::GetFirst(frame); |
71 // Isolate::context() may have been NULL when "script collected" event | 60 int offset = summary.code_offset(); |
72 // occured. | 61 Handle<AbstractCode> abstract_code = summary.abstract_code(); |
73 if (context.is_null()) return v8::Local<v8::Context>(); | 62 if (abstract_code->IsCode()) offset = offset - 1; |
74 Handle<Context> native_context(context->native_context()); | 63 auto it = BreakIterator::GetIterator(debug_info, abstract_code); |
75 return v8::Utils::ToLocal(native_context); | 64 it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset)); |
65 return it->GetBreakLocation(); | |
76 } | 66 } |
77 | 67 |
78 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, DebugBreakType type, | 68 void BreakLocation::AllAtCurrentStatement(Handle<DebugInfo> debug_info, |
79 int code_offset, int position, | 69 JavaScriptFrame* frame, |
80 int statement_position) | 70 List<BreakLocation>* result_out) { |
81 : debug_info_(debug_info), | 71 FrameSummary summary = FrameSummary::GetFirst(frame); |
82 code_offset_(code_offset), | 72 int offset = summary.code_offset(); |
83 type_(type), | 73 Handle<AbstractCode> abstract_code = summary.abstract_code(); |
84 position_(position), | 74 if (abstract_code->IsCode()) offset = offset - 1; |
85 statement_position_(statement_position) {} | 75 int statement_position; |
86 | 76 { |
87 BreakLocation::Iterator* BreakLocation::GetIterator( | 77 auto it = BreakIterator::GetIterator(debug_info, abstract_code); |
88 Handle<DebugInfo> debug_info, BreakLocatorType type) { | 78 it->SkipTo(BreakIndexFromCodeOffset(debug_info, abstract_code, offset)); |
89 if (debug_info->abstract_code()->IsBytecodeArray()) { | 79 statement_position = it->statement_position(); |
90 return new BytecodeArrayIterator(debug_info, type); | 80 } |
91 } else { | 81 for (auto it = BreakIterator::GetIterator(debug_info, abstract_code); |
92 return new CodeIterator(debug_info, type); | 82 !it->Done(); it->Next()) { |
83 if (it->statement_position() == statement_position) { | |
84 result_out->Add(it->GetBreakLocation()); | |
85 } | |
93 } | 86 } |
94 } | 87 } |
95 | 88 |
96 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info) | 89 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, |
97 : debug_info_(debug_info), break_index_(-1) { | 90 Handle<AbstractCode> abstract_code, |
91 int offset) { | |
92 // Run through all break points to locate the one closest to the address. | |
93 int closest_break = 0; | |
94 int distance = kMaxInt; | |
95 DCHECK(0 <= offset && offset < abstract_code->Size()); | |
96 for (auto it = BreakIterator::GetIterator(debug_info, abstract_code); | |
97 !it->Done(); it->Next()) { | |
98 // Check if this break point is closer that what was previously found. | |
99 if (it->code_offset() <= offset && offset - it->code_offset() < distance) { | |
100 closest_break = it->break_index(); | |
101 distance = offset - it->code_offset(); | |
102 // Check whether we can't get any closer. | |
103 if (distance == 0) break; | |
104 } | |
105 } | |
106 return closest_break; | |
107 } | |
108 | |
109 bool BreakLocation::HasBreakPoint(Handle<DebugInfo> debug_info) const { | |
110 // First check whether there is a break point with the same source position. | |
111 if (!debug_info->HasBreakPoint(position_)) return false; | |
112 // Then check whether a break point at that source position would have | |
113 // the same code offset. Otherwise it's just a break location that we can | |
114 // step to, but not actually a location where we can put a break point. | |
115 if (abstract_code_->IsCode()) { | |
116 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); | |
117 it.SkipToPosition(position_, BREAK_POSITION_ALIGNED); | |
118 return it.code_offset() == code_offset_; | |
119 } else { | |
jgruber
2016/08/11 14:28:13
Is abstract_code_->IsByteCodeArray() at this point
Yang
2016/08/12 05:33:46
Done. Not sure what kind of DCHECKs you had in min
| |
120 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); | |
121 it.SkipToPosition(position_, BREAK_POSITION_ALIGNED); | |
122 return it.code_offset() == code_offset_; | |
123 } | |
124 } | |
125 | |
126 std::unique_ptr<BreakIterator> BreakIterator::GetIterator( | |
127 Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code, | |
128 BreakLocatorType type) { | |
129 if (abstract_code->IsBytecodeArray()) { | |
130 DCHECK(debug_info->HasDebugBytecodeArray()); | |
131 return std::unique_ptr<BreakIterator>( | |
132 new BytecodeArrayBreakIterator(debug_info, type)); | |
133 } else { | |
134 DCHECK(abstract_code->IsCode()); | |
135 DCHECK(debug_info->HasDebugCode()); | |
136 return std::unique_ptr<BreakIterator>( | |
137 new CodeBreakIterator(debug_info, type)); | |
138 } | |
139 } | |
140 | |
141 BreakIterator::BreakIterator(Handle<DebugInfo> debug_info, | |
142 BreakLocatorType type) | |
143 : debug_info_(debug_info), break_index_(-1), break_locator_type_(type) { | |
98 position_ = debug_info->shared()->start_position(); | 144 position_ = debug_info->shared()->start_position(); |
99 statement_position_ = position_; | 145 statement_position_ = position_; |
100 } | 146 } |
101 | 147 |
102 BreakLocation::CodeIterator::CodeIterator(Handle<DebugInfo> debug_info, | 148 int BreakIterator::BreakIndexFromPosition(int source_position, |
103 BreakLocatorType type) | 149 BreakPositionAlignment alignment) { |
104 : Iterator(debug_info), | 150 int distance = kMaxInt; |
105 reloc_iterator_(debug_info->abstract_code()->GetCode(), | 151 int closest_break = break_index(); |
106 GetModeMask(type)), | 152 while (!Done()) { |
153 int next_position; | |
154 if (alignment == STATEMENT_ALIGNED) { | |
155 next_position = statement_position(); | |
156 } else { | |
157 DCHECK(alignment == BREAK_POSITION_ALIGNED); | |
158 next_position = position(); | |
159 } | |
160 if (source_position <= next_position && | |
161 next_position - source_position < distance) { | |
162 closest_break = break_index(); | |
163 distance = next_position - source_position; | |
164 // Check whether we can't get any closer. | |
165 if (distance == 0) break; | |
166 } | |
167 Next(); | |
168 } | |
169 return closest_break; | |
170 } | |
171 | |
172 CodeBreakIterator::CodeBreakIterator(Handle<DebugInfo> debug_info, | |
173 BreakLocatorType type) | |
174 : BreakIterator(debug_info, type), | |
175 reloc_iterator_(debug_info->DebugCode(), GetModeMask(type)), | |
107 source_position_iterator_( | 176 source_position_iterator_( |
108 debug_info->abstract_code()->GetCode()->source_position_table()) { | 177 debug_info->DebugCode()->source_position_table()) { |
109 // There is at least one break location. | 178 // There is at least one break location. |
110 DCHECK(!Done()); | 179 DCHECK(!Done()); |
111 Next(); | 180 Next(); |
112 } | 181 } |
113 | 182 |
114 int BreakLocation::CodeIterator::GetModeMask(BreakLocatorType type) { | 183 int CodeBreakIterator::GetModeMask(BreakLocatorType type) { |
115 int mask = 0; | 184 int mask = 0; |
116 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); | 185 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); |
117 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); | 186 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); |
118 if (isolate()->is_tail_call_elimination_enabled()) { | 187 if (isolate()->is_tail_call_elimination_enabled()) { |
119 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL); | 188 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL); |
120 } | 189 } |
121 if (type == ALL_BREAK_LOCATIONS) { | 190 if (type == ALL_BREAK_LOCATIONS) { |
122 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION); | 191 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION); |
123 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT); | 192 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT); |
124 } | 193 } |
125 return mask; | 194 return mask; |
126 } | 195 } |
127 | 196 |
128 void BreakLocation::CodeIterator::Next() { | 197 void CodeBreakIterator::Next() { |
129 DisallowHeapAllocation no_gc; | 198 DisallowHeapAllocation no_gc; |
130 DCHECK(!Done()); | 199 DCHECK(!Done()); |
131 | 200 |
132 // Iterate through reloc info stopping at each breakable code target. | 201 // Iterate through reloc info stopping at each breakable code target. |
133 bool first = break_index_ == -1; | 202 bool first = break_index_ == -1; |
134 | 203 |
135 if (!first) reloc_iterator_.next(); | 204 if (!first) reloc_iterator_.next(); |
136 first = false; | 205 first = false; |
137 if (Done()) return; | 206 if (Done()) return; |
138 | 207 |
139 int offset = code_offset(); | 208 int offset = code_offset(); |
140 while (!source_position_iterator_.done() && | 209 while (!source_position_iterator_.done() && |
141 source_position_iterator_.code_offset() <= offset) { | 210 source_position_iterator_.code_offset() <= offset) { |
142 position_ = source_position_iterator_.source_position(); | 211 position_ = source_position_iterator_.source_position(); |
143 if (source_position_iterator_.is_statement()) { | 212 if (source_position_iterator_.is_statement()) { |
144 statement_position_ = position_; | 213 statement_position_ = position_; |
145 } | 214 } |
146 source_position_iterator_.Advance(); | 215 source_position_iterator_.Advance(); |
147 } | 216 } |
148 | 217 |
149 DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) || | 218 DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) || |
150 RelocInfo::IsDebuggerStatement(rmode())); | 219 RelocInfo::IsDebuggerStatement(rmode())); |
151 break_index_++; | 220 break_index_++; |
152 } | 221 } |
153 | 222 |
154 BreakLocation BreakLocation::CodeIterator::GetBreakLocation() { | 223 DebugBreakType CodeBreakIterator::GetDebugBreakType() { |
155 DebugBreakType type; | |
156 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) { | 224 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) { |
157 type = DEBUG_BREAK_SLOT_AT_RETURN; | 225 return DEBUG_BREAK_SLOT_AT_RETURN; |
158 } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) { | 226 } else if (RelocInfo::IsDebugBreakSlotAtCall(rmode())) { |
159 type = DEBUG_BREAK_SLOT_AT_CALL; | 227 return DEBUG_BREAK_SLOT_AT_CALL; |
160 } else if (RelocInfo::IsDebugBreakSlotAtTailCall(rmode())) { | 228 } else if (RelocInfo::IsDebugBreakSlotAtTailCall(rmode())) { |
161 type = isolate()->is_tail_call_elimination_enabled() | 229 return isolate()->is_tail_call_elimination_enabled() |
162 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL | 230 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL |
163 : DEBUG_BREAK_SLOT_AT_CALL; | 231 : DEBUG_BREAK_SLOT_AT_CALL; |
164 } else if (RelocInfo::IsDebuggerStatement(rmode())) { | 232 } else if (RelocInfo::IsDebuggerStatement(rmode())) { |
165 type = DEBUGGER_STATEMENT; | 233 return DEBUGGER_STATEMENT; |
166 } else if (RelocInfo::IsDebugBreakSlot(rmode())) { | 234 } else if (RelocInfo::IsDebugBreakSlot(rmode())) { |
167 type = DEBUG_BREAK_SLOT; | 235 return DEBUG_BREAK_SLOT; |
168 } else { | 236 } else { |
169 type = NOT_DEBUG_BREAK; | 237 return NOT_DEBUG_BREAK; |
170 } | 238 } |
171 return BreakLocation(debug_info_, type, code_offset(), position(), | |
172 statement_position()); | |
173 } | 239 } |
174 | 240 |
175 BreakLocation::BytecodeArrayIterator::BytecodeArrayIterator( | 241 void CodeBreakIterator::SkipToPosition(int position, |
242 BreakPositionAlignment alignment) { | |
243 CodeBreakIterator it(debug_info_, break_locator_type_); | |
244 SkipTo(it.BreakIndexFromPosition(position, alignment)); | |
245 } | |
246 | |
247 void CodeBreakIterator::SetDebugBreak() { | |
248 DebugBreakType debug_break_type = GetDebugBreakType(); | |
249 if (debug_break_type == DEBUGGER_STATEMENT) return; | |
250 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); | |
251 Builtins* builtins = isolate()->builtins(); | |
252 Handle<Code> target = debug_break_type == DEBUG_BREAK_SLOT_AT_RETURN | |
253 ? builtins->Return_DebugBreak() | |
254 : builtins->Slot_DebugBreak(); | |
255 DebugCodegen::PatchDebugBreakSlot(isolate(), rinfo()->pc(), target); | |
256 } | |
257 | |
258 void CodeBreakIterator::ClearDebugBreak() { | |
259 DebugBreakType debug_break_type = GetDebugBreakType(); | |
260 if (debug_break_type == DEBUGGER_STATEMENT) return; | |
261 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); | |
262 DebugCodegen::ClearDebugBreakSlot(isolate(), rinfo()->pc()); | |
263 } | |
264 | |
265 bool CodeBreakIterator::IsDebugBreak() { | |
266 DebugBreakType debug_break_type = GetDebugBreakType(); | |
267 if (debug_break_type == DEBUGGER_STATEMENT) return false; | |
268 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); | |
269 return DebugCodegen::DebugBreakSlotIsPatched(rinfo()->pc()); | |
270 } | |
271 | |
272 BreakLocation CodeBreakIterator::GetBreakLocation() { | |
273 Handle<AbstractCode> code(AbstractCode::cast(debug_info_->DebugCode())); | |
274 return BreakLocation(code, GetDebugBreakType(), code_offset(), position_); | |
275 } | |
276 | |
277 BytecodeArrayBreakIterator::BytecodeArrayBreakIterator( | |
176 Handle<DebugInfo> debug_info, BreakLocatorType type) | 278 Handle<DebugInfo> debug_info, BreakLocatorType type) |
177 : Iterator(debug_info), | 279 : BreakIterator(debug_info, type), |
178 source_position_iterator_(debug_info->abstract_code() | 280 source_position_iterator_( |
179 ->GetBytecodeArray() | 281 debug_info->DebugBytecodeArray()->source_position_table()) { |
180 ->source_position_table()), | |
181 break_locator_type_(type) { | |
182 // There is at least one break location. | 282 // There is at least one break location. |
183 DCHECK(!Done()); | 283 DCHECK(!Done()); |
184 Next(); | 284 Next(); |
185 } | 285 } |
186 | 286 |
187 void BreakLocation::BytecodeArrayIterator::Next() { | 287 void BytecodeArrayBreakIterator::Next() { |
188 DisallowHeapAllocation no_gc; | 288 DisallowHeapAllocation no_gc; |
189 DCHECK(!Done()); | 289 DCHECK(!Done()); |
190 bool first = break_index_ == -1; | 290 bool first = break_index_ == -1; |
191 while (!Done()) { | 291 while (!Done()) { |
192 if (!first) source_position_iterator_.Advance(); | 292 if (!first) source_position_iterator_.Advance(); |
193 first = false; | 293 first = false; |
194 if (Done()) return; | 294 if (Done()) return; |
195 position_ = source_position_iterator_.source_position(); | 295 position_ = source_position_iterator_.source_position(); |
196 if (source_position_iterator_.is_statement()) { | 296 if (source_position_iterator_.is_statement()) { |
197 statement_position_ = position_; | 297 statement_position_ = position_; |
198 } | 298 } |
199 DCHECK(position_ >= 0); | 299 DCHECK(position_ >= 0); |
200 DCHECK(statement_position_ >= 0); | 300 DCHECK(statement_position_ >= 0); |
201 | 301 |
202 enum DebugBreakType type = GetDebugBreakType(); | 302 DebugBreakType type = GetDebugBreakType(); |
203 if (type == NOT_DEBUG_BREAK) continue; | 303 if (type == NOT_DEBUG_BREAK) continue; |
204 | 304 |
205 if (break_locator_type_ == ALL_BREAK_LOCATIONS) break; | 305 if (break_locator_type_ == ALL_BREAK_LOCATIONS) break; |
206 | 306 |
207 DCHECK_EQ(CALLS_AND_RETURNS, break_locator_type_); | 307 DCHECK_EQ(CALLS_AND_RETURNS, break_locator_type_); |
208 if (type == DEBUG_BREAK_SLOT_AT_CALL) break; | 308 if (type == DEBUG_BREAK_SLOT_AT_CALL) break; |
209 if (type == DEBUG_BREAK_SLOT_AT_RETURN) break; | 309 if (type == DEBUG_BREAK_SLOT_AT_RETURN) break; |
210 } | 310 } |
211 break_index_++; | 311 break_index_++; |
212 } | 312 } |
213 | 313 |
214 BreakLocation::DebugBreakType | 314 DebugBreakType BytecodeArrayBreakIterator::GetDebugBreakType() { |
215 BreakLocation::BytecodeArrayIterator::GetDebugBreakType() { | 315 BytecodeArray* bytecode_array = debug_info_->OriginalBytecodeArray(); |
216 BytecodeArray* bytecode_array = debug_info_->original_bytecode_array(); | |
217 interpreter::Bytecode bytecode = | 316 interpreter::Bytecode bytecode = |
218 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); | 317 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); |
219 | 318 |
220 if (bytecode == interpreter::Bytecode::kDebugger) { | 319 if (bytecode == interpreter::Bytecode::kDebugger) { |
221 return DEBUGGER_STATEMENT; | 320 return DEBUGGER_STATEMENT; |
222 } else if (bytecode == interpreter::Bytecode::kReturn) { | 321 } else if (bytecode == interpreter::Bytecode::kReturn) { |
223 return DEBUG_BREAK_SLOT_AT_RETURN; | 322 return DEBUG_BREAK_SLOT_AT_RETURN; |
224 } else if (bytecode == interpreter::Bytecode::kTailCall) { | 323 } else if (bytecode == interpreter::Bytecode::kTailCall) { |
225 return isolate()->is_tail_call_elimination_enabled() | 324 return isolate()->is_tail_call_elimination_enabled() |
226 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL | 325 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL |
227 : DEBUG_BREAK_SLOT_AT_CALL; | 326 : DEBUG_BREAK_SLOT_AT_CALL; |
228 } else if (interpreter::Bytecodes::IsCallOrNew(bytecode)) { | 327 } else if (interpreter::Bytecodes::IsCallOrNew(bytecode)) { |
229 return DEBUG_BREAK_SLOT_AT_CALL; | 328 return DEBUG_BREAK_SLOT_AT_CALL; |
230 } else if (source_position_iterator_.is_statement()) { | 329 } else if (source_position_iterator_.is_statement()) { |
231 return DEBUG_BREAK_SLOT; | 330 return DEBUG_BREAK_SLOT; |
232 } else { | 331 } else { |
233 return NOT_DEBUG_BREAK; | 332 return NOT_DEBUG_BREAK; |
234 } | 333 } |
235 } | 334 } |
236 | 335 |
237 BreakLocation BreakLocation::BytecodeArrayIterator::GetBreakLocation() { | 336 void BytecodeArrayBreakIterator::SkipToPosition( |
238 return BreakLocation(debug_info_, GetDebugBreakType(), code_offset(), | 337 int position, BreakPositionAlignment alignment) { |
239 position(), statement_position()); | 338 BytecodeArrayBreakIterator it(debug_info_, break_locator_type_); |
339 SkipTo(it.BreakIndexFromPosition(position, alignment)); | |
240 } | 340 } |
241 | 341 |
242 // Find the break point at the supplied address, or the closest one before | 342 void BytecodeArrayBreakIterator::SetDebugBreak() { |
243 // the address. | 343 DebugBreakType debug_break_type = GetDebugBreakType(); |
244 BreakLocation BreakLocation::FromCodeOffset(Handle<DebugInfo> debug_info, | 344 if (debug_break_type == DEBUGGER_STATEMENT) return; |
245 int offset) { | 345 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); |
246 std::unique_ptr<Iterator> it(GetIterator(debug_info)); | 346 BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray(); |
247 it->SkipTo(BreakIndexFromCodeOffset(debug_info, offset)); | 347 interpreter::Bytecode bytecode = |
248 return it->GetBreakLocation(); | 348 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); |
349 if (interpreter::Bytecodes::IsDebugBreak(bytecode)) return; | |
350 interpreter::Bytecode debugbreak = | |
351 interpreter::Bytecodes::GetDebugBreak(bytecode); | |
352 bytecode_array->set(code_offset(), | |
353 interpreter::Bytecodes::ToByte(debugbreak)); | |
249 } | 354 } |
250 | 355 |
251 BreakLocation BreakLocation::FromFrame(Handle<DebugInfo> debug_info, | 356 void BytecodeArrayBreakIterator::ClearDebugBreak() { |
252 JavaScriptFrame* frame) { | 357 DebugBreakType debug_break_type = GetDebugBreakType(); |
253 int code_offset = FrameSummary::GetFirst(frame).code_offset(); | 358 if (debug_break_type == DEBUGGER_STATEMENT) return; |
254 int call_offset = | 359 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); |
255 CallOffsetFromCodeOffset(code_offset, frame->is_interpreted()); | 360 BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray(); |
256 return FromCodeOffset(debug_info, call_offset); | 361 BytecodeArray* original = debug_info_->OriginalBytecodeArray(); |
362 bytecode_array->set(code_offset(), original->get(code_offset())); | |
257 } | 363 } |
258 | 364 |
259 void BreakLocation::AllForStatementPosition(Handle<DebugInfo> debug_info, | 365 bool BytecodeArrayBreakIterator::IsDebugBreak() { |
260 int statement_position, | 366 DebugBreakType debug_break_type = GetDebugBreakType(); |
261 List<BreakLocation>* result_out) { | 367 if (debug_break_type == DEBUGGER_STATEMENT) return false; |
262 for (std::unique_ptr<Iterator> it(GetIterator(debug_info)); !it->Done(); | 368 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); |
263 it->Next()) { | 369 BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray(); |
264 if (it->statement_position() == statement_position) { | 370 interpreter::Bytecode bytecode = |
265 result_out->Add(it->GetBreakLocation()); | 371 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); |
266 } | 372 return interpreter::Bytecodes::IsDebugBreak(bytecode); |
267 } | |
268 } | 373 } |
269 | 374 |
270 int BreakLocation::BreakIndexFromCodeOffset(Handle<DebugInfo> debug_info, | 375 BreakLocation BytecodeArrayBreakIterator::GetBreakLocation() { |
271 int offset) { | 376 Handle<AbstractCode> code( |
272 // Run through all break points to locate the one closest to the address. | 377 AbstractCode::cast(debug_info_->DebugBytecodeArray())); |
273 int closest_break = 0; | 378 return BreakLocation(code, GetDebugBreakType(), code_offset(), position_); |
274 int distance = kMaxInt; | |
275 DCHECK(0 <= offset && offset < debug_info->abstract_code()->Size()); | |
276 for (std::unique_ptr<Iterator> it(GetIterator(debug_info)); !it->Done(); | |
277 it->Next()) { | |
278 // Check if this break point is closer that what was previously found. | |
279 if (it->code_offset() <= offset && offset - it->code_offset() < distance) { | |
280 closest_break = it->break_index(); | |
281 distance = offset - it->code_offset(); | |
282 // Check whether we can't get any closer. | |
283 if (distance == 0) break; | |
284 } | |
285 } | |
286 return closest_break; | |
287 } | 379 } |
288 | 380 |
289 | 381 |
290 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info, | |
291 int position, | |
292 BreakPositionAlignment alignment) { | |
293 // Run through all break points to locate the one closest to the source | |
294 // position. | |
295 int distance = kMaxInt; | |
296 std::unique_ptr<Iterator> it(GetIterator(debug_info)); | |
297 BreakLocation closest_break = it->GetBreakLocation(); | |
298 while (!it->Done()) { | |
299 int next_position; | |
300 if (alignment == STATEMENT_ALIGNED) { | |
301 next_position = it->statement_position(); | |
302 } else { | |
303 DCHECK(alignment == BREAK_POSITION_ALIGNED); | |
304 next_position = it->position(); | |
305 } | |
306 if (position <= next_position && next_position - position < distance) { | |
307 closest_break = it->GetBreakLocation(); | |
308 distance = next_position - position; | |
309 // Check whether we can't get any closer. | |
310 if (distance == 0) break; | |
311 } | |
312 it->Next(); | |
313 } | |
314 return closest_break; | |
315 } | |
316 | |
317 | |
318 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { | |
319 // If there is not already a real break point here patch code with debug | |
320 // break. | |
321 if (!HasBreakPoint()) SetDebugBreak(); | |
322 DCHECK(IsDebugBreak() || IsDebuggerStatement()); | |
323 // Set the break point information. | |
324 DebugInfo::SetBreakPoint(debug_info_, position_, statement_position_, | |
325 break_point_object); | |
326 } | |
327 | |
328 | |
329 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) { | |
330 // Clear the break point information. | |
331 DebugInfo::ClearBreakPoint(debug_info_, position_, break_point_object); | |
332 // If there are no more break points here remove the debug break. | |
333 if (!HasBreakPoint()) { | |
334 ClearDebugBreak(); | |
335 DCHECK(!IsDebugBreak()); | |
336 } | |
337 } | |
338 | |
339 | |
340 void BreakLocation::SetOneShot() { | |
341 // Debugger statement always calls debugger. No need to modify it. | |
342 if (IsDebuggerStatement()) return; | |
343 | |
344 // Patch code with debug break. | |
345 SetDebugBreak(); | |
346 } | |
347 | |
348 | |
349 void BreakLocation::ClearOneShot() { | |
350 // Debugger statement always calls debugger. No need to modify it. | |
351 if (IsDebuggerStatement()) return; | |
352 | |
353 // If there is a real break point here no more to do. | |
354 if (HasBreakPoint()) { | |
355 DCHECK(IsDebugBreak()); | |
356 return; | |
357 } | |
358 | |
359 // Patch code removing debug break. | |
360 ClearDebugBreak(); | |
361 DCHECK(!IsDebugBreak()); | |
362 } | |
363 | |
364 | |
365 void BreakLocation::SetDebugBreak() { | |
366 // Debugger statement always calls debugger. No need to modify it. | |
367 if (IsDebuggerStatement()) return; | |
368 | |
369 // If there is already a break point here just return. This might happen if | |
370 // the same code is flooded with break points twice. Flooding the same | |
371 // function twice might happen when stepping in a function with an exception | |
372 // handler as the handler and the function is the same. | |
373 if (IsDebugBreak()) return; | |
374 | |
375 DCHECK(IsDebugBreakSlot()); | |
376 if (abstract_code()->IsCode()) { | |
377 Code* code = abstract_code()->GetCode(); | |
378 DCHECK(code->kind() == Code::FUNCTION); | |
379 Builtins* builtins = isolate()->builtins(); | |
380 Handle<Code> target = IsReturn() ? builtins->Return_DebugBreak() | |
381 : builtins->Slot_DebugBreak(); | |
382 Address pc = code->instruction_start() + code_offset(); | |
383 DebugCodegen::PatchDebugBreakSlot(isolate(), pc, target); | |
384 } else { | |
385 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray(); | |
386 interpreter::Bytecode bytecode = | |
387 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); | |
388 interpreter::Bytecode debugbreak = | |
389 interpreter::Bytecodes::GetDebugBreak(bytecode); | |
390 bytecode_array->set(code_offset(), | |
391 interpreter::Bytecodes::ToByte(debugbreak)); | |
392 } | |
393 DCHECK(IsDebugBreak()); | |
394 } | |
395 | |
396 | |
397 void BreakLocation::ClearDebugBreak() { | |
398 // Debugger statement always calls debugger. No need to modify it. | |
399 if (IsDebuggerStatement()) return; | |
400 | |
401 DCHECK(IsDebugBreakSlot()); | |
402 if (abstract_code()->IsCode()) { | |
403 Code* code = abstract_code()->GetCode(); | |
404 DCHECK(code->kind() == Code::FUNCTION); | |
405 Address pc = code->instruction_start() + code_offset(); | |
406 DebugCodegen::ClearDebugBreakSlot(isolate(), pc); | |
407 } else { | |
408 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray(); | |
409 BytecodeArray* original = debug_info_->original_bytecode_array(); | |
410 bytecode_array->set(code_offset(), original->get(code_offset())); | |
411 } | |
412 DCHECK(!IsDebugBreak()); | |
413 } | |
414 | |
415 | |
416 bool BreakLocation::IsDebugBreak() const { | |
417 if (IsDebuggerStatement()) return false; | |
418 DCHECK(IsDebugBreakSlot()); | |
419 if (abstract_code()->IsCode()) { | |
420 Code* code = abstract_code()->GetCode(); | |
421 DCHECK(code->kind() == Code::FUNCTION); | |
422 Address pc = code->instruction_start() + code_offset(); | |
423 return DebugCodegen::DebugBreakSlotIsPatched(pc); | |
424 } else { | |
425 BytecodeArray* bytecode_array = abstract_code()->GetBytecodeArray(); | |
426 interpreter::Bytecode bytecode = | |
427 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); | |
428 return interpreter::Bytecodes::IsDebugBreak(bytecode); | |
429 } | |
430 } | |
431 | |
432 Handle<Object> BreakLocation::BreakPointObjects() const { | |
433 return debug_info_->GetBreakPointObjects(position_); | |
434 } | |
435 | |
436 bool BreakLocation::HasBreakPoint() const { | |
437 // First check whether there is a break point with the same source position. | |
438 if (!debug_info_->HasBreakPoint(position_)) return false; | |
439 // Then check whether a break point at that source position would have | |
440 // the same code offset. Otherwise it's just a break location that we can | |
441 // step to, but not actually a location where we can put a break point. | |
442 BreakLocation break_point_location = BreakLocation::FromPosition( | |
443 debug_info_, position_, BREAK_POSITION_ALIGNED); | |
444 return break_point_location.code_offset() == code_offset_; | |
445 } | |
446 | |
447 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { | 382 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { |
448 uint32_t mask = 1 << feature; | 383 uint32_t mask = 1 << feature; |
449 // Only count one sample per feature and isolate. | 384 // Only count one sample per feature and isolate. |
450 if (bitfield_ & mask) return; | 385 if (bitfield_ & mask) return; |
451 isolate_->counters()->debug_feature_usage()->AddSample(feature); | 386 isolate_->counters()->debug_feature_usage()->AddSample(feature); |
452 bitfield_ |= mask; | 387 bitfield_ |= mask; |
453 } | 388 } |
454 | 389 |
455 | 390 |
456 // Threading support. | 391 // Threading support. |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
575 if (!EnsureDebugInfo(shared, function)) { | 510 if (!EnsureDebugInfo(shared, function)) { |
576 // Return if we failed to retrieve the debug info. | 511 // Return if we failed to retrieve the debug info. |
577 return; | 512 return; |
578 } | 513 } |
579 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_); | 514 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_); |
580 | 515 |
581 // Find the break location where execution has stopped. | 516 // Find the break location where execution has stopped. |
582 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); | 517 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
583 | 518 |
584 // Find actual break points, if any, and trigger debug break event. | 519 // Find actual break points, if any, and trigger debug break event. |
585 Handle<Object> break_points_hit = CheckBreakPoints(&location); | 520 Handle<Object> break_points_hit = CheckBreakPoints(debug_info, &location); |
586 if (!break_points_hit->IsUndefined(isolate_)) { | 521 if (!break_points_hit->IsUndefined(isolate_)) { |
587 // Clear all current stepping setup. | 522 // Clear all current stepping setup. |
588 ClearStepping(); | 523 ClearStepping(); |
589 // Notify the debug event listeners. | 524 // Notify the debug event listeners. |
590 OnDebugBreak(break_points_hit, false); | 525 OnDebugBreak(break_points_hit, false); |
591 return; | 526 return; |
592 } | 527 } |
593 | 528 |
594 // No break point. Check for stepping. | 529 // No break point. Check for stepping. |
595 StepAction step_action = last_step_action(); | 530 StepAction step_action = last_step_action(); |
(...skipping 15 matching lines...) Expand all Loading... | |
611 if (current_fp < target_fp) return; | 546 if (current_fp < target_fp) return; |
612 // For step-next, a tail call is like a return and should break. | 547 // For step-next, a tail call is like a return and should break. |
613 step_break = location.IsTailCall(); | 548 step_break = location.IsTailCall(); |
614 // Fall through. | 549 // Fall through. |
615 case StepIn: { | 550 case StepIn: { |
616 FrameSummary summary = FrameSummary::GetFirst(frame); | 551 FrameSummary summary = FrameSummary::GetFirst(frame); |
617 int offset = summary.code_offset(); | 552 int offset = summary.code_offset(); |
618 step_break = step_break || location.IsReturn() || | 553 step_break = step_break || location.IsReturn() || |
619 (current_fp != last_fp) || | 554 (current_fp != last_fp) || |
620 (thread_local_.last_statement_position_ != | 555 (thread_local_.last_statement_position_ != |
621 location.abstract_code()->SourceStatementPosition(offset)); | 556 summary.abstract_code()->SourceStatementPosition(offset)); |
622 break; | 557 break; |
623 } | 558 } |
624 case StepFrame: | 559 case StepFrame: |
625 step_break = current_fp != last_fp; | 560 step_break = current_fp != last_fp; |
626 break; | 561 break; |
627 } | 562 } |
628 | 563 |
629 // Clear all current stepping setup. | 564 // Clear all current stepping setup. |
630 ClearStepping(); | 565 ClearStepping(); |
631 | 566 |
632 if (step_break) { | 567 if (step_break) { |
633 // Notify the debug event listeners. | 568 // Notify the debug event listeners. |
634 OnDebugBreak(isolate_->factory()->undefined_value(), false); | 569 OnDebugBreak(isolate_->factory()->undefined_value(), false); |
635 } else { | 570 } else { |
636 // Re-prepare to continue. | 571 // Re-prepare to continue. |
637 PrepareStep(step_action); | 572 PrepareStep(step_action); |
638 } | 573 } |
639 } | 574 } |
640 | 575 |
641 | 576 |
642 // Find break point objects for this location, if any, and evaluate them. | 577 // Find break point objects for this location, if any, and evaluate them. |
643 // Return an array of break point objects that evaluated true. | 578 // Return an array of break point objects that evaluated true. |
644 Handle<Object> Debug::CheckBreakPoints(BreakLocation* location, | 579 Handle<Object> Debug::CheckBreakPoints(Handle<DebugInfo> debug_info, |
580 BreakLocation* location, | |
645 bool* has_break_points) { | 581 bool* has_break_points) { |
646 Factory* factory = isolate_->factory(); | 582 Factory* factory = isolate_->factory(); |
647 bool has_break_points_to_check = | 583 bool has_break_points_to_check = |
648 break_points_active_ && location->HasBreakPoint(); | 584 break_points_active_ && location->HasBreakPoint(debug_info); |
649 if (has_break_points) *has_break_points = has_break_points_to_check; | 585 if (has_break_points) *has_break_points = has_break_points_to_check; |
650 if (!has_break_points_to_check) return factory->undefined_value(); | 586 if (!has_break_points_to_check) return factory->undefined_value(); |
651 | 587 |
652 Handle<Object> break_point_objects = location->BreakPointObjects(); | 588 Handle<Object> break_point_objects = |
589 debug_info->GetBreakPointObjects(location->position()); | |
653 // Count the number of break points hit. If there are multiple break points | 590 // Count the number of break points hit. If there are multiple break points |
654 // they are in a FixedArray. | 591 // they are in a FixedArray. |
655 Handle<FixedArray> break_points_hit; | 592 Handle<FixedArray> break_points_hit; |
656 int break_points_hit_count = 0; | 593 int break_points_hit_count = 0; |
657 DCHECK(!break_point_objects->IsUndefined(isolate_)); | 594 DCHECK(!break_point_objects->IsUndefined(isolate_)); |
658 if (break_point_objects->IsFixedArray()) { | 595 if (break_point_objects->IsFixedArray()) { |
659 Handle<FixedArray> array(FixedArray::cast(*break_point_objects)); | 596 Handle<FixedArray> array(FixedArray::cast(*break_point_objects)); |
660 break_points_hit = factory->NewFixedArray(array->length()); | 597 break_points_hit = factory->NewFixedArray(array->length()); |
661 for (int i = 0; i < array->length(); i++) { | 598 for (int i = 0; i < array->length(); i++) { |
662 Handle<Object> break_point_object(array->get(i), isolate_); | 599 Handle<Object> break_point_object(array->get(i), isolate_); |
(...skipping 22 matching lines...) Expand all Loading... | |
685 // an exception event on exception at this location. | 622 // an exception event on exception at this location. |
686 Object* fun = frame->function(); | 623 Object* fun = frame->function(); |
687 if (!fun->IsJSFunction()) return false; | 624 if (!fun->IsJSFunction()) return false; |
688 JSFunction* function = JSFunction::cast(fun); | 625 JSFunction* function = JSFunction::cast(fun); |
689 if (!function->shared()->HasDebugInfo()) return false; | 626 if (!function->shared()->HasDebugInfo()) return false; |
690 HandleScope scope(isolate_); | 627 HandleScope scope(isolate_); |
691 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo()); | 628 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo()); |
692 // Enter the debugger. | 629 // Enter the debugger. |
693 DebugScope debug_scope(this); | 630 DebugScope debug_scope(this); |
694 if (debug_scope.failed()) return false; | 631 if (debug_scope.failed()) return false; |
695 BreakLocation current_position = BreakLocation::FromFrame(debug_info, frame); | |
696 List<BreakLocation> break_locations; | 632 List<BreakLocation> break_locations; |
697 BreakLocation::AllForStatementPosition( | 633 BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations); |
698 debug_info, current_position.statement_position(), &break_locations); | |
699 bool has_break_points_at_all = false; | 634 bool has_break_points_at_all = false; |
700 for (int i = 0; i < break_locations.length(); i++) { | 635 for (int i = 0; i < break_locations.length(); i++) { |
701 bool has_break_points; | 636 bool has_break_points; |
702 Handle<Object> check_result = | 637 Handle<Object> check_result = |
703 CheckBreakPoints(&break_locations[i], &has_break_points); | 638 CheckBreakPoints(debug_info, &break_locations[i], &has_break_points); |
704 has_break_points_at_all |= has_break_points; | 639 has_break_points_at_all |= has_break_points; |
705 if (has_break_points && !check_result->IsUndefined(isolate_)) return false; | 640 if (has_break_points && !check_result->IsUndefined(isolate_)) return false; |
706 } | 641 } |
707 return has_break_points_at_all; | 642 return has_break_points_at_all; |
708 } | 643 } |
709 | 644 |
710 | 645 |
711 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc, | 646 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc, |
712 Handle<Object> args[]) { | 647 Handle<Object> args[]) { |
713 PostponeInterruptsScope no_interrupts(isolate_); | 648 PostponeInterruptsScope no_interrupts(isolate_); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
755 if (!EnsureDebugInfo(shared, function)) { | 690 if (!EnsureDebugInfo(shared, function)) { |
756 // Return if retrieving debug info failed. | 691 // Return if retrieving debug info failed. |
757 return true; | 692 return true; |
758 } | 693 } |
759 | 694 |
760 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 695 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
761 // Source positions starts with zero. | 696 // Source positions starts with zero. |
762 DCHECK(*source_position >= 0); | 697 DCHECK(*source_position >= 0); |
763 | 698 |
764 // Find the break point and change it. | 699 // Find the break point and change it. |
765 BreakLocation location = BreakLocation::FromPosition( | 700 *source_position = |
766 debug_info, *source_position, STATEMENT_ALIGNED); | 701 FindBreakablePosition(debug_info, *source_position, STATEMENT_ALIGNED); |
767 *source_position = location.statement_position(); | 702 DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object); |
768 location.SetBreakPoint(break_point_object); | 703 // At least one active break point now. |
704 DCHECK(debug_info->GetBreakPointCount() > 0); | |
705 | |
706 ClearBreakPoints(debug_info); | |
707 ApplyBreakPoints(debug_info); | |
769 | 708 |
770 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); | 709 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); |
771 | 710 return true; |
772 // At least one active break point now. | |
773 return debug_info->GetBreakPointCount() > 0; | |
774 } | 711 } |
775 | 712 |
776 | 713 |
777 bool Debug::SetBreakPointForScript(Handle<Script> script, | 714 bool Debug::SetBreakPointForScript(Handle<Script> script, |
778 Handle<Object> break_point_object, | 715 Handle<Object> break_point_object, |
779 int* source_position, | 716 int* source_position, |
780 BreakPositionAlignment alignment) { | 717 BreakPositionAlignment alignment) { |
781 if (script->type() == Script::TYPE_WASM) { | 718 if (script->type() == Script::TYPE_WASM) { |
782 // TODO(clemensh): set breakpoint for wasm. | 719 // TODO(clemensh): set breakpoint for wasm. |
783 return false; | 720 return false; |
(...skipping 14 matching lines...) Expand all Loading... | |
798 | 735 |
799 // Find position within function. The script position might be before the | 736 // Find position within function. The script position might be before the |
800 // source position of the first function. | 737 // source position of the first function. |
801 if (shared->start_position() > *source_position) { | 738 if (shared->start_position() > *source_position) { |
802 *source_position = shared->start_position(); | 739 *source_position = shared->start_position(); |
803 } | 740 } |
804 | 741 |
805 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 742 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
806 | 743 |
807 // Find the break point and change it. | 744 // Find the break point and change it. |
808 BreakLocation location = | 745 *source_position = |
809 BreakLocation::FromPosition(debug_info, *source_position, alignment); | 746 FindBreakablePosition(debug_info, *source_position, alignment); |
810 location.SetBreakPoint(break_point_object); | 747 DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object); |
748 // At least one active break point now. | |
749 DCHECK(debug_info->GetBreakPointCount() > 0); | |
750 | |
751 ClearBreakPoints(debug_info); | |
752 ApplyBreakPoints(debug_info); | |
811 | 753 |
812 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); | 754 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); |
813 | |
814 *source_position = (alignment == STATEMENT_ALIGNED) | |
815 ? location.statement_position() | |
816 : location.position(); | |
817 | |
818 // At least one active break point now. | |
819 DCHECK(debug_info->GetBreakPointCount() > 0); | |
820 return true; | 755 return true; |
821 } | 756 } |
822 | 757 |
758 int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info, | |
759 int source_position, | |
760 BreakPositionAlignment alignment) { | |
761 int statement_position; | |
762 int position; | |
763 if (debug_info->HasDebugCode()) { | |
764 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); | |
765 it.SkipToPosition(source_position, alignment); | |
766 statement_position = it.statement_position(); | |
767 position = it.position(); | |
768 } else { | |
769 DCHECK(debug_info->HasDebugBytecodeArray()); | |
770 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); | |
771 it.SkipToPosition(source_position, alignment); | |
772 statement_position = it.statement_position(); | |
773 position = it.position(); | |
774 } | |
775 return alignment == STATEMENT_ALIGNED ? statement_position : position; | |
776 } | |
777 | |
778 void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) { | |
779 DisallowHeapAllocation no_gc; | |
780 if (debug_info->break_points()->IsUndefined(isolate_)) return; | |
781 FixedArray* break_points = debug_info->break_points(); | |
782 for (int i = 0; i < break_points->length(); i++) { | |
783 if (break_points->get(i)->IsUndefined(isolate_)) continue; | |
784 BreakPointInfo* info = BreakPointInfo::cast(break_points->get(i)); | |
785 if (info->GetBreakPointCount() == 0) continue; | |
786 if (debug_info->HasDebugCode()) { | |
787 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); | |
788 it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED); | |
789 it.SetDebugBreak(); | |
790 } | |
791 if (debug_info->HasDebugBytecodeArray()) { | |
792 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); | |
793 it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED); | |
794 it.SetDebugBreak(); | |
795 } | |
796 } | |
797 } | |
798 | |
799 void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) { | |
800 DisallowHeapAllocation no_gc; | |
801 if (debug_info->HasDebugCode()) { | |
802 for (CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); | |
803 it.Next()) { | |
804 it.ClearDebugBreak(); | |
805 } | |
806 } | |
807 if (debug_info->HasDebugBytecodeArray()) { | |
808 for (BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); | |
809 !it.Done(); it.Next()) { | |
810 it.ClearDebugBreak(); | |
811 } | |
812 } | |
813 } | |
823 | 814 |
824 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { | 815 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { |
825 HandleScope scope(isolate_); | 816 HandleScope scope(isolate_); |
826 | 817 |
827 DebugInfoListNode* node = debug_info_list_; | 818 for (DebugInfoListNode* node = debug_info_list_; node != NULL; |
828 while (node != NULL) { | 819 node = node->next()) { |
829 Handle<Object> result = | 820 Handle<Object> result = |
830 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); | 821 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); |
831 if (!result->IsUndefined(isolate_)) { | 822 if (result->IsUndefined(isolate_)) continue; |
832 // Get information in the break point. | 823 Handle<DebugInfo> debug_info = node->debug_info(); |
833 Handle<BreakPointInfo> break_point_info = | 824 if (DebugInfo::ClearBreakPoint(debug_info, break_point_object)) { |
834 Handle<BreakPointInfo>::cast(result); | 825 ClearBreakPoints(debug_info); |
835 Handle<DebugInfo> debug_info = node->debug_info(); | |
836 | |
837 BreakLocation location = BreakLocation::FromPosition( | |
838 debug_info, break_point_info->source_position(), | |
839 BREAK_POSITION_ALIGNED); | |
840 location.ClearBreakPoint(break_point_object); | |
841 | |
842 // If there are no more break points left remove the debug info for this | |
843 // function. | |
844 if (debug_info->GetBreakPointCount() == 0) { | 826 if (debug_info->GetBreakPointCount() == 0) { |
845 RemoveDebugInfoAndClearFromShared(debug_info); | 827 RemoveDebugInfoAndClearFromShared(debug_info); |
828 } else { | |
829 ApplyBreakPoints(debug_info); | |
846 } | 830 } |
847 | |
848 return; | 831 return; |
849 } | 832 } |
850 node = node->next(); | |
851 } | 833 } |
852 } | 834 } |
853 | 835 |
854 | |
855 // Clear out all the debug break code. This is ONLY supposed to be used when | 836 // Clear out all the debug break code. This is ONLY supposed to be used when |
856 // shutting down the debugger as it will leave the break point information in | 837 // shutting down the debugger as it will leave the break point information in |
857 // DebugInfo even though the code is patched back to the non break point state. | 838 // DebugInfo even though the code is patched back to the non break point state. |
858 void Debug::ClearAllBreakPoints() { | 839 void Debug::ClearAllBreakPoints() { |
859 for (DebugInfoListNode* node = debug_info_list_; node != NULL; | 840 for (DebugInfoListNode* node = debug_info_list_; node != NULL; |
860 node = node->next()) { | 841 node = node->next()) { |
861 for (std::unique_ptr<BreakLocation::Iterator> it( | 842 ClearBreakPoints(node->debug_info()); |
862 BreakLocation::GetIterator(node->debug_info())); | |
863 !it->Done(); it->Next()) { | |
864 it->GetBreakLocation().ClearDebugBreak(); | |
865 } | |
866 } | 843 } |
867 // Remove all debug info. | 844 // Remove all debug info. |
868 while (debug_info_list_ != NULL) { | 845 while (debug_info_list_ != NULL) { |
869 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); | 846 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); |
870 } | 847 } |
871 } | 848 } |
872 | 849 |
873 | |
874 void Debug::FloodWithOneShot(Handle<JSFunction> function, | 850 void Debug::FloodWithOneShot(Handle<JSFunction> function, |
875 BreakLocatorType type) { | 851 BreakLocatorType type) { |
876 // Debug utility functions are not subject to debugging. | 852 // Debug utility functions are not subject to debugging. |
877 if (function->native_context() == *debug_context()) return; | 853 if (function->native_context() == *debug_context()) return; |
878 | 854 |
879 if (!function->shared()->IsSubjectToDebugging()) { | 855 if (!function->shared()->IsSubjectToDebugging()) { |
880 // Builtin functions are not subject to stepping, but need to be | 856 // Builtin functions are not subject to stepping, but need to be |
881 // deoptimized, because optimized code does not check for debug | 857 // deoptimized, because optimized code does not check for debug |
882 // step in at call sites. | 858 // step in at call sites. |
883 Deoptimizer::DeoptimizeFunction(*function); | 859 Deoptimizer::DeoptimizeFunction(*function); |
884 return; | 860 return; |
885 } | 861 } |
886 // Make sure the function is compiled and has set up the debug info. | 862 // Make sure the function is compiled and has set up the debug info. |
887 Handle<SharedFunctionInfo> shared(function->shared()); | 863 Handle<SharedFunctionInfo> shared(function->shared()); |
888 if (!EnsureDebugInfo(shared, function)) { | 864 if (!EnsureDebugInfo(shared, function)) { |
889 // Return if we failed to retrieve the debug info. | 865 // Return if we failed to retrieve the debug info. |
890 return; | 866 return; |
891 } | 867 } |
892 | 868 |
893 // Flood the function with break points. | 869 // Flood the function with break points. |
894 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 870 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
895 for (std::unique_ptr<BreakLocation::Iterator> it( | 871 if (debug_info->HasDebugCode()) { |
896 BreakLocation::GetIterator(debug_info, type)); | 872 for (CodeBreakIterator it(debug_info, type); !it.Done(); it.Next()) { |
897 !it->Done(); it->Next()) { | 873 it.SetDebugBreak(); |
898 it->GetBreakLocation().SetOneShot(); | 874 } |
875 } | |
876 if (debug_info->HasDebugBytecodeArray()) { | |
877 for (BytecodeArrayBreakIterator it(debug_info, type); !it.Done(); | |
878 it.Next()) { | |
879 it.SetDebugBreak(); | |
880 } | |
899 } | 881 } |
900 } | 882 } |
901 | 883 |
902 | |
903 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { | 884 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { |
904 if (type == BreakUncaughtException) { | 885 if (type == BreakUncaughtException) { |
905 break_on_uncaught_exception_ = enable; | 886 break_on_uncaught_exception_ = enable; |
906 } else { | 887 } else { |
907 break_on_exception_ = enable; | 888 break_on_exception_ = enable; |
908 } | 889 } |
909 } | 890 } |
910 | 891 |
911 | 892 |
912 bool Debug::IsBreakOnException(ExceptionBreakType type) { | 893 bool Debug::IsBreakOnException(ExceptionBreakType type) { |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1007 // Get the debug info (create it if it does not exist). | 988 // Get the debug info (create it if it does not exist). |
1008 FrameSummary summary = FrameSummary::GetFirst(frame); | 989 FrameSummary summary = FrameSummary::GetFirst(frame); |
1009 Handle<JSFunction> function(summary.function()); | 990 Handle<JSFunction> function(summary.function()); |
1010 Handle<SharedFunctionInfo> shared(function->shared()); | 991 Handle<SharedFunctionInfo> shared(function->shared()); |
1011 if (!EnsureDebugInfo(shared, function)) { | 992 if (!EnsureDebugInfo(shared, function)) { |
1012 // Return if ensuring debug info failed. | 993 // Return if ensuring debug info failed. |
1013 return; | 994 return; |
1014 } | 995 } |
1015 | 996 |
1016 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 997 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1017 // Refresh frame summary if the code has been recompiled for debugging. | 998 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
1018 if (AbstractCode::cast(shared->code()) != *summary.abstract_code()) { | |
1019 summary = FrameSummary::GetFirst(frame); | |
1020 } | |
1021 | |
1022 int call_offset = | |
1023 CallOffsetFromCodeOffset(summary.code_offset(), frame->is_interpreted()); | |
1024 BreakLocation location = | |
1025 BreakLocation::FromCodeOffset(debug_info, call_offset); | |
1026 | 999 |
1027 // Any step at a return is a step-out. | 1000 // Any step at a return is a step-out. |
1028 if (location.IsReturn()) step_action = StepOut; | 1001 if (location.IsReturn()) step_action = StepOut; |
1029 // A step-next at a tail call is a step-out. | 1002 // A step-next at a tail call is a step-out. |
1030 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; | 1003 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; |
1031 | 1004 |
1032 thread_local_.last_statement_position_ = | 1005 thread_local_.last_statement_position_ = |
1033 debug_info->abstract_code()->SourceStatementPosition( | 1006 summary.abstract_code()->SourceStatementPosition(summary.code_offset()); |
1034 summary.code_offset()); | |
1035 thread_local_.last_fp_ = frame->UnpaddedFP(); | 1007 thread_local_.last_fp_ = frame->UnpaddedFP(); |
1036 // No longer perform the current async step. | 1008 // No longer perform the current async step. |
1037 clear_suspended_generator(); | 1009 clear_suspended_generator(); |
1038 | 1010 |
1039 switch (step_action) { | 1011 switch (step_action) { |
1040 case StepNone: | 1012 case StepNone: |
1041 UNREACHABLE(); | 1013 UNREACHABLE(); |
1042 break; | 1014 break; |
1043 case StepOut: | 1015 case StepOut: |
1044 // Advance to caller frame. | 1016 // Advance to caller frame. |
(...skipping 24 matching lines...) Expand all Loading... | |
1069 FloodWithOneShot(function); | 1041 FloodWithOneShot(function); |
1070 break; | 1042 break; |
1071 case StepFrame: | 1043 case StepFrame: |
1072 // No point in setting one-shot breaks at places where we are not about | 1044 // No point in setting one-shot breaks at places where we are not about |
1073 // to leave the current frame. | 1045 // to leave the current frame. |
1074 FloodWithOneShot(function, CALLS_AND_RETURNS); | 1046 FloodWithOneShot(function, CALLS_AND_RETURNS); |
1075 break; | 1047 break; |
1076 } | 1048 } |
1077 } | 1049 } |
1078 | 1050 |
1079 | |
1080 // Simple function for returning the source positions for active break points. | 1051 // Simple function for returning the source positions for active break points. |
1081 Handle<Object> Debug::GetSourceBreakLocations( | 1052 Handle<Object> Debug::GetSourceBreakLocations( |
1082 Handle<SharedFunctionInfo> shared, | 1053 Handle<SharedFunctionInfo> shared, |
1083 BreakPositionAlignment position_alignment) { | 1054 BreakPositionAlignment position_alignment) { |
1084 Isolate* isolate = shared->GetIsolate(); | 1055 Isolate* isolate = shared->GetIsolate(); |
1085 if (!shared->HasDebugInfo()) { | 1056 if (!shared->HasDebugInfo()) { |
1086 return isolate->factory()->undefined_value(); | 1057 return isolate->factory()->undefined_value(); |
1087 } | 1058 } |
1088 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1059 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1089 if (debug_info->GetBreakPointCount() == 0) { | 1060 if (debug_info->GetBreakPointCount() == 0) { |
1090 return isolate->factory()->undefined_value(); | 1061 return isolate->factory()->undefined_value(); |
1091 } | 1062 } |
1092 Handle<FixedArray> locations = | 1063 Handle<FixedArray> locations = |
1093 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); | 1064 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); |
1094 int count = 0; | 1065 int count = 0; |
1095 for (int i = 0; i < debug_info->break_points()->length(); ++i) { | 1066 for (int i = 0; i < debug_info->break_points()->length(); ++i) { |
1096 if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) { | 1067 if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) { |
1097 BreakPointInfo* break_point_info = | 1068 BreakPointInfo* break_point_info = |
1098 BreakPointInfo::cast(debug_info->break_points()->get(i)); | 1069 BreakPointInfo::cast(debug_info->break_points()->get(i)); |
1099 int break_points = break_point_info->GetBreakPointCount(); | 1070 int break_points = break_point_info->GetBreakPointCount(); |
1100 if (break_points == 0) continue; | 1071 if (break_points == 0) continue; |
1101 Smi* position = NULL; | 1072 Smi* position = NULL; |
1102 if (position_alignment == STATEMENT_ALIGNED) { | 1073 if (position_alignment == STATEMENT_ALIGNED) { |
1103 BreakLocation break_point_location = BreakLocation::FromPosition( | 1074 if (debug_info->HasDebugCode()) { |
1104 debug_info, break_point_info->source_position(), | 1075 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); |
1105 BREAK_POSITION_ALIGNED); | 1076 it.SkipToPosition(break_point_info->source_position(), |
1106 position = Smi::FromInt(break_point_location.statement_position()); | 1077 BREAK_POSITION_ALIGNED); |
1078 position = Smi::FromInt(it.statement_position()); | |
1079 } else { | |
jgruber
2016/08/11 14:28:13
Same here.
Yang
2016/08/12 05:33:46
Done.
| |
1080 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); | |
1081 it.SkipToPosition(break_point_info->source_position(), | |
1082 BREAK_POSITION_ALIGNED); | |
1083 position = Smi::FromInt(it.statement_position()); | |
1084 } | |
1107 } else { | 1085 } else { |
1108 DCHECK_EQ(BREAK_POSITION_ALIGNED, position_alignment); | 1086 DCHECK_EQ(BREAK_POSITION_ALIGNED, position_alignment); |
1109 position = Smi::FromInt(break_point_info->source_position()); | 1087 position = Smi::FromInt(break_point_info->source_position()); |
1110 } | 1088 } |
1111 for (int j = 0; j < break_points; ++j) locations->set(count++, position); | 1089 for (int j = 0; j < break_points; ++j) locations->set(count++, position); |
1112 } | 1090 } |
1113 } | 1091 } |
1114 return locations; | 1092 return locations; |
1115 } | 1093 } |
1116 | 1094 |
1117 | |
1118 void Debug::ClearStepping() { | 1095 void Debug::ClearStepping() { |
1119 // Clear the various stepping setup. | 1096 // Clear the various stepping setup. |
1120 ClearOneShot(); | 1097 ClearOneShot(); |
1121 | 1098 |
1122 thread_local_.last_step_action_ = StepNone; | 1099 thread_local_.last_step_action_ = StepNone; |
1123 thread_local_.last_statement_position_ = kNoSourcePosition; | 1100 thread_local_.last_statement_position_ = kNoSourcePosition; |
1124 thread_local_.last_fp_ = 0; | 1101 thread_local_.last_fp_ = 0; |
1125 thread_local_.target_fp_ = 0; | 1102 thread_local_.target_fp_ = 0; |
1126 } | 1103 } |
1127 | 1104 |
1128 | 1105 |
1129 // Clears all the one-shot break points that are currently set. Normally this | 1106 // Clears all the one-shot break points that are currently set. Normally this |
1130 // function is called each time a break point is hit as one shot break points | 1107 // function is called each time a break point is hit as one shot break points |
1131 // are used to support stepping. | 1108 // are used to support stepping. |
1132 void Debug::ClearOneShot() { | 1109 void Debug::ClearOneShot() { |
1133 // The current implementation just runs through all the breakpoints. When the | 1110 // The current implementation just runs through all the breakpoints. When the |
1134 // last break point for a function is removed that function is automatically | 1111 // last break point for a function is removed that function is automatically |
1135 // removed from the list. | 1112 // removed from the list. |
1136 for (DebugInfoListNode* node = debug_info_list_; node != NULL; | 1113 for (DebugInfoListNode* node = debug_info_list_; node != NULL; |
1137 node = node->next()) { | 1114 node = node->next()) { |
1138 for (std::unique_ptr<BreakLocation::Iterator> it( | 1115 Handle<DebugInfo> debug_info = node->debug_info(); |
1139 BreakLocation::GetIterator(node->debug_info())); | 1116 ClearBreakPoints(debug_info); |
1140 !it->Done(); it->Next()) { | 1117 ApplyBreakPoints(debug_info); |
jgruber
2016/08/11 14:28:13
Why are breakpoints reapplied here?
Yang
2016/08/12 05:33:46
Because having a function flooded with one-shots m
| |
1141 it->GetBreakLocation().ClearOneShot(); | |
1142 } | |
1143 } | 1118 } |
1144 } | 1119 } |
1145 | 1120 |
1146 | 1121 |
1147 bool MatchingCodeTargets(Code* target1, Code* target2) { | 1122 bool MatchingCodeTargets(Code* target1, Code* target2) { |
1148 if (target1 == target2) return true; | 1123 if (target1 == target2) return true; |
1149 if (target1->kind() != target2->kind()) return false; | 1124 if (target1->kind() != target2->kind()) return false; |
1150 return target1->is_handler() || target1->is_inline_cache_stub(); | 1125 return target1->is_handler() || target1->is_inline_cache_stub(); |
1151 } | 1126 } |
1152 | 1127 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1236 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { | 1211 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { |
1237 JavaScriptFrame* frame = it.frame(); | 1212 JavaScriptFrame* frame = it.frame(); |
1238 JSFunction* function = frame->function(); | 1213 JSFunction* function = frame->function(); |
1239 if (frame->is_optimized()) continue; | 1214 if (frame->is_optimized()) continue; |
1240 if (!function->Inlines(shared_)) continue; | 1215 if (!function->Inlines(shared_)) continue; |
1241 | 1216 |
1242 if (frame->is_interpreted()) { | 1217 if (frame->is_interpreted()) { |
1243 InterpretedFrame* interpreted_frame = | 1218 InterpretedFrame* interpreted_frame = |
1244 reinterpret_cast<InterpretedFrame*>(frame); | 1219 reinterpret_cast<InterpretedFrame*>(frame); |
1245 BytecodeArray* debug_copy = | 1220 BytecodeArray* debug_copy = |
1246 shared_->GetDebugInfo()->abstract_code()->GetBytecodeArray(); | 1221 shared_->GetDebugInfo()->DebugBytecodeArray(); |
1247 interpreted_frame->PatchBytecodeArray(debug_copy); | 1222 interpreted_frame->PatchBytecodeArray(debug_copy); |
1248 continue; | 1223 continue; |
1249 } | 1224 } |
1250 | 1225 |
1251 Code* frame_code = frame->LookupCode(); | 1226 Code* frame_code = frame->LookupCode(); |
1252 DCHECK(frame_code->kind() == Code::FUNCTION); | 1227 DCHECK(frame_code->kind() == Code::FUNCTION); |
1253 if (frame_code->has_debug_break_slots()) continue; | 1228 if (frame_code->has_debug_break_slots()) continue; |
1254 | 1229 |
1255 Code* new_code = function->shared()->code(); | 1230 Code* new_code = function->shared()->code(); |
1256 Address old_pc = frame->pc(); | 1231 Address old_pc = frame->pc(); |
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1589 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { | 1564 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { |
1590 HandleScope scope(isolate_); | 1565 HandleScope scope(isolate_); |
1591 | 1566 |
1592 // Get the executing function in which the debug break occurred. | 1567 // Get the executing function in which the debug break occurred. |
1593 Handle<SharedFunctionInfo> shared(frame->function()->shared()); | 1568 Handle<SharedFunctionInfo> shared(frame->function()->shared()); |
1594 | 1569 |
1595 // With no debug info there are no break points, so we can't be at a return. | 1570 // With no debug info there are no break points, so we can't be at a return. |
1596 if (!shared->HasDebugInfo()) return false; | 1571 if (!shared->HasDebugInfo()) return false; |
1597 | 1572 |
1598 DCHECK(!frame->is_optimized()); | 1573 DCHECK(!frame->is_optimized()); |
1599 int code_offset = FrameSummary::GetFirst(frame).code_offset(); | |
1600 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); | 1574 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); |
1601 BreakLocation location = | 1575 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); |
1602 BreakLocation::FromCodeOffset(debug_info, code_offset); | |
1603 return location.IsReturn() || location.IsTailCall(); | 1576 return location.IsReturn() || location.IsTailCall(); |
1604 } | 1577 } |
1605 | 1578 |
1606 | 1579 |
1607 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, | 1580 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, |
1608 LiveEdit::FrameDropMode mode) { | 1581 LiveEdit::FrameDropMode mode) { |
1609 if (mode != LiveEdit::CURRENTLY_SET_MODE) { | 1582 if (mode != LiveEdit::CURRENTLY_SET_MODE) { |
1610 thread_local_.frame_drop_mode_ = mode; | 1583 thread_local_.frame_drop_mode_ = mode; |
1611 } | 1584 } |
1612 thread_local_.break_frame_id_ = new_break_frame_id; | 1585 thread_local_.break_frame_id_ = new_break_frame_id; |
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2423 Handle<Object> json; | 2396 Handle<Object> json; |
2424 if (!maybe_json.ToHandle(&json) || !json->IsString()) { | 2397 if (!maybe_json.ToHandle(&json) || !json->IsString()) { |
2425 return v8::Local<v8::String>(); | 2398 return v8::Local<v8::String>(); |
2426 } | 2399 } |
2427 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); | 2400 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); |
2428 } else { | 2401 } else { |
2429 return v8::Utils::ToLocal(response_json_); | 2402 return v8::Utils::ToLocal(response_json_); |
2430 } | 2403 } |
2431 } | 2404 } |
2432 | 2405 |
2406 namespace { | |
2407 v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { | |
2408 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); | |
2409 // Isolate::context() may have been NULL when "script collected" event | |
2410 // occured. | |
2411 if (context.is_null()) return v8::Local<v8::Context>(); | |
2412 Handle<Context> native_context(context->native_context()); | |
2413 return v8::Utils::ToLocal(native_context); | |
2414 } | |
2415 } // anonymous namespace | |
2433 | 2416 |
2434 v8::Local<v8::Context> MessageImpl::GetEventContext() const { | 2417 v8::Local<v8::Context> MessageImpl::GetEventContext() const { |
2435 Isolate* isolate = event_data_->GetIsolate(); | 2418 Isolate* isolate = event_data_->GetIsolate(); |
2436 v8::Local<v8::Context> context = GetDebugEventContext(isolate); | 2419 v8::Local<v8::Context> context = GetDebugEventContext(isolate); |
2437 // Isolate::context() may be NULL when "script collected" event occurs. | 2420 // Isolate::context() may be NULL when "script collected" event occurs. |
2438 DCHECK(!context.IsEmpty()); | 2421 DCHECK(!context.IsEmpty()); |
2439 return context; | 2422 return context; |
2440 } | 2423 } |
2441 | 2424 |
2442 | 2425 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2583 } | 2566 } |
2584 | 2567 |
2585 | 2568 |
2586 void LockingCommandMessageQueue::Clear() { | 2569 void LockingCommandMessageQueue::Clear() { |
2587 base::LockGuard<base::Mutex> lock_guard(&mutex_); | 2570 base::LockGuard<base::Mutex> lock_guard(&mutex_); |
2588 queue_.Clear(); | 2571 queue_.Clear(); |
2589 } | 2572 } |
2590 | 2573 |
2591 } // namespace internal | 2574 } // namespace internal |
2592 } // namespace v8 | 2575 } // namespace v8 |
OLD | NEW |