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

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

Issue 2664793002: [debugger] account for inlined functions when stepping. (Closed)
Patch Set: comment addressed Created 3 years, 10 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/frames.h » ('j') | no next file with comments »
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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 } 109 }
110 110
111 bool BreakLocation::HasBreakPoint(Handle<DebugInfo> debug_info) const { 111 bool BreakLocation::HasBreakPoint(Handle<DebugInfo> debug_info) const {
112 // First check whether there is a break point with the same source position. 112 // First check whether there is a break point with the same source position.
113 if (!debug_info->HasBreakPoint(position_)) return false; 113 if (!debug_info->HasBreakPoint(position_)) return false;
114 // Then check whether a break point at that source position would have 114 // Then check whether a break point at that source position would have
115 // the same code offset. Otherwise it's just a break location that we can 115 // the same code offset. Otherwise it's just a break location that we can
116 // step to, but not actually a location where we can put a break point. 116 // step to, but not actually a location where we can put a break point.
117 if (abstract_code_->IsCode()) { 117 if (abstract_code_->IsCode()) {
118 DCHECK_EQ(debug_info->DebugCode(), abstract_code_->GetCode()); 118 DCHECK_EQ(debug_info->DebugCode(), abstract_code_->GetCode());
119 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 119 CodeBreakIterator it(debug_info);
120 it.SkipToPosition(position_, BREAK_POSITION_ALIGNED); 120 it.SkipToPosition(position_, BREAK_POSITION_ALIGNED);
121 return it.code_offset() == code_offset_; 121 return it.code_offset() == code_offset_;
122 } else { 122 } else {
123 DCHECK(abstract_code_->IsBytecodeArray()); 123 DCHECK(abstract_code_->IsBytecodeArray());
124 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 124 BytecodeArrayBreakIterator it(debug_info);
125 it.SkipToPosition(position_, BREAK_POSITION_ALIGNED); 125 it.SkipToPosition(position_, BREAK_POSITION_ALIGNED);
126 return it.code_offset() == code_offset_; 126 return it.code_offset() == code_offset_;
127 } 127 }
128 } 128 }
129 129
130 std::unique_ptr<BreakIterator> BreakIterator::GetIterator( 130 std::unique_ptr<BreakIterator> BreakIterator::GetIterator(
131 Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code, 131 Handle<DebugInfo> debug_info, Handle<AbstractCode> abstract_code) {
132 BreakLocatorType type) {
133 if (abstract_code->IsBytecodeArray()) { 132 if (abstract_code->IsBytecodeArray()) {
134 DCHECK(debug_info->HasDebugBytecodeArray()); 133 DCHECK(debug_info->HasDebugBytecodeArray());
135 return std::unique_ptr<BreakIterator>( 134 return std::unique_ptr<BreakIterator>(
136 new BytecodeArrayBreakIterator(debug_info, type)); 135 new BytecodeArrayBreakIterator(debug_info));
137 } else { 136 } else {
138 DCHECK(abstract_code->IsCode()); 137 DCHECK(abstract_code->IsCode());
139 DCHECK(debug_info->HasDebugCode()); 138 DCHECK(debug_info->HasDebugCode());
140 return std::unique_ptr<BreakIterator>( 139 return std::unique_ptr<BreakIterator>(new CodeBreakIterator(debug_info));
141 new CodeBreakIterator(debug_info, type));
142 } 140 }
143 } 141 }
144 142
145 BreakIterator::BreakIterator(Handle<DebugInfo> debug_info, 143 BreakIterator::BreakIterator(Handle<DebugInfo> debug_info)
146 BreakLocatorType type) 144 : debug_info_(debug_info), break_index_(-1) {
147 : debug_info_(debug_info), break_index_(-1), break_locator_type_(type) {
148 position_ = debug_info->shared()->start_position(); 145 position_ = debug_info->shared()->start_position();
149 statement_position_ = position_; 146 statement_position_ = position_;
150 } 147 }
151 148
152 int BreakIterator::BreakIndexFromPosition(int source_position, 149 int BreakIterator::BreakIndexFromPosition(int source_position,
153 BreakPositionAlignment alignment) { 150 BreakPositionAlignment alignment) {
154 int distance = kMaxInt; 151 int distance = kMaxInt;
155 int closest_break = break_index(); 152 int closest_break = break_index();
156 while (!Done()) { 153 while (!Done()) {
157 int next_position; 154 int next_position;
158 if (alignment == STATEMENT_ALIGNED) { 155 if (alignment == STATEMENT_ALIGNED) {
159 next_position = statement_position(); 156 next_position = statement_position();
160 } else { 157 } else {
161 DCHECK(alignment == BREAK_POSITION_ALIGNED); 158 DCHECK(alignment == BREAK_POSITION_ALIGNED);
162 next_position = position(); 159 next_position = position();
163 } 160 }
164 if (source_position <= next_position && 161 if (source_position <= next_position &&
165 next_position - source_position < distance) { 162 next_position - source_position < distance) {
166 closest_break = break_index(); 163 closest_break = break_index();
167 distance = next_position - source_position; 164 distance = next_position - source_position;
168 // Check whether we can't get any closer. 165 // Check whether we can't get any closer.
169 if (distance == 0) break; 166 if (distance == 0) break;
170 } 167 }
171 Next(); 168 Next();
172 } 169 }
173 return closest_break; 170 return closest_break;
174 } 171 }
175 172
176 CodeBreakIterator::CodeBreakIterator(Handle<DebugInfo> debug_info, 173 CodeBreakIterator::CodeBreakIterator(Handle<DebugInfo> debug_info)
177 BreakLocatorType type) 174 : BreakIterator(debug_info),
178 : BreakIterator(debug_info, type), 175 reloc_iterator_(debug_info->DebugCode(), GetModeMask()),
179 reloc_iterator_(debug_info->DebugCode(), GetModeMask(type)),
180 source_position_iterator_( 176 source_position_iterator_(
181 debug_info->DebugCode()->source_position_table()) { 177 debug_info->DebugCode()->source_position_table()) {
182 // There is at least one break location. 178 // There is at least one break location.
183 DCHECK(!Done()); 179 DCHECK(!Done());
184 Next(); 180 Next();
185 } 181 }
186 182
187 int CodeBreakIterator::GetModeMask(BreakLocatorType type) { 183 int CodeBreakIterator::GetModeMask() {
188 int mask = 0; 184 int mask = 0;
189 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); 185 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN);
190 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); 186 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL);
191 if (isolate()->is_tail_call_elimination_enabled()) { 187 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL);
192 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_TAIL_CALL); 188 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
193 } 189 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT);
194 if (type == ALL_BREAK_LOCATIONS) {
195 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION);
196 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT);
197 }
198 return mask; 190 return mask;
199 } 191 }
200 192
201 void CodeBreakIterator::Next() { 193 void CodeBreakIterator::Next() {
202 DisallowHeapAllocation no_gc; 194 DisallowHeapAllocation no_gc;
203 DCHECK(!Done()); 195 DCHECK(!Done());
204 196
205 // Iterate through reloc info stopping at each breakable code target. 197 // Iterate through reloc info stopping at each breakable code target.
206 bool first = break_index_ == -1; 198 bool first = break_index_ == -1;
207 199
(...skipping 29 matching lines...) Expand all
237 return DEBUGGER_STATEMENT; 229 return DEBUGGER_STATEMENT;
238 } else if (RelocInfo::IsDebugBreakSlot(rmode())) { 230 } else if (RelocInfo::IsDebugBreakSlot(rmode())) {
239 return DEBUG_BREAK_SLOT; 231 return DEBUG_BREAK_SLOT;
240 } else { 232 } else {
241 return NOT_DEBUG_BREAK; 233 return NOT_DEBUG_BREAK;
242 } 234 }
243 } 235 }
244 236
245 void CodeBreakIterator::SkipToPosition(int position, 237 void CodeBreakIterator::SkipToPosition(int position,
246 BreakPositionAlignment alignment) { 238 BreakPositionAlignment alignment) {
247 CodeBreakIterator it(debug_info_, break_locator_type_); 239 CodeBreakIterator it(debug_info_);
248 SkipTo(it.BreakIndexFromPosition(position, alignment)); 240 SkipTo(it.BreakIndexFromPosition(position, alignment));
249 } 241 }
250 242
251 void CodeBreakIterator::SetDebugBreak() { 243 void CodeBreakIterator::SetDebugBreak() {
252 DebugBreakType debug_break_type = GetDebugBreakType(); 244 DebugBreakType debug_break_type = GetDebugBreakType();
253 if (debug_break_type == DEBUGGER_STATEMENT) return; 245 if (debug_break_type == DEBUGGER_STATEMENT) return;
254 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); 246 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
255 Builtins* builtins = isolate()->builtins(); 247 Builtins* builtins = isolate()->builtins();
256 Handle<Code> target = debug_break_type == DEBUG_BREAK_SLOT_AT_RETURN 248 Handle<Code> target = debug_break_type == DEBUG_BREAK_SLOT_AT_RETURN
257 ? builtins->Return_DebugBreak() 249 ? builtins->Return_DebugBreak()
(...skipping 14 matching lines...) Expand all
272 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); 264 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
273 return DebugCodegen::DebugBreakSlotIsPatched(rinfo()->pc()); 265 return DebugCodegen::DebugBreakSlotIsPatched(rinfo()->pc());
274 } 266 }
275 267
276 BreakLocation CodeBreakIterator::GetBreakLocation() { 268 BreakLocation CodeBreakIterator::GetBreakLocation() {
277 Handle<AbstractCode> code(AbstractCode::cast(debug_info_->DebugCode())); 269 Handle<AbstractCode> code(AbstractCode::cast(debug_info_->DebugCode()));
278 return BreakLocation(code, GetDebugBreakType(), code_offset(), position_); 270 return BreakLocation(code, GetDebugBreakType(), code_offset(), position_);
279 } 271 }
280 272
281 BytecodeArrayBreakIterator::BytecodeArrayBreakIterator( 273 BytecodeArrayBreakIterator::BytecodeArrayBreakIterator(
282 Handle<DebugInfo> debug_info, BreakLocatorType type) 274 Handle<DebugInfo> debug_info)
283 : BreakIterator(debug_info, type), 275 : BreakIterator(debug_info),
284 source_position_iterator_( 276 source_position_iterator_(
285 debug_info->DebugBytecodeArray()->source_position_table()) { 277 debug_info->DebugBytecodeArray()->source_position_table()) {
286 // There is at least one break location. 278 // There is at least one break location.
287 DCHECK(!Done()); 279 DCHECK(!Done());
288 Next(); 280 Next();
289 } 281 }
290 282
291 void BytecodeArrayBreakIterator::Next() { 283 void BytecodeArrayBreakIterator::Next() {
292 DisallowHeapAllocation no_gc; 284 DisallowHeapAllocation no_gc;
293 DCHECK(!Done()); 285 DCHECK(!Done());
294 bool first = break_index_ == -1; 286 bool first = break_index_ == -1;
295 while (!Done()) { 287 while (!Done()) {
296 if (!first) source_position_iterator_.Advance(); 288 if (!first) source_position_iterator_.Advance();
297 first = false; 289 first = false;
298 if (Done()) return; 290 if (Done()) return;
299 position_ = source_position_iterator_.source_position().ScriptOffset(); 291 position_ = source_position_iterator_.source_position().ScriptOffset();
300 if (source_position_iterator_.is_statement()) { 292 if (source_position_iterator_.is_statement()) {
301 statement_position_ = position_; 293 statement_position_ = position_;
302 } 294 }
303 DCHECK(position_ >= 0); 295 DCHECK(position_ >= 0);
304 DCHECK(statement_position_ >= 0); 296 DCHECK(statement_position_ >= 0);
305 297
306 DebugBreakType type = GetDebugBreakType(); 298 DebugBreakType type = GetDebugBreakType();
307 if (type == NOT_DEBUG_BREAK) continue; 299 if (type != NOT_DEBUG_BREAK) break;
308
309 if (break_locator_type_ == ALL_BREAK_LOCATIONS) break;
310
311 DCHECK_EQ(CALLS_AND_RETURNS, break_locator_type_);
312 if (type == DEBUG_BREAK_SLOT_AT_CALL) break;
313 if (type == DEBUG_BREAK_SLOT_AT_RETURN) break;
314 } 300 }
315 break_index_++; 301 break_index_++;
316 } 302 }
317 303
318 DebugBreakType BytecodeArrayBreakIterator::GetDebugBreakType() { 304 DebugBreakType BytecodeArrayBreakIterator::GetDebugBreakType() {
319 BytecodeArray* bytecode_array = debug_info_->OriginalBytecodeArray(); 305 BytecodeArray* bytecode_array = debug_info_->OriginalBytecodeArray();
320 interpreter::Bytecode bytecode = 306 interpreter::Bytecode bytecode =
321 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); 307 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
322 308
323 if (bytecode == interpreter::Bytecode::kDebugger) { 309 if (bytecode == interpreter::Bytecode::kDebugger) {
324 return DEBUGGER_STATEMENT; 310 return DEBUGGER_STATEMENT;
325 } else if (bytecode == interpreter::Bytecode::kReturn) { 311 } else if (bytecode == interpreter::Bytecode::kReturn) {
326 return DEBUG_BREAK_SLOT_AT_RETURN; 312 return DEBUG_BREAK_SLOT_AT_RETURN;
327 } else if (bytecode == interpreter::Bytecode::kTailCall) { 313 } else if (bytecode == interpreter::Bytecode::kTailCall) {
328 return isolate()->is_tail_call_elimination_enabled() 314 return isolate()->is_tail_call_elimination_enabled()
329 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL 315 ? DEBUG_BREAK_SLOT_AT_TAIL_CALL
330 : DEBUG_BREAK_SLOT_AT_CALL; 316 : DEBUG_BREAK_SLOT_AT_CALL;
331 } else if (interpreter::Bytecodes::IsCallOrConstruct(bytecode)) { 317 } else if (interpreter::Bytecodes::IsCallOrConstruct(bytecode)) {
332 return DEBUG_BREAK_SLOT_AT_CALL; 318 return DEBUG_BREAK_SLOT_AT_CALL;
333 } else if (source_position_iterator_.is_statement()) { 319 } else if (source_position_iterator_.is_statement()) {
334 return DEBUG_BREAK_SLOT; 320 return DEBUG_BREAK_SLOT;
335 } else { 321 } else {
336 return NOT_DEBUG_BREAK; 322 return NOT_DEBUG_BREAK;
337 } 323 }
338 } 324 }
339 325
340 void BytecodeArrayBreakIterator::SkipToPosition( 326 void BytecodeArrayBreakIterator::SkipToPosition(
341 int position, BreakPositionAlignment alignment) { 327 int position, BreakPositionAlignment alignment) {
342 BytecodeArrayBreakIterator it(debug_info_, break_locator_type_); 328 BytecodeArrayBreakIterator it(debug_info_);
343 SkipTo(it.BreakIndexFromPosition(position, alignment)); 329 SkipTo(it.BreakIndexFromPosition(position, alignment));
344 } 330 }
345 331
346 void BytecodeArrayBreakIterator::SetDebugBreak() { 332 void BytecodeArrayBreakIterator::SetDebugBreak() {
347 DebugBreakType debug_break_type = GetDebugBreakType(); 333 DebugBreakType debug_break_type = GetDebugBreakType();
348 if (debug_break_type == DEBUGGER_STATEMENT) return; 334 if (debug_break_type == DEBUGGER_STATEMENT) return;
349 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT); 335 DCHECK(debug_break_type >= DEBUG_BREAK_SLOT);
350 BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray(); 336 BytecodeArray* bytecode_array = debug_info_->DebugBytecodeArray();
351 interpreter::Bytecode bytecode = 337 interpreter::Bytecode bytecode =
352 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset())); 338 interpreter::Bytecodes::FromByte(bytecode_array->get(code_offset()));
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 } 378 }
393 379
394 380
395 // Threading support. 381 // Threading support.
396 void Debug::ThreadInit() { 382 void Debug::ThreadInit() {
397 thread_local_.break_count_ = 0; 383 thread_local_.break_count_ = 0;
398 thread_local_.break_id_ = 0; 384 thread_local_.break_id_ = 0;
399 thread_local_.break_frame_id_ = StackFrame::NO_ID; 385 thread_local_.break_frame_id_ = StackFrame::NO_ID;
400 thread_local_.last_step_action_ = StepNone; 386 thread_local_.last_step_action_ = StepNone;
401 thread_local_.last_statement_position_ = kNoSourcePosition; 387 thread_local_.last_statement_position_ = kNoSourcePosition;
402 thread_local_.last_fp_ = 0; 388 thread_local_.last_frame_count_ = -1;
403 thread_local_.target_fp_ = 0; 389 thread_local_.target_frame_count_ = -1;
404 thread_local_.return_value_ = Smi::kZero; 390 thread_local_.return_value_ = Smi::kZero;
405 thread_local_.async_task_count_ = 0; 391 thread_local_.async_task_count_ = 0;
406 clear_suspended_generator(); 392 clear_suspended_generator();
407 thread_local_.restart_fp_ = nullptr; 393 thread_local_.restart_fp_ = nullptr;
408 base::NoBarrier_Store(&thread_local_.current_debug_scope_, 394 base::NoBarrier_Store(&thread_local_.current_debug_scope_,
409 static_cast<base::AtomicWord>(0)); 395 static_cast<base::AtomicWord>(0));
410 UpdateHookOnFunctionCall(); 396 UpdateHookOnFunctionCall();
411 } 397 }
412 398
413 399
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 // Enter the debugger. 494 // Enter the debugger.
509 DebugScope debug_scope(this); 495 DebugScope debug_scope(this);
510 if (debug_scope.failed()) return; 496 if (debug_scope.failed()) return;
511 497
512 // Postpone interrupt during breakpoint processing. 498 // Postpone interrupt during breakpoint processing.
513 PostponeInterruptsScope postpone(isolate_); 499 PostponeInterruptsScope postpone(isolate_);
514 500
515 // Return if we fail to retrieve debug info. 501 // Return if we fail to retrieve debug info.
516 Handle<JSFunction> function(frame->function()); 502 Handle<JSFunction> function(frame->function());
517 Handle<SharedFunctionInfo> shared(function->shared()); 503 Handle<SharedFunctionInfo> shared(function->shared());
518 if (!EnsureDebugInfo(shared, function)) return; 504 if (!EnsureDebugInfo(shared)) return;
519 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_); 505 Handle<DebugInfo> debug_info(shared->GetDebugInfo(), isolate_);
520 506
521 // Find the break location where execution has stopped. 507 // Find the break location where execution has stopped.
522 BreakLocation location = BreakLocation::FromFrame(debug_info, frame); 508 BreakLocation location = BreakLocation::FromFrame(debug_info, frame);
523 509
524 // Find actual break points, if any, and trigger debug break event. 510 // Find actual break points, if any, and trigger debug break event.
525 MaybeHandle<FixedArray> break_points_hit = 511 MaybeHandle<FixedArray> break_points_hit =
526 CheckBreakPoints(debug_info, &location); 512 CheckBreakPoints(debug_info, &location);
527 if (!break_points_hit.is_null()) { 513 if (!break_points_hit.is_null()) {
528 // Clear all current stepping setup. 514 // Clear all current stepping setup.
529 ClearStepping(); 515 ClearStepping();
530 // Notify the debug event listeners. 516 // Notify the debug event listeners.
531 Handle<JSArray> jsarr = isolate_->factory()->NewJSArrayWithElements( 517 Handle<JSArray> jsarr = isolate_->factory()->NewJSArrayWithElements(
532 break_points_hit.ToHandleChecked()); 518 break_points_hit.ToHandleChecked());
533 OnDebugBreak(jsarr); 519 OnDebugBreak(jsarr);
534 return; 520 return;
535 } 521 }
536 522
537 // No break point. Check for stepping. 523 // No break point. Check for stepping.
538 StepAction step_action = last_step_action(); 524 StepAction step_action = last_step_action();
539 Address current_fp = frame->UnpaddedFP(); 525 int current_frame_count = CurrentFrameCount();
540 Address target_fp = thread_local_.target_fp_; 526 int target_frame_count = thread_local_.target_frame_count_;
541 Address last_fp = thread_local_.last_fp_; 527 int last_frame_count = thread_local_.last_frame_count_;
542 528
543 bool step_break = false; 529 bool step_break = false;
544 switch (step_action) { 530 switch (step_action) {
545 case StepNone: 531 case StepNone:
546 return; 532 return;
547 case StepOut: 533 case StepOut:
548 // Step out has not reached the target frame yet. 534 // Step out should not break in a deeper frame than target frame.
549 if (current_fp < target_fp) return; 535 if (current_frame_count > target_frame_count) return;
550 step_break = true; 536 step_break = true;
551 break; 537 break;
552 case StepNext: 538 case StepNext:
553 // Step next should not break in a deeper frame. 539 // Step next should not break in a deeper frame than target frame.
554 if (current_fp < target_fp) return; 540 if (current_frame_count > target_frame_count) return;
555 // For step-next, a tail call is like a return and should break. 541 // For step-next, a tail call is like a return and should break.
556 step_break = location.IsTailCall(); 542 step_break = location.IsTailCall();
557 // Fall through. 543 // Fall through.
558 case StepIn: { 544 case StepIn: {
559 FrameSummary summary = FrameSummary::GetTop(frame); 545 FrameSummary summary = FrameSummary::GetTop(frame);
560 step_break = step_break || location.IsReturn() || current_fp != last_fp || 546 step_break = step_break || location.IsReturn() ||
547 current_frame_count != last_frame_count ||
561 thread_local_.last_statement_position_ != 548 thread_local_.last_statement_position_ !=
562 summary.SourceStatementPosition(); 549 summary.SourceStatementPosition();
563 break; 550 break;
564 } 551 }
565 } 552 }
566 553
567 // Clear all current stepping setup. 554 // Clear all current stepping setup.
568 ClearStepping(); 555 ClearStepping();
569 556
570 if (step_break) { 557 if (step_break) {
(...skipping 17 matching lines...) Expand all
588 if (has_break_points) *has_break_points = has_break_points_to_check; 575 if (has_break_points) *has_break_points = has_break_points_to_check;
589 if (!has_break_points_to_check) return {}; 576 if (!has_break_points_to_check) return {};
590 577
591 Handle<Object> break_point_objects = 578 Handle<Object> break_point_objects =
592 debug_info->GetBreakPointObjects(location->position()); 579 debug_info->GetBreakPointObjects(location->position());
593 return Debug::GetHitBreakPointObjects(break_point_objects); 580 return Debug::GetHitBreakPointObjects(break_point_objects);
594 } 581 }
595 582
596 583
597 bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) { 584 bool Debug::IsMutedAtCurrentLocation(JavaScriptFrame* frame) {
585 HandleScope scope(isolate_);
598 // A break location is considered muted if break locations on the current 586 // A break location is considered muted if break locations on the current
599 // statement have at least one break point, and all of these break points 587 // statement have at least one break point, and all of these break points
600 // evaluate to false. Aside from not triggering a debug break event at the 588 // evaluate to false. Aside from not triggering a debug break event at the
601 // break location, we also do not trigger one for debugger statements, nor 589 // break location, we also do not trigger one for debugger statements, nor
602 // an exception event on exception at this location. 590 // an exception event on exception at this location.
603 Object* fun = frame->function(); 591 FrameSummary summary = FrameSummary::GetTop(frame);
604 if (!fun->IsJSFunction()) return false; 592 DCHECK(!summary.IsWasm());
605 JSFunction* function = JSFunction::cast(fun); 593 Handle<JSFunction> function = summary.AsJavaScript().function();
606 if (!function->shared()->HasDebugInfo()) return false; 594 if (!function->shared()->HasDebugInfo()) return false;
607 HandleScope scope(isolate_);
608 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo()); 595 Handle<DebugInfo> debug_info(function->shared()->GetDebugInfo());
609 // Enter the debugger. 596 // Enter the debugger.
610 DebugScope debug_scope(this); 597 DebugScope debug_scope(this);
611 if (debug_scope.failed()) return false; 598 if (debug_scope.failed()) return false;
612 List<BreakLocation> break_locations; 599 List<BreakLocation> break_locations;
613 BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations); 600 BreakLocation::AllAtCurrentStatement(debug_info, frame, &break_locations);
614 bool has_break_points_at_all = false; 601 bool has_break_points_at_all = false;
615 for (int i = 0; i < break_locations.length(); i++) { 602 for (int i = 0; i < break_locations.length(); i++) {
616 bool has_break_points; 603 bool has_break_points;
617 MaybeHandle<FixedArray> check_result = 604 MaybeHandle<FixedArray> check_result =
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 } 650 }
664 651
665 652
666 bool Debug::SetBreakPoint(Handle<JSFunction> function, 653 bool Debug::SetBreakPoint(Handle<JSFunction> function,
667 Handle<Object> break_point_object, 654 Handle<Object> break_point_object,
668 int* source_position) { 655 int* source_position) {
669 HandleScope scope(isolate_); 656 HandleScope scope(isolate_);
670 657
671 // Make sure the function is compiled and has set up the debug info. 658 // Make sure the function is compiled and has set up the debug info.
672 Handle<SharedFunctionInfo> shared(function->shared()); 659 Handle<SharedFunctionInfo> shared(function->shared());
673 if (!EnsureDebugInfo(shared, function)) { 660 if (!EnsureDebugInfo(shared)) return true;
674 // Return if retrieving debug info failed.
675 return true;
676 }
677
678 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 661 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
679 // Source positions starts with zero. 662 // Source positions starts with zero.
680 DCHECK(*source_position >= 0); 663 DCHECK(*source_position >= 0);
681 664
682 // Find the break point and change it. 665 // Find the break point and change it.
683 *source_position = 666 *source_position =
684 FindBreakablePosition(debug_info, *source_position, STATEMENT_ALIGNED); 667 FindBreakablePosition(debug_info, *source_position, STATEMENT_ALIGNED);
685 DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object); 668 DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
686 // At least one active break point now. 669 // At least one active break point now.
687 DCHECK(debug_info->GetBreakPointCount() > 0); 670 DCHECK(debug_info->GetBreakPointCount() > 0);
(...skipping 19 matching lines...) Expand all
707 690
708 HandleScope scope(isolate_); 691 HandleScope scope(isolate_);
709 692
710 // Obtain shared function info for the function. 693 // Obtain shared function info for the function.
711 Handle<Object> result = 694 Handle<Object> result =
712 FindSharedFunctionInfoInScript(script, *source_position); 695 FindSharedFunctionInfoInScript(script, *source_position);
713 if (result->IsUndefined(isolate_)) return false; 696 if (result->IsUndefined(isolate_)) return false;
714 697
715 // Make sure the function has set up the debug info. 698 // Make sure the function has set up the debug info.
716 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); 699 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result);
717 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { 700 if (!EnsureDebugInfo(shared)) return false;
718 // Return if retrieving debug info failed.
719 return false;
720 }
721 701
722 // Find position within function. The script position might be before the 702 // Find position within function. The script position might be before the
723 // source position of the first function. 703 // source position of the first function.
724 if (shared->start_position() > *source_position) { 704 if (shared->start_position() > *source_position) {
725 *source_position = shared->start_position(); 705 *source_position = shared->start_position();
726 } 706 }
727 707
728 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 708 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
729 709
730 // Find the break point and change it. 710 // Find the break point and change it.
731 *source_position = 711 *source_position =
732 FindBreakablePosition(debug_info, *source_position, alignment); 712 FindBreakablePosition(debug_info, *source_position, alignment);
733 DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object); 713 DebugInfo::SetBreakPoint(debug_info, *source_position, break_point_object);
734 // At least one active break point now. 714 // At least one active break point now.
735 DCHECK(debug_info->GetBreakPointCount() > 0); 715 DCHECK(debug_info->GetBreakPointCount() > 0);
736 716
737 ClearBreakPoints(debug_info); 717 ClearBreakPoints(debug_info);
738 ApplyBreakPoints(debug_info); 718 ApplyBreakPoints(debug_info);
739 719
740 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); 720 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint);
741 return true; 721 return true;
742 } 722 }
743 723
744 int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info, 724 int Debug::FindBreakablePosition(Handle<DebugInfo> debug_info,
745 int source_position, 725 int source_position,
746 BreakPositionAlignment alignment) { 726 BreakPositionAlignment alignment) {
747 int statement_position; 727 int statement_position;
748 int position; 728 int position;
749 if (debug_info->HasDebugCode()) { 729 if (debug_info->HasDebugCode()) {
750 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 730 CodeBreakIterator it(debug_info);
751 it.SkipToPosition(source_position, alignment); 731 it.SkipToPosition(source_position, alignment);
752 statement_position = it.statement_position(); 732 statement_position = it.statement_position();
753 position = it.position(); 733 position = it.position();
754 } else { 734 } else {
755 DCHECK(debug_info->HasDebugBytecodeArray()); 735 DCHECK(debug_info->HasDebugBytecodeArray());
756 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 736 BytecodeArrayBreakIterator it(debug_info);
757 it.SkipToPosition(source_position, alignment); 737 it.SkipToPosition(source_position, alignment);
758 statement_position = it.statement_position(); 738 statement_position = it.statement_position();
759 position = it.position(); 739 position = it.position();
760 } 740 }
761 return alignment == STATEMENT_ALIGNED ? statement_position : position; 741 return alignment == STATEMENT_ALIGNED ? statement_position : position;
762 } 742 }
763 743
764 void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) { 744 void Debug::ApplyBreakPoints(Handle<DebugInfo> debug_info) {
765 DisallowHeapAllocation no_gc; 745 DisallowHeapAllocation no_gc;
766 if (debug_info->break_points()->IsUndefined(isolate_)) return; 746 if (debug_info->break_points()->IsUndefined(isolate_)) return;
767 FixedArray* break_points = debug_info->break_points(); 747 FixedArray* break_points = debug_info->break_points();
768 for (int i = 0; i < break_points->length(); i++) { 748 for (int i = 0; i < break_points->length(); i++) {
769 if (break_points->get(i)->IsUndefined(isolate_)) continue; 749 if (break_points->get(i)->IsUndefined(isolate_)) continue;
770 BreakPointInfo* info = BreakPointInfo::cast(break_points->get(i)); 750 BreakPointInfo* info = BreakPointInfo::cast(break_points->get(i));
771 if (info->GetBreakPointCount() == 0) continue; 751 if (info->GetBreakPointCount() == 0) continue;
772 if (debug_info->HasDebugCode()) { 752 if (debug_info->HasDebugCode()) {
773 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 753 CodeBreakIterator it(debug_info);
774 it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED); 754 it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED);
775 it.SetDebugBreak(); 755 it.SetDebugBreak();
776 } 756 }
777 if (debug_info->HasDebugBytecodeArray()) { 757 if (debug_info->HasDebugBytecodeArray()) {
778 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 758 BytecodeArrayBreakIterator it(debug_info);
779 it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED); 759 it.SkipToPosition(info->source_position(), BREAK_POSITION_ALIGNED);
780 it.SetDebugBreak(); 760 it.SetDebugBreak();
781 } 761 }
782 } 762 }
783 } 763 }
784 764
785 void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) { 765 void Debug::ClearBreakPoints(Handle<DebugInfo> debug_info) {
786 DisallowHeapAllocation no_gc; 766 DisallowHeapAllocation no_gc;
787 if (debug_info->HasDebugCode()) { 767 if (debug_info->HasDebugCode()) {
788 for (CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); 768 for (CodeBreakIterator it(debug_info); !it.Done(); it.Next()) {
789 it.Next()) {
790 it.ClearDebugBreak(); 769 it.ClearDebugBreak();
791 } 770 }
792 } 771 }
793 if (debug_info->HasDebugBytecodeArray()) { 772 if (debug_info->HasDebugBytecodeArray()) {
794 for (BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 773 for (BytecodeArrayBreakIterator it(debug_info); !it.Done(); it.Next()) {
795 !it.Done(); it.Next()) {
796 it.ClearDebugBreak(); 774 it.ClearDebugBreak();
797 } 775 }
798 } 776 }
799 } 777 }
800 778
801 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { 779 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
802 HandleScope scope(isolate_); 780 HandleScope scope(isolate_);
803 781
804 for (DebugInfoListNode* node = debug_info_list_; node != NULL; 782 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
805 node = node->next()) { 783 node = node->next()) {
(...skipping 20 matching lines...) Expand all
826 for (DebugInfoListNode* node = debug_info_list_; node != NULL; 804 for (DebugInfoListNode* node = debug_info_list_; node != NULL;
827 node = node->next()) { 805 node = node->next()) {
828 ClearBreakPoints(node->debug_info()); 806 ClearBreakPoints(node->debug_info());
829 } 807 }
830 // Remove all debug info. 808 // Remove all debug info.
831 while (debug_info_list_ != NULL) { 809 while (debug_info_list_ != NULL) {
832 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); 810 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info());
833 } 811 }
834 } 812 }
835 813
836 void Debug::FloodWithOneShot(Handle<JSFunction> function, 814 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) {
837 BreakLocatorType type) { 815 if (!shared->IsSubjectToDebugging() || IsBlackboxed(shared)) return;
838 // Debug utility functions are not subject to debugging.
839 if (function->native_context() == *debug_context()) return;
840
841 if (!function->shared()->IsSubjectToDebugging() ||
842 IsBlackboxed(function->shared())) {
843 // Builtin functions are not subject to stepping, but need to be
844 // deoptimized, because optimized code does not check for debug
845 // step in at call sites.
846 Deoptimizer::DeoptimizeFunction(*function);
847 return;
848 }
849 // Make sure the function is compiled and has set up the debug info. 816 // Make sure the function is compiled and has set up the debug info.
850 Handle<SharedFunctionInfo> shared(function->shared()); 817 if (!EnsureDebugInfo(shared)) return;
851 if (!EnsureDebugInfo(shared, function)) { 818 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
852 // Return if we failed to retrieve the debug info.
853 return;
854 }
855
856 // Flood the function with break points. 819 // Flood the function with break points.
857 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
858 if (debug_info->HasDebugCode()) { 820 if (debug_info->HasDebugCode()) {
859 for (CodeBreakIterator it(debug_info, type); !it.Done(); it.Next()) { 821 for (CodeBreakIterator it(debug_info); !it.Done(); it.Next()) {
860 it.SetDebugBreak(); 822 it.SetDebugBreak();
861 } 823 }
862 } 824 }
863 if (debug_info->HasDebugBytecodeArray()) { 825 if (debug_info->HasDebugBytecodeArray()) {
864 for (BytecodeArrayBreakIterator it(debug_info, type); !it.Done(); 826 for (BytecodeArrayBreakIterator it(debug_info); !it.Done(); it.Next()) {
865 it.Next()) {
866 it.SetDebugBreak(); 827 it.SetDebugBreak();
867 } 828 }
868 } 829 }
869 } 830 }
870 831
871 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { 832 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
872 if (type == BreakUncaughtException) { 833 if (type == BreakUncaughtException) {
873 break_on_uncaught_exception_ = enable; 834 break_on_uncaught_exception_ = enable;
874 } else { 835 } else {
875 break_on_exception_ = enable; 836 break_on_exception_ = enable;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
909 if (break_points_hit_count == 0) return {}; 870 if (break_points_hit_count == 0) return {};
910 break_points_hit->Shrink(break_points_hit_count); 871 break_points_hit->Shrink(break_points_hit_count);
911 return break_points_hit; 872 return break_points_hit;
912 } 873 }
913 874
914 void Debug::PrepareStepIn(Handle<JSFunction> function) { 875 void Debug::PrepareStepIn(Handle<JSFunction> function) {
915 CHECK(last_step_action() >= StepIn); 876 CHECK(last_step_action() >= StepIn);
916 if (ignore_events()) return; 877 if (ignore_events()) return;
917 if (in_debug_scope()) return; 878 if (in_debug_scope()) return;
918 if (break_disabled()) return; 879 if (break_disabled()) return;
919 FloodWithOneShot(function); 880 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared(), isolate_));
920 } 881 }
921 882
922 void Debug::PrepareStepInSuspendedGenerator() { 883 void Debug::PrepareStepInSuspendedGenerator() {
923 CHECK(has_suspended_generator()); 884 CHECK(has_suspended_generator());
924 if (ignore_events()) return; 885 if (ignore_events()) return;
925 if (in_debug_scope()) return; 886 if (in_debug_scope()) return;
926 if (break_disabled()) return; 887 if (break_disabled()) return;
927 thread_local_.last_step_action_ = StepIn; 888 thread_local_.last_step_action_ = StepIn;
928 UpdateHookOnFunctionCall(); 889 UpdateHookOnFunctionCall();
929 Handle<JSFunction> function( 890 Handle<JSFunction> function(
930 JSGeneratorObject::cast(thread_local_.suspended_generator_)->function()); 891 JSGeneratorObject::cast(thread_local_.suspended_generator_)->function());
931 FloodWithOneShot(function); 892 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared(), isolate_));
932 clear_suspended_generator(); 893 clear_suspended_generator();
933 } 894 }
934 895
935 void Debug::PrepareStepOnThrow() { 896 void Debug::PrepareStepOnThrow() {
936 if (last_step_action() == StepNone) return; 897 if (last_step_action() == StepNone) return;
937 if (ignore_events()) return; 898 if (ignore_events()) return;
938 if (in_debug_scope()) return; 899 if (in_debug_scope()) return;
939 if (break_disabled()) return; 900 if (break_disabled()) return;
940 901
941 ClearOneShot(); 902 ClearOneShot();
942 903
904 int current_frame_count = CurrentFrameCount();
905
943 // Iterate through the JavaScript stack looking for handlers. 906 // Iterate through the JavaScript stack looking for handlers.
944 JavaScriptFrameIterator it(isolate_); 907 JavaScriptFrameIterator it(isolate_);
945 while (!it.done()) { 908 while (!it.done()) {
946 JavaScriptFrame* frame = it.frame(); 909 JavaScriptFrame* frame = it.frame();
947 if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break; 910 if (frame->LookupExceptionHandlerInTable(nullptr, nullptr) > 0) break;
911 List<SharedFunctionInfo*> infos;
912 frame->GetFunctions(&infos);
913 current_frame_count -= infos.length();
948 it.Advance(); 914 it.Advance();
949 } 915 }
950 916
951 if (last_step_action() == StepNext || last_step_action() == StepOut) { 917 // No handler found. Nothing to instrument.
952 while (!it.done()) { 918 if (it.done()) return;
953 Address current_fp = it.frame()->UnpaddedFP(); 919
954 if (current_fp >= thread_local_.target_fp_) break; 920 bool found_handler = false;
955 it.Advance(); 921 // Iterate frames, including inlined frames. First, find the handler frame.
922 // Then skip to the frame we want to break in, then instrument for stepping.
923 for (; !it.done(); it.Advance()) {
924 JavaScriptFrame* frame = JavaScriptFrame::cast(it.frame());
925 if (last_step_action() == StepIn) {
926 // Deoptimize frame to ensure calls are checked for step-in.
927 Deoptimizer::DeoptimizeFunction(frame->function());
928 }
929 List<FrameSummary> summaries;
930 frame->Summarize(&summaries);
931 for (int i = summaries.length() - 1; i >= 0; i--, current_frame_count--) {
932 if (!found_handler) {
933 // We have yet to find the handler. If the frame inlines multiple
934 // functions, we have to check each one for the handler.
935 // If it only contains one function, we already found the handler.
936 if (summaries.length() > 1) {
937 Handle<AbstractCode> code =
938 summaries[i].AsJavaScript().abstract_code();
939 CHECK_EQ(AbstractCode::INTERPRETED_FUNCTION, code->kind());
940 BytecodeArray* bytecode = code->GetBytecodeArray();
941 HandlerTable* table = HandlerTable::cast(bytecode->handler_table());
942 int code_offset = summaries[i].code_offset();
943 HandlerTable::CatchPrediction prediction;
944 int index = table->LookupRange(code_offset, nullptr, &prediction);
945 if (index > 0) found_handler = true;
946 } else {
947 found_handler = true;
948 }
949 }
950
951 if (found_handler) {
952 // We found the handler. If we are stepping next or out, we need to
953 // iterate until we found the suitable target frame to break in.
954 if ((last_step_action() == StepNext || last_step_action() == StepOut) &&
955 current_frame_count > thread_local_.target_frame_count_) {
956 continue;
957 }
958 Handle<SharedFunctionInfo> info(
959 summaries[i].AsJavaScript().function()->shared());
960 if (!info->IsSubjectToDebugging() || IsBlackboxed(info)) continue;
961 FloodWithOneShot(info);
962 return;
963 }
956 } 964 }
957 } 965 }
958
959 // Find the closest Javascript frame we can flood with one-shots.
960 while (!it.done() &&
961 (!it.frame()->function()->shared()->IsSubjectToDebugging() ||
962 IsBlackboxed(it.frame()->function()->shared()))) {
963 it.Advance();
964 }
965
966 if (it.done()) return; // No suitable Javascript catch handler.
967
968 FloodWithOneShot(Handle<JSFunction>(it.frame()->function()));
969 } 966 }
970 967
971 968
972 void Debug::PrepareStep(StepAction step_action) { 969 void Debug::PrepareStep(StepAction step_action) {
973 HandleScope scope(isolate_); 970 HandleScope scope(isolate_);
974 971
975 DCHECK(in_debug_scope()); 972 DCHECK(in_debug_scope());
976 973
977 // Get the frame where the execution has stopped and skip the debug frame if 974 // Get the frame where the execution has stopped and skip the debug frame if
978 // any. The debug frame will only be present if execution was stopped due to 975 // any. The debug frame will only be present if execution was stopped due to
979 // hitting a break point. In other situations (e.g. unhandled exception) the 976 // hitting a break point. In other situations (e.g. unhandled exception) the
980 // debug frame is not present. 977 // debug frame is not present.
981 StackFrame::Id frame_id = break_frame_id(); 978 StackFrame::Id frame_id = break_frame_id();
982 // If there is no JavaScript stack don't do anything. 979 // If there is no JavaScript stack don't do anything.
983 if (frame_id == StackFrame::NO_ID) return; 980 if (frame_id == StackFrame::NO_ID) return;
984 981
985 StackTraceFrameIterator frames_it(isolate_, frame_id);
986 StandardFrame* frame = frames_it.frame();
987
988 feature_tracker()->Track(DebugFeatureTracker::kStepping); 982 feature_tracker()->Track(DebugFeatureTracker::kStepping);
989 983
990 thread_local_.last_step_action_ = step_action; 984 thread_local_.last_step_action_ = step_action;
991 UpdateHookOnFunctionCall(); 985 UpdateHookOnFunctionCall();
992 986
987 StackTraceFrameIterator frames_it(isolate_, frame_id);
988 StandardFrame* frame = frames_it.frame();
989
993 // Handle stepping in wasm functions via the wasm interpreter. 990 // Handle stepping in wasm functions via the wasm interpreter.
994 if (frame->is_wasm()) { 991 if (frame->is_wasm()) {
995 // If the top frame is compiled, we cannot step. 992 // If the top frame is compiled, we cannot step.
996 if (frame->is_wasm_compiled()) return; 993 if (frame->is_wasm_compiled()) return;
997 WasmInterpreterEntryFrame* wasm_frame = 994 WasmInterpreterEntryFrame* wasm_frame =
998 WasmInterpreterEntryFrame::cast(frame); 995 WasmInterpreterEntryFrame::cast(frame);
999 wasm_frame->wasm_instance()->debug_info()->PrepareStep(step_action); 996 wasm_frame->wasm_instance()->debug_info()->PrepareStep(step_action);
1000 return; 997 return;
1001 } 998 }
1002 999
1003 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame); 1000 JavaScriptFrame* js_frame = JavaScriptFrame::cast(frame);
1004 1001 DCHECK(js_frame->function()->IsJSFunction());
1005 // If the function on the top frame is unresolved perform step out. This will
1006 // be the case when calling unknown function and having the debugger stopped
1007 // in an unhandled exception.
1008 if (!js_frame->function()->IsJSFunction()) {
1009 // Step out: Find the calling JavaScript frame and flood it with
1010 // breakpoints.
1011 frames_it.Advance();
1012 // Fill the function to return to with one-shot break points.
1013 JSFunction* function = JavaScriptFrame::cast(frames_it.frame())->function();
1014 FloodWithOneShot(handle(function, isolate_));
1015 return;
1016 }
1017 1002
1018 // Get the debug info (create it if it does not exist). 1003 // Get the debug info (create it if it does not exist).
1019 auto summary = FrameSummary::GetTop(frame).AsJavaScript(); 1004 auto summary = FrameSummary::GetTop(frame).AsJavaScript();
1020 Handle<JSFunction> function(summary.function()); 1005 Handle<JSFunction> function(summary.function());
1021 Handle<SharedFunctionInfo> shared(function->shared()); 1006 Handle<SharedFunctionInfo> shared(function->shared());
1022 if (!EnsureDebugInfo(shared, function)) { 1007 if (!EnsureDebugInfo(shared)) return;
1023 // Return if ensuring debug info failed. 1008 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1024 return;
1025 }
1026 1009
1027 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1028 BreakLocation location = BreakLocation::FromFrame(debug_info, js_frame); 1010 BreakLocation location = BreakLocation::FromFrame(debug_info, js_frame);
1029 1011
1030 // Any step at a return is a step-out. 1012 // Any step at a return is a step-out.
1031 if (location.IsReturn()) step_action = StepOut; 1013 if (location.IsReturn()) step_action = StepOut;
1032 // A step-next at a tail call is a step-out. 1014 // A step-next at a tail call is a step-out.
1033 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut; 1015 if (location.IsTailCall() && step_action == StepNext) step_action = StepOut;
1034 // A step-next in blackboxed function is a step-out. 1016 // A step-next in blackboxed function is a step-out.
1035 if (step_action == StepNext && IsBlackboxed(shared)) step_action = StepOut; 1017 if (step_action == StepNext && IsBlackboxed(shared)) step_action = StepOut;
1036 1018
1037 thread_local_.last_statement_position_ = 1019 thread_local_.last_statement_position_ =
1038 summary.abstract_code()->SourceStatementPosition(summary.code_offset()); 1020 summary.abstract_code()->SourceStatementPosition(summary.code_offset());
1039 thread_local_.last_fp_ = frame->UnpaddedFP(); 1021 int current_frame_count = CurrentFrameCount();
1022 thread_local_.last_frame_count_ = current_frame_count;
1040 // No longer perform the current async step. 1023 // No longer perform the current async step.
1041 clear_suspended_generator(); 1024 clear_suspended_generator();
1042 1025
1043 switch (step_action) { 1026 switch (step_action) {
1044 case StepNone: 1027 case StepNone:
1045 UNREACHABLE(); 1028 UNREACHABLE();
1046 break; 1029 break;
1047 case StepOut: 1030 case StepOut: {
1048 // Advance to caller frame.
1049 frames_it.Advance();
1050 // Find top-most function which is subject to debugging.
1051 while (!frames_it.done()) {
1052 StandardFrame* caller_frame = frames_it.frame();
1053 if (caller_frame->is_wasm()) {
1054 // TODO(clemensh): Implement stepping out from JS to WASM.
1055 break;
1056 }
1057 Handle<JSFunction> js_caller_function(
1058 JavaScriptFrame::cast(caller_frame)->function(), isolate_);
1059 if (js_caller_function->shared()->IsSubjectToDebugging() &&
1060 !IsBlackboxed(js_caller_function->shared())) {
1061 // Fill the caller function to return to with one-shot break points.
1062 FloodWithOneShot(js_caller_function);
1063 thread_local_.target_fp_ = frames_it.frame()->UnpaddedFP();
1064 break;
1065 }
1066 // Builtin functions are not subject to stepping, but need to be
1067 // deoptimized to include checks for step-in at call sites.
1068 Deoptimizer::DeoptimizeFunction(*js_caller_function);
1069 frames_it.Advance();
1070 }
1071 // Clear last position info. For stepping out it does not matter. 1031 // Clear last position info. For stepping out it does not matter.
1072 thread_local_.last_statement_position_ = kNoSourcePosition; 1032 thread_local_.last_statement_position_ = kNoSourcePosition;
1073 thread_local_.last_fp_ = 0; 1033 thread_local_.last_frame_count_ = -1;
1034 // Skip the current frame, find the first frame we want to step out to
1035 // and deoptimize every frame along the way.
1036 bool in_current_frame = true;
1037 for (; !frames_it.done(); frames_it.Advance()) {
1038 // TODO(clemensh): Implement stepping out from JS to WASM.
1039 if (frames_it.frame()->is_wasm()) continue;
1040 JavaScriptFrame* frame = JavaScriptFrame::cast(frames_it.frame());
1041 if (last_step_action() == StepIn) {
1042 // Deoptimize frame to ensure calls are checked for step-in.
1043 Deoptimizer::DeoptimizeFunction(frame->function());
1044 }
1045 HandleScope scope(isolate_);
1046 List<Handle<SharedFunctionInfo>> infos;
1047 frame->GetFunctions(&infos);
1048 for (; !infos.is_empty(); current_frame_count--) {
1049 Handle<SharedFunctionInfo> info = infos.RemoveLast();
1050 if (in_current_frame) {
1051 // We want to skip out, so skip the current frame.
1052 in_current_frame = false;
1053 continue;
1054 }
1055 if (!info->IsSubjectToDebugging() || IsBlackboxed(info)) continue;
1056 FloodWithOneShot(info);
1057 thread_local_.target_frame_count_ = current_frame_count;
1058 return;
1059 }
1060 }
1074 break; 1061 break;
1062 }
1075 case StepNext: 1063 case StepNext:
1076 thread_local_.target_fp_ = frame->UnpaddedFP(); 1064 thread_local_.target_frame_count_ = current_frame_count;
1077 FloodWithOneShot(function); 1065 // Fall through.
1078 break;
1079 case StepIn: 1066 case StepIn:
1080 // TODO(clemensh): Implement stepping from JS into WASM. 1067 // TODO(clemensh): Implement stepping from JS into WASM.
1081 FloodWithOneShot(function); 1068 FloodWithOneShot(shared);
1082 break; 1069 break;
1083 } 1070 }
1084 } 1071 }
1085 1072
1086 // Simple function for returning the source positions for active break points. 1073 // Simple function for returning the source positions for active break points.
1087 Handle<Object> Debug::GetSourceBreakLocations( 1074 Handle<Object> Debug::GetSourceBreakLocations(
1088 Handle<SharedFunctionInfo> shared, 1075 Handle<SharedFunctionInfo> shared,
1089 BreakPositionAlignment position_alignment) { 1076 BreakPositionAlignment position_alignment) {
1090 Isolate* isolate = shared->GetIsolate(); 1077 Isolate* isolate = shared->GetIsolate();
1091 if (!shared->HasDebugInfo()) { 1078 if (!shared->HasDebugInfo()) {
1092 return isolate->factory()->undefined_value(); 1079 return isolate->factory()->undefined_value();
1093 } 1080 }
1094 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 1081 Handle<DebugInfo> debug_info(shared->GetDebugInfo());
1095 if (debug_info->GetBreakPointCount() == 0) { 1082 if (debug_info->GetBreakPointCount() == 0) {
1096 return isolate->factory()->undefined_value(); 1083 return isolate->factory()->undefined_value();
1097 } 1084 }
1098 Handle<FixedArray> locations = 1085 Handle<FixedArray> locations =
1099 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); 1086 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1100 int count = 0; 1087 int count = 0;
1101 for (int i = 0; i < debug_info->break_points()->length(); ++i) { 1088 for (int i = 0; i < debug_info->break_points()->length(); ++i) {
1102 if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) { 1089 if (!debug_info->break_points()->get(i)->IsUndefined(isolate)) {
1103 BreakPointInfo* break_point_info = 1090 BreakPointInfo* break_point_info =
1104 BreakPointInfo::cast(debug_info->break_points()->get(i)); 1091 BreakPointInfo::cast(debug_info->break_points()->get(i));
1105 int break_points = break_point_info->GetBreakPointCount(); 1092 int break_points = break_point_info->GetBreakPointCount();
1106 if (break_points == 0) continue; 1093 if (break_points == 0) continue;
1107 Smi* position = NULL; 1094 Smi* position = NULL;
1108 if (position_alignment == STATEMENT_ALIGNED) { 1095 if (position_alignment == STATEMENT_ALIGNED) {
1109 if (debug_info->HasDebugCode()) { 1096 if (debug_info->HasDebugCode()) {
1110 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 1097 CodeBreakIterator it(debug_info);
1111 it.SkipToPosition(break_point_info->source_position(), 1098 it.SkipToPosition(break_point_info->source_position(),
1112 BREAK_POSITION_ALIGNED); 1099 BREAK_POSITION_ALIGNED);
1113 position = Smi::FromInt(it.statement_position()); 1100 position = Smi::FromInt(it.statement_position());
1114 } else { 1101 } else {
1115 DCHECK(debug_info->HasDebugBytecodeArray()); 1102 DCHECK(debug_info->HasDebugBytecodeArray());
1116 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 1103 BytecodeArrayBreakIterator it(debug_info);
1117 it.SkipToPosition(break_point_info->source_position(), 1104 it.SkipToPosition(break_point_info->source_position(),
1118 BREAK_POSITION_ALIGNED); 1105 BREAK_POSITION_ALIGNED);
1119 position = Smi::FromInt(it.statement_position()); 1106 position = Smi::FromInt(it.statement_position());
1120 } 1107 }
1121 } else { 1108 } else {
1122 DCHECK_EQ(BREAK_POSITION_ALIGNED, position_alignment); 1109 DCHECK_EQ(BREAK_POSITION_ALIGNED, position_alignment);
1123 position = Smi::FromInt(break_point_info->source_position()); 1110 position = Smi::FromInt(break_point_info->source_position());
1124 } 1111 }
1125 for (int j = 0; j < break_points; ++j) locations->set(count++, position); 1112 for (int j = 0; j < break_points; ++j) locations->set(count++, position);
1126 } 1113 }
1127 } 1114 }
1128 return locations; 1115 return locations;
1129 } 1116 }
1130 1117
1131 void Debug::ClearStepping() { 1118 void Debug::ClearStepping() {
1132 // Clear the various stepping setup. 1119 // Clear the various stepping setup.
1133 ClearOneShot(); 1120 ClearOneShot();
1134 1121
1135 thread_local_.last_step_action_ = StepNone; 1122 thread_local_.last_step_action_ = StepNone;
1136 thread_local_.last_statement_position_ = kNoSourcePosition; 1123 thread_local_.last_statement_position_ = kNoSourcePosition;
1137 thread_local_.last_fp_ = 0; 1124 thread_local_.last_frame_count_ = -1;
1138 thread_local_.target_fp_ = 0; 1125 thread_local_.target_frame_count_ = -1;
1139 UpdateHookOnFunctionCall(); 1126 UpdateHookOnFunctionCall();
1140 } 1127 }
1141 1128
1142 1129
1143 // Clears all the one-shot break points that are currently set. Normally this 1130 // Clears all the one-shot break points that are currently set. Normally this
1144 // function is called each time a break point is hit as one shot break points 1131 // function is called each time a break point is hit as one shot break points
1145 // are used to support stepping. 1132 // are used to support stepping.
1146 void Debug::ClearOneShot() { 1133 void Debug::ClearOneShot() {
1147 // The current implementation just runs through all the breakpoints. When the 1134 // The current implementation just runs through all the breakpoints. When the
1148 // last break point for a function is removed that function is automatically 1135 // last break point for a function is removed that function is automatically
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
1347 positions->insert(alignment == STATEMENT_ALIGNED ? it->statement_position() 1334 positions->insert(alignment == STATEMENT_ALIGNED ? it->statement_position()
1348 : it->position()); 1335 : it->position());
1349 it->Next(); 1336 it->Next();
1350 } 1337 }
1351 } 1338 }
1352 1339
1353 void FindBreakablePositions(Handle<DebugInfo> debug_info, int start_position, 1340 void FindBreakablePositions(Handle<DebugInfo> debug_info, int start_position,
1354 int end_position, BreakPositionAlignment alignment, 1341 int end_position, BreakPositionAlignment alignment,
1355 std::set<int>* positions) { 1342 std::set<int>* positions) {
1356 if (debug_info->HasDebugCode()) { 1343 if (debug_info->HasDebugCode()) {
1357 CodeBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 1344 CodeBreakIterator it(debug_info);
1358 GetBreakablePositions(&it, start_position, end_position, alignment, 1345 GetBreakablePositions(&it, start_position, end_position, alignment,
1359 positions); 1346 positions);
1360 } else { 1347 } else {
1361 DCHECK(debug_info->HasDebugBytecodeArray()); 1348 DCHECK(debug_info->HasDebugBytecodeArray());
1362 BytecodeArrayBreakIterator it(debug_info, ALL_BREAK_LOCATIONS); 1349 BytecodeArrayBreakIterator it(debug_info);
1363 GetBreakablePositions(&it, start_position, end_position, alignment, 1350 GetBreakablePositions(&it, start_position, end_position, alignment,
1364 positions); 1351 positions);
1365 } 1352 }
1366 } 1353 }
1367 } // namespace 1354 } // namespace
1368 1355
1369 bool Debug::GetPossibleBreakpoints(Handle<Script> script, int start_position, 1356 bool Debug::GetPossibleBreakpoints(Handle<Script> script, int start_position,
1370 int end_position, std::set<int>* positions) { 1357 int end_position, std::set<int>* positions) {
1371 while (true) { 1358 while (true) {
1372 HandleScope scope(isolate_); 1359 HandleScope scope(isolate_);
(...skipping 14 matching lines...) Expand all
1387 for (int i = 0; i < candidates.length(); ++i) { 1374 for (int i = 0; i < candidates.length(); ++i) {
1388 // Code that cannot be compiled lazily are internal and not debuggable. 1375 // Code that cannot be compiled lazily are internal and not debuggable.
1389 DCHECK(candidates[i]->allows_lazy_compilation()); 1376 DCHECK(candidates[i]->allows_lazy_compilation());
1390 if (!candidates[i]->HasDebugCode()) { 1377 if (!candidates[i]->HasDebugCode()) {
1391 if (!Compiler::CompileDebugCode(candidates[i])) { 1378 if (!Compiler::CompileDebugCode(candidates[i])) {
1392 return false; 1379 return false;
1393 } else { 1380 } else {
1394 was_compiled = true; 1381 was_compiled = true;
1395 } 1382 }
1396 } 1383 }
1397 if (!EnsureDebugInfo(candidates[i], Handle<JSFunction>::null())) 1384 if (!EnsureDebugInfo(candidates[i])) return false;
1398 return false;
1399 } 1385 }
1400 if (was_compiled) continue; 1386 if (was_compiled) continue;
1401 1387
1402 for (int i = 0; i < candidates.length(); ++i) { 1388 for (int i = 0; i < candidates.length(); ++i) {
1403 CHECK(candidates[i]->HasDebugInfo()); 1389 CHECK(candidates[i]->HasDebugInfo());
1404 Handle<DebugInfo> debug_info(candidates[i]->GetDebugInfo()); 1390 Handle<DebugInfo> debug_info(candidates[i]->GetDebugInfo());
1405 FindBreakablePositions(debug_info, start_position, end_position, 1391 FindBreakablePositions(debug_info, start_position, end_position,
1406 STATEMENT_ALIGNED, positions); 1392 STATEMENT_ALIGNED, positions);
1407 } 1393 }
1408 return true; 1394 return true;
1409 } 1395 }
1410 UNREACHABLE(); 1396 UNREACHABLE();
1411 return false; 1397 return false;
1412 } 1398 }
1413 1399
1414 void Debug::RecordGenerator(Handle<JSGeneratorObject> generator_object) { 1400 void Debug::RecordGenerator(Handle<JSGeneratorObject> generator_object) {
1415 if (last_step_action() <= StepOut) return; 1401 if (last_step_action() <= StepOut) return;
1416 1402
1417 if (last_step_action() == StepNext) { 1403 if (last_step_action() == StepNext) {
1418 // Only consider this generator a step-next target if not stepping in. 1404 // Only consider this generator a step-next target if not stepping in.
1419 JavaScriptFrameIterator stack_iterator(isolate_); 1405 if (thread_local_.target_frame_count_ < CurrentFrameCount()) return;
1420 JavaScriptFrame* frame = stack_iterator.frame();
1421 if (frame->UnpaddedFP() < thread_local_.target_fp_) return;
1422 } 1406 }
1423 1407
1424 DCHECK(!has_suspended_generator()); 1408 DCHECK(!has_suspended_generator());
1425 thread_local_.suspended_generator_ = *generator_object; 1409 thread_local_.suspended_generator_ = *generator_object;
1426 ClearStepping(); 1410 ClearStepping();
1427 } 1411 }
1428 1412
1429 class SharedFunctionInfoFinder { 1413 class SharedFunctionInfoFinder {
1430 public: 1414 public:
1431 explicit SharedFunctionInfoFinder(int target_position) 1415 explicit SharedFunctionInfoFinder(int target_position)
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
1519 HandleScope scope(isolate_); 1503 HandleScope scope(isolate_);
1520 // Code that cannot be compiled lazily are internal and not debuggable. 1504 // Code that cannot be compiled lazily are internal and not debuggable.
1521 DCHECK(shared->allows_lazy_compilation()); 1505 DCHECK(shared->allows_lazy_compilation());
1522 if (!Compiler::CompileDebugCode(handle(shared))) break; 1506 if (!Compiler::CompileDebugCode(handle(shared))) break;
1523 } 1507 }
1524 return isolate_->factory()->undefined_value(); 1508 return isolate_->factory()->undefined_value();
1525 } 1509 }
1526 1510
1527 1511
1528 // Ensures the debug information is present for shared. 1512 // Ensures the debug information is present for shared.
1529 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, 1513 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
1530 Handle<JSFunction> function) {
1531 if (!shared->IsSubjectToDebugging()) return false;
1532
1533 // Return if we already have the debug info for shared. 1514 // Return if we already have the debug info for shared.
1534 if (shared->HasDebugInfo()) return true; 1515 if (shared->HasDebugInfo()) return true;
1535 1516 if (!shared->IsSubjectToDebugging()) return false;
1536 if (function.is_null()) { 1517 if (!shared->is_compiled() && !Compiler::CompileDebugCode(shared)) {
1537 DCHECK(shared->HasDebugCode());
1538 } else if (!Compiler::Compile(function, Compiler::CLEAR_EXCEPTION)) {
1539 return false; 1518 return false;
1540 } 1519 }
1541 1520
1542 // To prepare bytecode for debugging, we already need to have the debug 1521 // To prepare bytecode for debugging, we already need to have the debug
1543 // info (containing the debug copy) upfront, but since we do not recompile, 1522 // info (containing the debug copy) upfront, but since we do not recompile,
1544 // preparing for break points cannot fail. 1523 // preparing for break points cannot fail.
1545 CreateDebugInfo(shared); 1524 CreateDebugInfo(shared);
1546 CHECK(PrepareFunctionForBreakPoints(shared)); 1525 CHECK(PrepareFunctionForBreakPoints(shared));
1547 return true; 1526 return true;
1548 } 1527 }
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1699 Handle<Smi> id) { 1678 Handle<Smi> id) {
1700 DCHECK(id->IsNumber()); 1679 DCHECK(id->IsNumber());
1701 // Create the async task event object. 1680 // Create the async task event object.
1702 Handle<Object> argv[] = {type, id}; 1681 Handle<Object> argv[] = {type, id};
1703 return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv); 1682 return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv);
1704 } 1683 }
1705 1684
1706 1685
1707 void Debug::OnThrow(Handle<Object> exception) { 1686 void Debug::OnThrow(Handle<Object> exception) {
1708 if (in_debug_scope() || ignore_events()) return; 1687 if (in_debug_scope() || ignore_events()) return;
1709 PrepareStepOnThrow();
1710 // Temporarily clear any scheduled_exception to allow evaluating 1688 // Temporarily clear any scheduled_exception to allow evaluating
1711 // JavaScript from the debug event handler. 1689 // JavaScript from the debug event handler.
1712 HandleScope scope(isolate_); 1690 HandleScope scope(isolate_);
1713 Handle<Object> scheduled_exception; 1691 Handle<Object> scheduled_exception;
1714 if (isolate_->has_scheduled_exception()) { 1692 if (isolate_->has_scheduled_exception()) {
1715 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_); 1693 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_);
1716 isolate_->clear_scheduled_exception(); 1694 isolate_->clear_scheduled_exception();
1717 } 1695 }
1718 OnException(exception, isolate_->GetPromiseOnStackOnThrow()); 1696 OnException(exception, isolate_->GetPromiseOnStackOnThrow());
1719 if (!scheduled_exception.is_null()) { 1697 if (!scheduled_exception.is_null()) {
1720 isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception; 1698 isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception;
1721 } 1699 }
1700 PrepareStepOnThrow();
1722 } 1701 }
1723 1702
1724 void Debug::OnPromiseReject(Handle<Object> promise, Handle<Object> value) { 1703 void Debug::OnPromiseReject(Handle<Object> promise, Handle<Object> value) {
1725 if (in_debug_scope() || ignore_events()) return; 1704 if (in_debug_scope() || ignore_events()) return;
1726 HandleScope scope(isolate_); 1705 HandleScope scope(isolate_);
1727 // Check whether the promise has been marked as having triggered a message. 1706 // Check whether the promise has been marked as having triggered a message.
1728 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); 1707 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol();
1729 if (!promise->IsJSObject() || 1708 if (!promise->IsJSObject() ||
1730 JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key) 1709 JSReceiver::GetDataProperty(Handle<JSObject>::cast(promise), key)
1731 ->IsUndefined(isolate_)) { 1710 ->IsUndefined(isolate_)) {
(...skipping 23 matching lines...) Expand all
1755 while (!it.done()) { 1734 while (!it.done()) {
1756 if (!IsFrameBlackboxed(it.frame())) return false; 1735 if (!IsFrameBlackboxed(it.frame())) return false;
1757 it.Advance(); 1736 it.Advance();
1758 } 1737 }
1759 return true; 1738 return true;
1760 } 1739 }
1761 1740
1762 bool Debug::IsFrameBlackboxed(JavaScriptFrame* frame) { 1741 bool Debug::IsFrameBlackboxed(JavaScriptFrame* frame) {
1763 HandleScope scope(isolate_); 1742 HandleScope scope(isolate_);
1764 if (!frame->HasInlinedFrames()) { 1743 if (!frame->HasInlinedFrames()) {
1765 return IsBlackboxed(frame->function()->shared()); 1744 Handle<SharedFunctionInfo> shared(frame->function()->shared(), isolate_);
1745 return IsBlackboxed(shared);
1766 } 1746 }
1767 List<SharedFunctionInfo*> raw_shareds; 1747 List<Handle<SharedFunctionInfo>> infos;
1768 frame->GetFunctions(&raw_shareds); 1748 frame->GetFunctions(&infos);
1769 List<Handle<SharedFunctionInfo>> shareds; 1749 for (const auto& info : infos)
1770 for (int i = 0; i < raw_shareds.length(); ++i) { 1750 if (!IsBlackboxed(info)) return false;
1771 shareds.Add(handle(raw_shareds[i]));
1772 }
1773 for (int i = 0; i < shareds.length(); ++i) {
1774 if (!IsBlackboxed(shareds[i])) return false;
1775 }
1776 return true; 1751 return true;
1777 } 1752 }
1778 1753
1779 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { 1754 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) {
1780 // We cannot generate debug events when JS execution is disallowed. 1755 // We cannot generate debug events when JS execution is disallowed.
1781 // TODO(5530): Reenable debug events within DisallowJSScopes once relevant 1756 // TODO(5530): Reenable debug events within DisallowJSScopes once relevant
1782 // code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++. 1757 // code (MakeExceptionEvent and ProcessDebugEvent) have been moved to C++.
1783 if (!AllowJavascriptExecution::IsAllowed(isolate_)) return; 1758 if (!AllowJavascriptExecution::IsAllowed(isolate_)) return;
1784 1759
1785 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher(); 1760 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher();
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
2006 } 1981 }
2007 1982
2008 namespace { 1983 namespace {
2009 debug::Location GetDebugLocation(Handle<Script> script, int source_position) { 1984 debug::Location GetDebugLocation(Handle<Script> script, int source_position) {
2010 Script::PositionInfo info; 1985 Script::PositionInfo info;
2011 Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET); 1986 Script::GetPositionInfo(script, source_position, &info, Script::WITH_OFFSET);
2012 return debug::Location(info.line, info.column); 1987 return debug::Location(info.line, info.column);
2013 } 1988 }
2014 } // namespace 1989 } // namespace
2015 1990
2016 bool Debug::IsBlackboxed(SharedFunctionInfo* shared) {
2017 HandleScope scope(isolate_);
2018 Handle<SharedFunctionInfo> shared_function_info(shared);
2019 return IsBlackboxed(shared_function_info);
2020 }
2021
2022 bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) { 1991 bool Debug::IsBlackboxed(Handle<SharedFunctionInfo> shared) {
2023 if (!debug_delegate_) return false; 1992 if (!debug_delegate_) return false;
2024 if (!shared->computed_debug_is_blackboxed()) { 1993 if (!shared->computed_debug_is_blackboxed()) {
2025 bool is_blackboxed = false; 1994 bool is_blackboxed = false;
2026 if (shared->script()->IsScript()) { 1995 if (shared->script()->IsScript()) {
2027 HandleScope handle_scope(isolate_); 1996 HandleScope handle_scope(isolate_);
2028 Handle<Script> script(Script::cast(shared->script())); 1997 Handle<Script> script(Script::cast(shared->script()));
2029 if (script->type() == i::Script::TYPE_NORMAL) { 1998 if (script->type() == i::Script::TYPE_NORMAL) {
2030 debug::Location start = 1999 debug::Location start =
2031 GetDebugLocation(script, shared->start_position()); 2000 GetDebugLocation(script, shared->start_position());
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
2155 // Set new entry. 2124 // Set new entry.
2156 if (!callback->IsNullOrUndefined(isolate_)) { 2125 if (!callback->IsNullOrUndefined(isolate_)) {
2157 event_listener_ = global_handles->Create(*callback); 2126 event_listener_ = global_handles->Create(*callback);
2158 if (data.is_null()) data = isolate_->factory()->undefined_value(); 2127 if (data.is_null()) data = isolate_->factory()->undefined_value();
2159 event_listener_data_ = global_handles->Create(*data); 2128 event_listener_data_ = global_handles->Create(*data);
2160 } 2129 }
2161 2130
2162 UpdateState(); 2131 UpdateState();
2163 } 2132 }
2164 2133
2134 int Debug::CurrentFrameCount() {
2135 StackTraceFrameIterator it(isolate_);
2136 if (break_frame_id() != StackFrame::NO_ID) {
2137 // Skip to break frame.
2138 DCHECK(in_debug_scope());
2139 while (!it.done() && it.frame()->id() != break_frame_id()) it.Advance();
2140 }
2141 int counter = 0;
2142 while (!it.done()) {
2143 if (it.frame()->is_optimized()) {
2144 List<SharedFunctionInfo*> infos;
2145 OptimizedFrame::cast(it.frame())->GetFunctions(&infos);
2146 counter += infos.length();
2147 } else {
2148 counter++;
2149 }
2150 it.Advance();
2151 }
2152 return counter;
2153 }
2154
2165 void Debug::SetDebugDelegate(debug::DebugDelegate* delegate) { 2155 void Debug::SetDebugDelegate(debug::DebugDelegate* delegate) {
2166 debug_delegate_ = delegate; 2156 debug_delegate_ = delegate;
2167 UpdateState(); 2157 UpdateState();
2168 } 2158 }
2169 2159
2170 void Debug::UpdateState() { 2160 void Debug::UpdateState() {
2171 bool is_active = !event_listener_.is_null() || debug_delegate_ != nullptr; 2161 bool is_active = !event_listener_.is_null() || debug_delegate_ != nullptr;
2172 if (is_active || in_debug_scope()) { 2162 if (is_active || in_debug_scope()) {
2173 // Note that the debug context could have already been loaded to 2163 // Note that the debug context could have already been loaded to
2174 // bootstrap test cases. 2164 // bootstrap test cases.
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
2218 // Ignore debug break if debugger is not active. 2208 // Ignore debug break if debugger is not active.
2219 if (!is_active()) return; 2209 if (!is_active()) return;
2220 2210
2221 StackLimitCheck check(isolate_); 2211 StackLimitCheck check(isolate_);
2222 if (check.HasOverflowed()) return; 2212 if (check.HasOverflowed()) return;
2223 2213
2224 { JavaScriptFrameIterator it(isolate_); 2214 { JavaScriptFrameIterator it(isolate_);
2225 DCHECK(!it.done()); 2215 DCHECK(!it.done());
2226 Object* fun = it.frame()->function(); 2216 Object* fun = it.frame()->function();
2227 if (fun && fun->IsJSFunction()) { 2217 if (fun && fun->IsJSFunction()) {
2218 HandleScope scope(isolate_);
2228 // Don't stop in builtin and blackboxed functions. 2219 // Don't stop in builtin and blackboxed functions.
2229 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging() || 2220 Handle<SharedFunctionInfo> shared(JSFunction::cast(fun)->shared(),
2230 IsBlackboxed(JSFunction::cast(fun)->shared())) { 2221 isolate_);
2222 if (!shared->IsSubjectToDebugging() || IsBlackboxed(shared)) {
2231 // Inspector uses pause on next statement for asynchronous breakpoints. 2223 // Inspector uses pause on next statement for asynchronous breakpoints.
2232 // When breakpoint is fired we try to break on first not blackboxed 2224 // When breakpoint is fired we try to break on first not blackboxed
2233 // statement. To achieve this goal we need to deoptimize current 2225 // statement. To achieve this goal we need to deoptimize current
2234 // function and don't clear requested DebugBreak even if it's blackboxed 2226 // function and don't clear requested DebugBreak even if it's blackboxed
2235 // to be able to break on not blackboxed function call. 2227 // to be able to break on not blackboxed function call.
2236 // TODO(yangguo): introduce break_on_function_entry since current 2228 // TODO(yangguo): introduce break_on_function_entry since current
2237 // implementation is slow. 2229 // implementation is slow.
2238 Deoptimizer::DeoptimizeFunction(JSFunction::cast(fun)); 2230 Deoptimizer::DeoptimizeFunction(JSFunction::cast(fun));
2239 return; 2231 return;
2240 } 2232 }
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
2428 return v8::Utils::ToLocal(callback_data_); 2420 return v8::Utils::ToLocal(callback_data_);
2429 } 2421 }
2430 2422
2431 2423
2432 v8::Isolate* EventDetailsImpl::GetIsolate() const { 2424 v8::Isolate* EventDetailsImpl::GetIsolate() const {
2433 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); 2425 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate());
2434 } 2426 }
2435 2427
2436 } // namespace internal 2428 } // namespace internal
2437 } // namespace v8 2429 } // namespace v8
OLDNEW
« no previous file with comments | « src/debug/debug.h ('k') | src/frames.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698