Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(163)

Side by Side Diff: src/debug/debug.cc

Issue 2238893002: [debugger] separate break point info from code instrumentation. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: fix Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/debug/debug.h ('k') | src/factory.cc » ('j') | src/objects.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/debug/debug.h ('k') | src/factory.cc » ('j') | src/objects.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698