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 3 // found in the LICENSE file. 4 5 #include "src/debug/debug.h" 6 7 #include "src/api.h" 8 #include "src/arguments.h" 9 #include "src/bootstrapper.h" 10 #include "src/code-stubs.h" 11 #include "src/codegen.h" 12 #include "src/compilation-cache.h" 13 #include "src/compiler.h" 14 #include "src/deoptimizer.h" 15 #include "src/execution.h" 16 #include "src/frames-inl.h" 17 #include "src/full-codegen/full-codegen.h" 18 #include "src/global-handles.h" 19 #include "src/isolate-inl.h" 20 #include "src/list.h" 21 #include "src/log.h" 22 #include "src/messages.h" 23 #include "src/snapshot/natives.h" 24 25 #include "include/v8-debug.h" 26 27 namespace v8 { 28 namespace internal { 29 30 Debug::Debug(Isolate* isolate) 31 : debug_context_(Handle<Context>()), 32 event_listener_(Handle<Object>()), 33 event_listener_data_(Handle<Object>()), 34 message_handler_(NULL), 35 command_received_(0), 36 command_queue_(isolate->logger(), kQueueInitialSize), 37 is_active_(false), 38 is_suppressed_(false), 39 live_edit_enabled_(true), // TODO(yangguo): set to false by default. 40 break_disabled_(false), 41 break_points_active_(true), 42 in_debug_event_listener_(false), 43 break_on_exception_(false), 44 break_on_uncaught_exception_(false), 45 debug_info_list_(NULL), 46 feature_tracker_(isolate), 47 isolate_(isolate) { 48 ThreadInit(); 49 } 50 51 52 static v8::Local<v8::Context> GetDebugEventContext(Isolate* isolate) { 53 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); 54 // Isolate::context() may have been NULL when "script collected" event 55 // occured. 56 if (context.is_null()) return v8::Local<v8::Context>(); 57 Handle<Context> native_context(context->native_context()); 58 return v8::Utils::ToLocal(native_context); 59 } 60 61 62 BreakLocation::BreakLocation(Handle<DebugInfo> debug_info, RelocInfo* rinfo, 63 int position, int statement_position) 64 : debug_info_(debug_info), 65 pc_offset_(static_cast<int>(rinfo->pc() - debug_info->code()->entry())), 66 rmode_(rinfo->rmode()), 67 data_(rinfo->data()), 68 position_(position), 69 statement_position_(statement_position) {} 70 71 72 BreakLocation::Iterator::Iterator(Handle<DebugInfo> debug_info, 73 BreakLocatorType type) 74 : debug_info_(debug_info), 75 reloc_iterator_(debug_info->code(), GetModeMask(type)), 76 break_index_(-1), 77 position_(1), 78 statement_position_(1) { 79 if (!Done()) Next(); 80 } 81 82 83 int BreakLocation::Iterator::GetModeMask(BreakLocatorType type) { 84 int mask = 0; 85 mask |= RelocInfo::ModeMask(RelocInfo::POSITION); 86 mask |= RelocInfo::ModeMask(RelocInfo::STATEMENT_POSITION); 87 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); 88 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_CALL); 89 if (type == ALL_BREAK_LOCATIONS) { 90 mask |= RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_POSITION); 91 mask |= RelocInfo::ModeMask(RelocInfo::DEBUGGER_STATEMENT); 92 } 93 return mask; 94 } 95 96 97 void BreakLocation::Iterator::Next() { 98 DisallowHeapAllocation no_gc; 99 DCHECK(!Done()); 100 101 // Iterate through reloc info for code and original code stopping at each 102 // breakable code target. 103 bool first = break_index_ == -1; 104 while (!Done()) { 105 if (!first) reloc_iterator_.next(); 106 first = false; 107 if (Done()) return; 108 109 // Whenever a statement position or (plain) position is passed update the 110 // current value of these. 111 if (RelocInfo::IsPosition(rmode())) { 112 if (RelocInfo::IsStatementPosition(rmode())) { 113 statement_position_ = static_cast<int>( 114 rinfo()->data() - debug_info_->shared()->start_position()); 115 } 116 // Always update the position as we don't want that to be before the 117 // statement position. 118 position_ = static_cast<int>(rinfo()->data() - 119 debug_info_->shared()->start_position()); 120 DCHECK(position_ >= 0); 121 DCHECK(statement_position_ >= 0); 122 continue; 123 } 124 125 DCHECK(RelocInfo::IsDebugBreakSlot(rmode()) || 126 RelocInfo::IsDebuggerStatement(rmode())); 127 128 if (RelocInfo::IsDebugBreakSlotAtReturn(rmode())) { 129 // Set the positions to the end of the function. 130 if (debug_info_->shared()->HasSourceCode()) { 131 position_ = debug_info_->shared()->end_position() - 132 debug_info_->shared()->start_position() - 1; 133 } else { 134 position_ = 0; 135 } 136 statement_position_ = position_; 137 } 138 139 break; 140 } 141 break_index_++; 142 } 143 144 145 // Find the break point at the supplied address, or the closest one before 146 // the address. 147 BreakLocation BreakLocation::FromAddress(Handle<DebugInfo> debug_info, 148 Address pc) { 149 Iterator it(debug_info, ALL_BREAK_LOCATIONS); 150 it.SkipTo(BreakIndexFromAddress(debug_info, pc)); 151 return it.GetBreakLocation(); 152 } 153 154 155 // Find the break point at the supplied address, or the closest one before 156 // the address. 157 void BreakLocation::FromAddressSameStatement(Handle<DebugInfo> debug_info, 158 Address pc, 159 List<BreakLocation>* result_out) { 160 int break_index = BreakIndexFromAddress(debug_info, pc); 161 Iterator it(debug_info, ALL_BREAK_LOCATIONS); 162 it.SkipTo(break_index); 163 int statement_position = it.statement_position(); 164 while (!it.Done() && it.statement_position() == statement_position) { 165 result_out->Add(it.GetBreakLocation()); 166 it.Next(); 167 } 168 } 169 170 171 int BreakLocation::BreakIndexFromAddress(Handle<DebugInfo> debug_info, 172 Address pc) { 173 // Run through all break points to locate the one closest to the address. 174 int closest_break = 0; 175 int distance = kMaxInt; 176 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { 177 // Check if this break point is closer that what was previously found. 178 if (it.pc() <= pc && pc - it.pc() < distance) { 179 closest_break = it.break_index(); 180 distance = static_cast<int>(pc - it.pc()); 181 // Check whether we can't get any closer. 182 if (distance == 0) break; 183 } 184 } 185 return closest_break; 186 } 187 188 189 BreakLocation BreakLocation::FromPosition(Handle<DebugInfo> debug_info, 190 int position, 191 BreakPositionAlignment alignment) { 192 // Run through all break points to locate the one closest to the source 193 // position. 194 int closest_break = 0; 195 int distance = kMaxInt; 196 197 for (Iterator it(debug_info, ALL_BREAK_LOCATIONS); !it.Done(); it.Next()) { 198 int next_position; 199 if (alignment == STATEMENT_ALIGNED) { 200 next_position = it.statement_position(); 201 } else { 202 DCHECK(alignment == BREAK_POSITION_ALIGNED); 203 next_position = it.position(); 204 } 205 if (position <= next_position && next_position - position < distance) { 206 closest_break = it.break_index(); 207 distance = next_position - position; 208 // Check whether we can't get any closer. 209 if (distance == 0) break; 210 } 211 } 212 213 Iterator it(debug_info, ALL_BREAK_LOCATIONS); 214 it.SkipTo(closest_break); 215 return it.GetBreakLocation(); 216 } 217 218 219 void BreakLocation::SetBreakPoint(Handle<Object> break_point_object) { 220 // If there is not already a real break point here patch code with debug 221 // break. 222 if (!HasBreakPoint()) SetDebugBreak(); 223 DCHECK(IsDebugBreak() || IsDebuggerStatement()); 224 // Set the break point information. 225 DebugInfo::SetBreakPoint(debug_info_, pc_offset_, position_, 226 statement_position_, break_point_object); 227 } 228 229 230 void BreakLocation::ClearBreakPoint(Handle<Object> break_point_object) { 231 // Clear the break point information. 232 DebugInfo::ClearBreakPoint(debug_info_, pc_offset_, break_point_object); 233 // If there are no more break points here remove the debug break. 234 if (!HasBreakPoint()) { 235 ClearDebugBreak(); 236 DCHECK(!IsDebugBreak()); 237 } 238 } 239 240 241 void BreakLocation::SetOneShot() { 242 // Debugger statement always calls debugger. No need to modify it. 243 if (IsDebuggerStatement()) return; 244 245 // If there is a real break point here no more to do. 246 if (HasBreakPoint()) { 247 DCHECK(IsDebugBreak()); 248 return; 249 } 250 251 // Patch code with debug break. 252 SetDebugBreak(); 253 } 254 255 256 void BreakLocation::ClearOneShot() { 257 // Debugger statement always calls debugger. No need to modify it. 258 if (IsDebuggerStatement()) return; 259 260 // If there is a real break point here no more to do. 261 if (HasBreakPoint()) { 262 DCHECK(IsDebugBreak()); 263 return; 264 } 265 266 // Patch code removing debug break. 267 ClearDebugBreak(); 268 DCHECK(!IsDebugBreak()); 269 } 270 271 272 void BreakLocation::SetDebugBreak() { 273 // Debugger statement always calls debugger. No need to modify it. 274 if (IsDebuggerStatement()) return; 275 276 // If there is already a break point here just return. This might happen if 277 // the same code is flooded with break points twice. Flooding the same 278 // function twice might happen when stepping in a function with an exception 279 // handler as the handler and the function is the same. 280 if (IsDebugBreak()) return; 281 282 DCHECK(IsDebugBreakSlot()); 283 Isolate* isolate = debug_info_->GetIsolate(); 284 Builtins* builtins = isolate->builtins(); 285 Handle<Code> target = 286 IsReturn() ? builtins->Return_DebugBreak() : builtins->Slot_DebugBreak(); 287 DebugCodegen::PatchDebugBreakSlot(isolate, pc(), target); 288 DCHECK(IsDebugBreak()); 289 } 290 291 292 void BreakLocation::ClearDebugBreak() { 293 // Debugger statement always calls debugger. No need to modify it. 294 if (IsDebuggerStatement()) return; 295 296 DCHECK(IsDebugBreakSlot()); 297 DebugCodegen::ClearDebugBreakSlot(debug_info_->GetIsolate(), pc()); 298 DCHECK(!IsDebugBreak()); 299 } 300 301 302 bool BreakLocation::IsDebugBreak() const { 303 if (IsDebuggerStatement()) return false; 304 DCHECK(IsDebugBreakSlot()); 305 return rinfo().IsPatchedDebugBreakSlotSequence(); 306 } 307 308 309 Handle<Object> BreakLocation::BreakPointObjects() const { 310 return debug_info_->GetBreakPointObjects(pc_offset_); 311 } 312 313 314 void DebugFeatureTracker::Track(DebugFeatureTracker::Feature feature) { 315 uint32_t mask = 1 << feature; 316 // Only count one sample per feature and isolate. 317 if (bitfield_ & mask) return; 318 isolate_->counters()->debug_feature_usage()->AddSample(feature); 319 bitfield_ |= mask; 320 } 321 322 323 // Threading support. 324 void Debug::ThreadInit() { 325 thread_local_.break_count_ = 0; 326 thread_local_.break_id_ = 0; 327 thread_local_.break_frame_id_ = StackFrame::NO_ID; 328 thread_local_.last_step_action_ = StepNone; 329 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; 330 thread_local_.last_fp_ = 0; 331 thread_local_.target_fp_ = 0; 332 thread_local_.step_in_enabled_ = false; 333 // TODO(isolates): frames_are_dropped_? 334 base::NoBarrier_Store(&thread_local_.current_debug_scope_, 335 static_cast<base::AtomicWord>(0)); 336 } 337 338 339 char* Debug::ArchiveDebug(char* storage) { 340 char* to = storage; 341 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); 342 ThreadInit(); 343 return storage + ArchiveSpacePerThread(); 344 } 345 346 347 char* Debug::RestoreDebug(char* storage) { 348 char* from = storage; 349 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); 350 return storage + ArchiveSpacePerThread(); 351 } 352 353 354 int Debug::ArchiveSpacePerThread() { 355 return sizeof(ThreadLocal); 356 } 357 358 359 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { 360 // Globalize the request debug info object and make it weak. 361 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); 362 debug_info_ = 363 Handle<DebugInfo>::cast(global_handles->Create(debug_info)).location(); 364 } 365 366 367 DebugInfoListNode::~DebugInfoListNode() { 368 if (debug_info_ == nullptr) return; 369 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_)); 370 debug_info_ = nullptr; 371 } 372 373 374 bool Debug::Load() { 375 // Return if debugger is already loaded. 376 if (is_loaded()) return true; 377 378 // Bail out if we're already in the process of compiling the native 379 // JavaScript source code for the debugger. 380 if (is_suppressed_) return false; 381 SuppressDebug while_loading(this); 382 383 // Disable breakpoints and interrupts while compiling and running the 384 // debugger scripts including the context creation code. 385 DisableBreak disable(this, true); 386 PostponeInterruptsScope postpone(isolate_); 387 388 // Create the debugger context. 389 HandleScope scope(isolate_); 390 ExtensionConfiguration no_extensions; 391 Handle<Context> context = isolate_->bootstrapper()->CreateEnvironment( 392 MaybeHandle<JSGlobalProxy>(), v8::Local<ObjectTemplate>(), &no_extensions, 393 DEBUG_CONTEXT); 394 395 // Fail if no context could be created. 396 if (context.is_null()) return false; 397 398 debug_context_ = Handle<Context>::cast( 399 isolate_->global_handles()->Create(*context)); 400 401 feature_tracker()->Track(DebugFeatureTracker::kActive); 402 403 return true; 404 } 405 406 407 void Debug::Unload() { 408 ClearAllBreakPoints(); 409 ClearStepping(); 410 411 // Return debugger is not loaded. 412 if (!is_loaded()) return; 413 414 // Clear debugger context global handle. 415 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); 416 debug_context_ = Handle<Context>(); 417 } 418 419 420 void Debug::Break(Arguments args, JavaScriptFrame* frame) { 421 HandleScope scope(isolate_); 422 DCHECK(args.length() == 0); 423 424 // Initialize LiveEdit. 425 LiveEdit::InitializeThreadLocal(this); 426 427 // Just continue if breaks are disabled or debugger cannot be loaded. 428 if (break_disabled()) return; 429 430 // Enter the debugger. 431 DebugScope debug_scope(this); 432 if (debug_scope.failed()) return; 433 434 // Postpone interrupt during breakpoint processing. 435 PostponeInterruptsScope postpone(isolate_); 436 437 // Get the debug info (create it if it does not exist). 438 Handle<JSFunction> function(frame->function()); 439 Handle<SharedFunctionInfo> shared(function->shared()); 440 if (!EnsureDebugInfo(shared, function)) { 441 // Return if we failed to retrieve the debug info. 442 return; 443 } 444 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 445 446 // Find the break location where execution has stopped. 447 // PC points to the instruction after the current one, possibly a break 448 // location as well. So the "- 1" to exclude it from the search. 449 Address call_pc = frame->pc() - 1; 450 BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc); 451 452 // Find actual break points, if any, and trigger debug break event. 453 if (break_points_active_ && location.HasBreakPoint()) { 454 Handle<Object> break_point_objects = location.BreakPointObjects(); 455 Handle<Object> break_points_hit = CheckBreakPoints(break_point_objects); 456 if (!break_points_hit->IsUndefined()) { 457 // Clear all current stepping setup. 458 ClearStepping(); 459 // Notify the debug event listeners. 460 OnDebugBreak(break_points_hit, false); 461 return; 462 } 463 } 464 465 // No break point. Check for stepping. 466 StepAction step_action = last_step_action(); 467 Address current_fp = frame->UnpaddedFP(); 468 Address target_fp = thread_local_.target_fp_; 469 Address last_fp = thread_local_.last_fp_; 470 471 bool step_break = true; 472 switch (step_action) { 473 case StepNone: 474 return; 475 case StepOut: 476 // Step out has not reached the target frame yet. 477 if (current_fp < target_fp) return; 478 break; 479 case StepNext: 480 // Step next should not break in a deeper frame. 481 if (current_fp < target_fp) return; 482 // Fall through. 483 case StepIn: 484 step_break = location.IsReturn() || (current_fp != last_fp) || 485 (thread_local_.last_statement_position_ != 486 location.code()->SourceStatementPosition(frame->pc())); 487 break; 488 case StepFrame: 489 step_break = current_fp != last_fp; 490 break; 491 } 492 493 // Clear all current stepping setup. 494 ClearStepping(); 495 496 if (step_break) { 497 // Notify the debug event listeners. 498 OnDebugBreak(isolate_->factory()->undefined_value(), false); 499 } else { 500 // Re-prepare to continue. 501 PrepareStep(step_action); 502 } 503 } 504 505 506 // Check the break point objects for whether one or more are actually 507 // triggered. This function returns a JSArray with the break point objects 508 // which is triggered. 509 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { 510 Factory* factory = isolate_->factory(); 511 512 // Count the number of break points hit. If there are multiple break points 513 // they are in a FixedArray. 514 Handle<FixedArray> break_points_hit; 515 int break_points_hit_count = 0; 516 DCHECK(!break_point_objects->IsUndefined()); 517 if (break_point_objects->IsFixedArray()) { 518 Handle<FixedArray> array(FixedArray::cast(*break_point_objects)); 519 break_points_hit = factory->NewFixedArray(array->length()); 520 for (int i = 0; i < array->length(); i++) { 521 Handle<Object> o(array->get(i), isolate_); 522 if (CheckBreakPoint(o)) { 523 break_points_hit->set(break_points_hit_count++, *o); 524 } 525 } 526 } else { 527 break_points_hit = factory->NewFixedArray(1); 528 if (CheckBreakPoint(break_point_objects)) { 529 break_points_hit->set(break_points_hit_count++, *break_point_objects); 530 } 531 } 532 533 // Return undefined if no break points were triggered. 534 if (break_points_hit_count == 0) { 535 return factory->undefined_value(); 536 } 537 // Return break points hit as a JSArray. 538 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit); 539 result->set_length(Smi::FromInt(break_points_hit_count)); 540 return result; 541 } 542 543 544 MaybeHandle<Object> Debug::CallFunction(const char* name, int argc, 545 Handle<Object> args[]) { 546 PostponeInterruptsScope no_interrupts(isolate_); 547 AssertDebugContext(); 548 Handle<Object> holder = isolate_->natives_utils_object(); 549 Handle<JSFunction> fun = Handle<JSFunction>::cast( 550 Object::GetProperty(isolate_, holder, name, STRICT).ToHandleChecked()); 551 Handle<Object> undefined = isolate_->factory()->undefined_value(); 552 return Execution::TryCall(isolate_, fun, undefined, argc, args); 553 } 554 555 556 // Check whether a single break point object is triggered. 557 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) { 558 Factory* factory = isolate_->factory(); 559 HandleScope scope(isolate_); 560 561 // Ignore check if break point object is not a JSObject. 562 if (!break_point_object->IsJSObject()) return true; 563 564 // Get the break id as an object. 565 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id()); 566 567 // Call IsBreakPointTriggered. 568 Handle<Object> argv[] = { break_id, break_point_object }; 569 Handle<Object> result; 570 if (!CallFunction("IsBreakPointTriggered", arraysize(argv), argv) 571 .ToHandle(&result)) { 572 return false; 573 } 574 575 // Return whether the break point is triggered. 576 return result->IsTrue(); 577 } 578 579 580 bool Debug::SetBreakPoint(Handle<JSFunction> function, 581 Handle<Object> break_point_object, 582 int* source_position) { 583 HandleScope scope(isolate_); 584 585 // Make sure the function is compiled and has set up the debug info. 586 Handle<SharedFunctionInfo> shared(function->shared()); 587 if (!EnsureDebugInfo(shared, function)) { 588 // Return if retrieving debug info failed. 589 return true; 590 } 591 592 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 593 // Source positions starts with zero. 594 DCHECK(*source_position >= 0); 595 596 // Find the break point and change it. 597 BreakLocation location = BreakLocation::FromPosition( 598 debug_info, *source_position, STATEMENT_ALIGNED); 599 *source_position = location.statement_position(); 600 location.SetBreakPoint(break_point_object); 601 602 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); 603 604 // At least one active break point now. 605 return debug_info->GetBreakPointCount() > 0; 606 } 607 608 609 bool Debug::SetBreakPointForScript(Handle<Script> script, 610 Handle<Object> break_point_object, 611 int* source_position, 612 BreakPositionAlignment alignment) { 613 HandleScope scope(isolate_); 614 615 // Obtain shared function info for the function. 616 Handle<Object> result = 617 FindSharedFunctionInfoInScript(script, *source_position); 618 if (result->IsUndefined()) return false; 619 620 // Make sure the function has set up the debug info. 621 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>::cast(result); 622 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { 623 // Return if retrieving debug info failed. 624 return false; 625 } 626 627 // Find position within function. The script position might be before the 628 // source position of the first function. 629 int position; 630 if (shared->start_position() > *source_position) { 631 position = 0; 632 } else { 633 position = *source_position - shared->start_position(); 634 } 635 636 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 637 // Source positions starts with zero. 638 DCHECK(position >= 0); 639 640 // Find the break point and change it. 641 BreakLocation location = 642 BreakLocation::FromPosition(debug_info, position, alignment); 643 location.SetBreakPoint(break_point_object); 644 645 feature_tracker()->Track(DebugFeatureTracker::kBreakPoint); 646 647 position = (alignment == STATEMENT_ALIGNED) ? location.statement_position() 648 : location.position(); 649 650 *source_position = position + shared->start_position(); 651 652 // At least one active break point now. 653 DCHECK(debug_info->GetBreakPointCount() > 0); 654 return true; 655 } 656 657 658 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { 659 HandleScope scope(isolate_); 660 661 DebugInfoListNode* node = debug_info_list_; 662 while (node != NULL) { 663 Handle<Object> result = 664 DebugInfo::FindBreakPointInfo(node->debug_info(), break_point_object); 665 if (!result->IsUndefined()) { 666 // Get information in the break point. 667 Handle<BreakPointInfo> break_point_info = 668 Handle<BreakPointInfo>::cast(result); 669 Handle<DebugInfo> debug_info = node->debug_info(); 670 671 // Find the break point and clear it. 672 Address pc = 673 debug_info->code()->entry() + break_point_info->code_position(); 674 675 BreakLocation location = BreakLocation::FromAddress(debug_info, pc); 676 location.ClearBreakPoint(break_point_object); 677 678 // If there are no more break points left remove the debug info for this 679 // function. 680 if (debug_info->GetBreakPointCount() == 0) { 681 RemoveDebugInfoAndClearFromShared(debug_info); 682 } 683 684 return; 685 } 686 node = node->next(); 687 } 688 } 689 690 691 // Clear out all the debug break code. This is ONLY supposed to be used when 692 // shutting down the debugger as it will leave the break point information in 693 // DebugInfo even though the code is patched back to the non break point state. 694 void Debug::ClearAllBreakPoints() { 695 for (DebugInfoListNode* node = debug_info_list_; node != NULL; 696 node = node->next()) { 697 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS); 698 !it.Done(); it.Next()) { 699 it.GetBreakLocation().ClearDebugBreak(); 700 } 701 } 702 // Remove all debug info. 703 while (debug_info_list_ != NULL) { 704 RemoveDebugInfoAndClearFromShared(debug_info_list_->debug_info()); 705 } 706 } 707 708 709 void Debug::FloodWithOneShot(Handle<JSFunction> function, 710 BreakLocatorType type) { 711 // Debug utility functions are not subject to debugging. 712 if (function->native_context() == *debug_context()) return; 713 714 if (!function->shared()->IsSubjectToDebugging()) { 715 // Builtin functions are not subject to stepping, but need to be 716 // deoptimized, because optimized code does not check for debug 717 // step in at call sites. 718 Deoptimizer::DeoptimizeFunction(*function); 719 return; 720 } 721 // Make sure the function is compiled and has set up the debug info. 722 Handle<SharedFunctionInfo> shared(function->shared()); 723 if (!EnsureDebugInfo(shared, function)) { 724 // Return if we failed to retrieve the debug info. 725 return; 726 } 727 728 // Flood the function with break points. 729 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 730 for (BreakLocation::Iterator it(debug_info, type); !it.Done(); it.Next()) { 731 it.GetBreakLocation().SetOneShot(); 732 } 733 } 734 735 736 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { 737 if (type == BreakUncaughtException) { 738 break_on_uncaught_exception_ = enable; 739 } else { 740 break_on_exception_ = enable; 741 } 742 } 743 744 745 bool Debug::IsBreakOnException(ExceptionBreakType type) { 746 if (type == BreakUncaughtException) { 747 return break_on_uncaught_exception_; 748 } else { 749 return break_on_exception_; 750 } 751 } 752 753 754 FrameSummary GetFirstFrameSummary(JavaScriptFrame* frame) { 755 List<FrameSummary> frames(FLAG_max_inlining_levels + 1); 756 frame->Summarize(&frames); 757 return frames.first(); 758 } 759 760 761 void Debug::PrepareStepIn(Handle<JSFunction> function) { 762 if (!is_active()) return; 763 if (last_step_action() < StepIn) return; 764 if (in_debug_scope()) return; 765 if (thread_local_.step_in_enabled_) { 766 FloodWithOneShot(function); 767 } 768 } 769 770 771 void Debug::PrepareStepOnThrow() { 772 if (!is_active()) return; 773 if (last_step_action() == StepNone) return; 774 if (in_debug_scope()) return; 775 776 ClearOneShot(); 777 778 // Iterate through the JavaScript stack looking for handlers. 779 JavaScriptFrameIterator it(isolate_); 780 while (!it.done()) { 781 JavaScriptFrame* frame = it.frame(); 782 int stack_slots = 0; // The computed stack slot count is not used. 783 if (frame->LookupExceptionHandlerInTable(&stack_slots, NULL) > 0) break; 784 it.Advance(); 785 } 786 787 // Find the closest Javascript frame we can flood with one-shots. 788 while (!it.done() && 789 !it.frame()->function()->shared()->IsSubjectToDebugging()) { 790 it.Advance(); 791 } 792 793 if (it.done()) return; // No suitable Javascript catch handler. 794 795 FloodWithOneShot(Handle<JSFunction>(it.frame()->function())); 796 } 797 798 799 void Debug::PrepareStep(StepAction step_action) { 800 HandleScope scope(isolate_); 801 802 DCHECK(in_debug_scope()); 803 804 // Get the frame where the execution has stopped and skip the debug frame if 805 // any. The debug frame will only be present if execution was stopped due to 806 // hitting a break point. In other situations (e.g. unhandled exception) the 807 // debug frame is not present. 808 StackFrame::Id frame_id = break_frame_id(); 809 // If there is no JavaScript stack don't do anything. 810 if (frame_id == StackFrame::NO_ID) return; 811 812 JavaScriptFrameIterator frames_it(isolate_, frame_id); 813 JavaScriptFrame* frame = frames_it.frame(); 814 815 feature_tracker()->Track(DebugFeatureTracker::kStepping); 816 817 // Remember this step action and count. 818 thread_local_.last_step_action_ = step_action; 819 STATIC_ASSERT(StepFrame > StepIn); 820 thread_local_.step_in_enabled_ = (step_action >= StepIn); 821 822 // If the function on the top frame is unresolved perform step out. This will 823 // be the case when calling unknown function and having the debugger stopped 824 // in an unhandled exception. 825 if (!frame->function()->IsJSFunction()) { 826 // Step out: Find the calling JavaScript frame and flood it with 827 // breakpoints. 828 frames_it.Advance(); 829 // Fill the function to return to with one-shot break points. 830 JSFunction* function = frames_it.frame()->function(); 831 FloodWithOneShot(Handle<JSFunction>(function)); 832 return; 833 } 834 835 // Get the debug info (create it if it does not exist). 836 FrameSummary summary = GetFirstFrameSummary(frame); 837 Handle<JSFunction> function(summary.function()); 838 Handle<SharedFunctionInfo> shared(function->shared()); 839 if (!EnsureDebugInfo(shared, function)) { 840 // Return if ensuring debug info failed. 841 return; 842 } 843 844 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 845 // Refresh frame summary if the code has been recompiled for debugging. 846 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); 847 848 // PC points to the instruction after the current one, possibly a break 849 // location as well. So the "- 1" to exclude it from the search. 850 Address call_pc = summary.pc() - 1; 851 BreakLocation location = BreakLocation::FromAddress(debug_info, call_pc); 852 853 // At a return statement we will step out either way. 854 if (location.IsReturn()) step_action = StepOut; 855 856 thread_local_.last_statement_position_ = 857 debug_info->code()->SourceStatementPosition(summary.pc()); 858 thread_local_.last_fp_ = frame->UnpaddedFP(); 859 860 switch (step_action) { 861 case StepNone: 862 UNREACHABLE(); 863 break; 864 case StepOut: 865 // Advance to caller frame. 866 frames_it.Advance(); 867 // Skip native and extension functions on the stack. 868 while (!frames_it.done() && 869 !frames_it.frame()->function()->shared()->IsSubjectToDebugging()) { 870 // Builtin functions are not subject to stepping, but need to be 871 // deoptimized to include checks for step-in at call sites. 872 Deoptimizer::DeoptimizeFunction(frames_it.frame()->function()); 873 frames_it.Advance(); 874 } 875 if (frames_it.done()) { 876 // Stepping out to the embedder. Disable step-in to avoid stepping into 877 // the next (unrelated) call that the embedder makes. 878 thread_local_.step_in_enabled_ = false; 879 } else { 880 // Fill the caller function to return to with one-shot break points. 881 Handle<JSFunction> caller_function(frames_it.frame()->function()); 882 FloodWithOneShot(caller_function); 883 thread_local_.target_fp_ = frames_it.frame()->UnpaddedFP(); 884 } 885 // Clear last position info. For stepping out it does not matter. 886 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; 887 thread_local_.last_fp_ = 0; 888 break; 889 case StepNext: 890 thread_local_.target_fp_ = frame->UnpaddedFP(); 891 FloodWithOneShot(function); 892 break; 893 case StepIn: 894 FloodWithOneShot(function); 895 break; 896 case StepFrame: 897 // No point in setting one-shot breaks at places where we are not about 898 // to leave the current frame. 899 FloodWithOneShot(function, CALLS_AND_RETURNS); 900 break; 901 } 902 } 903 904 905 // Simple function for returning the source positions for active break points. 906 Handle<Object> Debug::GetSourceBreakLocations( 907 Handle<SharedFunctionInfo> shared, 908 BreakPositionAlignment position_alignment) { 909 Isolate* isolate = shared->GetIsolate(); 910 Heap* heap = isolate->heap(); 911 if (!shared->HasDebugInfo()) { 912 return Handle<Object>(heap->undefined_value(), isolate); 913 } 914 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 915 if (debug_info->GetBreakPointCount() == 0) { 916 return Handle<Object>(heap->undefined_value(), isolate); 917 } 918 Handle<FixedArray> locations = 919 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); 920 int count = 0; 921 for (int i = 0; i < debug_info->break_points()->length(); ++i) { 922 if (!debug_info->break_points()->get(i)->IsUndefined()) { 923 BreakPointInfo* break_point_info = 924 BreakPointInfo::cast(debug_info->break_points()->get(i)); 925 int break_points = break_point_info->GetBreakPointCount(); 926 if (break_points == 0) continue; 927 Smi* position = NULL; 928 switch (position_alignment) { 929 case STATEMENT_ALIGNED: 930 position = Smi::FromInt(break_point_info->statement_position()); 931 break; 932 case BREAK_POSITION_ALIGNED: 933 position = Smi::FromInt(break_point_info->source_position()); 934 break; 935 } 936 for (int j = 0; j < break_points; ++j) locations->set(count++, position); 937 } 938 } 939 return locations; 940 } 941 942 943 void Debug::ClearStepping() { 944 // Clear the various stepping setup. 945 ClearOneShot(); 946 947 thread_local_.last_step_action_ = StepNone; 948 thread_local_.step_in_enabled_ = false; 949 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; 950 thread_local_.last_fp_ = 0; 951 thread_local_.target_fp_ = 0; 952 } 953 954 955 // Clears all the one-shot break points that are currently set. Normally this 956 // function is called each time a break point is hit as one shot break points 957 // are used to support stepping. 958 void Debug::ClearOneShot() { 959 // The current implementation just runs through all the breakpoints. When the 960 // last break point for a function is removed that function is automatically 961 // removed from the list. 962 for (DebugInfoListNode* node = debug_info_list_; node != NULL; 963 node = node->next()) { 964 for (BreakLocation::Iterator it(node->debug_info(), ALL_BREAK_LOCATIONS); 965 !it.Done(); it.Next()) { 966 it.GetBreakLocation().ClearOneShot(); 967 } 968 } 969 } 970 971 972 void Debug::EnableStepIn() { 973 STATIC_ASSERT(StepFrame > StepIn); 974 thread_local_.step_in_enabled_ = (last_step_action() >= StepIn); 975 } 976 977 978 bool MatchingCodeTargets(Code* target1, Code* target2) { 979 if (target1 == target2) return true; 980 if (target1->kind() != target2->kind()) return false; 981 return target1->is_handler() || target1->is_inline_cache_stub(); 982 } 983 984 985 // Count the number of calls before the current frame PC to find the 986 // corresponding PC in the newly recompiled code. 987 static Address ComputeNewPcForRedirect(Code* new_code, Code* old_code, 988 Address old_pc) { 989 DCHECK_EQ(old_code->kind(), Code::FUNCTION); 990 DCHECK_EQ(new_code->kind(), Code::FUNCTION); 991 DCHECK(new_code->has_debug_break_slots()); 992 static const int mask = RelocInfo::kCodeTargetMask; 993 994 // Find the target of the current call. 995 Code* target = NULL; 996 intptr_t delta = 0; 997 for (RelocIterator it(old_code, mask); !it.done(); it.next()) { 998 RelocInfo* rinfo = it.rinfo(); 999 Address current_pc = rinfo->pc(); 1000 // The frame PC is behind the call instruction by the call instruction size. 1001 if (current_pc > old_pc) break; 1002 delta = old_pc - current_pc; 1003 target = Code::GetCodeFromTargetAddress(rinfo->target_address()); 1004 } 1005 1006 // Count the number of calls to the same target before the current call. 1007 int index = 0; 1008 for (RelocIterator it(old_code, mask); !it.done(); it.next()) { 1009 RelocInfo* rinfo = it.rinfo(); 1010 Address current_pc = rinfo->pc(); 1011 if (current_pc > old_pc) break; 1012 Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address()); 1013 if (MatchingCodeTargets(target, current)) index++; 1014 } 1015 1016 DCHECK(index > 0); 1017 1018 // Repeat the count on the new code to find corresponding call. 1019 for (RelocIterator it(new_code, mask); !it.done(); it.next()) { 1020 RelocInfo* rinfo = it.rinfo(); 1021 Code* current = Code::GetCodeFromTargetAddress(rinfo->target_address()); 1022 if (MatchingCodeTargets(target, current)) index--; 1023 if (index == 0) return rinfo->pc() + delta; 1024 } 1025 1026 UNREACHABLE(); 1027 return NULL; 1028 } 1029 1030 1031 // Count the number of continuations at which the current pc offset is at. 1032 static int ComputeContinuationIndexFromPcOffset(Code* code, int pc_offset) { 1033 DCHECK_EQ(code->kind(), Code::FUNCTION); 1034 Address pc = code->instruction_start() + pc_offset; 1035 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION); 1036 int index = 0; 1037 for (RelocIterator it(code, mask); !it.done(); it.next()) { 1038 index++; 1039 RelocInfo* rinfo = it.rinfo(); 1040 Address current_pc = rinfo->pc(); 1041 if (current_pc == pc) break; 1042 DCHECK(current_pc < pc); 1043 } 1044 return index; 1045 } 1046 1047 1048 // Find the pc offset for the given continuation index. 1049 static int ComputePcOffsetFromContinuationIndex(Code* code, int index) { 1050 DCHECK_EQ(code->kind(), Code::FUNCTION); 1051 DCHECK(code->has_debug_break_slots()); 1052 int mask = RelocInfo::ModeMask(RelocInfo::GENERATOR_CONTINUATION); 1053 RelocIterator it(code, mask); 1054 for (int i = 1; i < index; i++) it.next(); 1055 return static_cast<int>(it.rinfo()->pc() - code->instruction_start()); 1056 } 1057 1058 1059 class RedirectActiveFunctions : public ThreadVisitor { 1060 public: 1061 explicit RedirectActiveFunctions(SharedFunctionInfo* shared) 1062 : shared_(shared) { 1063 DCHECK(shared->HasDebugCode()); 1064 } 1065 1066 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { 1067 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { 1068 JavaScriptFrame* frame = it.frame(); 1069 JSFunction* function = frame->function(); 1070 if (frame->is_optimized()) continue; 1071 if (!function->Inlines(shared_)) continue; 1072 1073 Code* frame_code = frame->LookupCode(); 1074 DCHECK(frame_code->kind() == Code::FUNCTION); 1075 if (frame_code->has_debug_break_slots()) continue; 1076 1077 Code* new_code = function->shared()->code(); 1078 Address old_pc = frame->pc(); 1079 Address new_pc = ComputeNewPcForRedirect(new_code, frame_code, old_pc); 1080 1081 if (FLAG_trace_deopt) { 1082 PrintF("Replacing pc for debugging: %08" V8PRIxPTR " => %08" V8PRIxPTR 1083 "\n", 1084 reinterpret_cast<intptr_t>(old_pc), 1085 reinterpret_cast<intptr_t>(new_pc)); 1086 } 1087 1088 if (FLAG_enable_embedded_constant_pool) { 1089 // Update constant pool pointer for new code. 1090 frame->set_constant_pool(new_code->constant_pool()); 1091 } 1092 1093 // Patch the return address to return into the code with 1094 // debug break slots. 1095 frame->set_pc(new_pc); 1096 } 1097 } 1098 1099 private: 1100 SharedFunctionInfo* shared_; 1101 DisallowHeapAllocation no_gc_; 1102 }; 1103 1104 1105 bool Debug::PrepareFunctionForBreakPoints(Handle<SharedFunctionInfo> shared) { 1106 DCHECK(shared->is_compiled()); 1107 1108 if (isolate_->concurrent_recompilation_enabled()) { 1109 isolate_->optimizing_compile_dispatcher()->Flush(); 1110 } 1111 1112 List<Handle<JSFunction> > functions; 1113 List<Handle<JSGeneratorObject> > suspended_generators; 1114 1115 // Flush all optimized code maps. Note that the below heap iteration does not 1116 // cover this, because the given function might have been inlined into code 1117 // for which no JSFunction exists. 1118 { 1119 SharedFunctionInfo::Iterator iterator(isolate_); 1120 while (SharedFunctionInfo* shared = iterator.Next()) { 1121 if (!shared->OptimizedCodeMapIsCleared()) { 1122 shared->ClearOptimizedCodeMap(); 1123 } 1124 } 1125 } 1126 1127 // Make sure we abort incremental marking. 1128 isolate_->heap()->CollectAllGarbage(Heap::kMakeHeapIterableMask, 1129 "prepare for break points"); 1130 1131 { 1132 HeapIterator iterator(isolate_->heap()); 1133 HeapObject* obj; 1134 bool include_generators = shared->is_generator(); 1135 1136 while ((obj = iterator.next())) { 1137 if (obj->IsJSFunction()) { 1138 JSFunction* function = JSFunction::cast(obj); 1139 if (!function->Inlines(*shared)) continue; 1140 if (function->code()->kind() == Code::OPTIMIZED_FUNCTION) { 1141 Deoptimizer::DeoptimizeFunction(function); 1142 } 1143 if (function->shared() == *shared) functions.Add(handle(function)); 1144 } else if (include_generators && obj->IsJSGeneratorObject()) { 1145 JSGeneratorObject* generator_obj = JSGeneratorObject::cast(obj); 1146 if (!generator_obj->is_suspended()) continue; 1147 JSFunction* function = generator_obj->function(); 1148 if (!function->Inlines(*shared)) continue; 1149 int pc_offset = generator_obj->continuation(); 1150 int index = 1151 ComputeContinuationIndexFromPcOffset(function->code(), pc_offset); 1152 generator_obj->set_continuation(index); 1153 suspended_generators.Add(handle(generator_obj)); 1154 } 1155 } 1156 } 1157 1158 if (!shared->HasDebugCode()) { 1159 DCHECK(functions.length() > 0); 1160 if (!Compiler::CompileDebugCode(functions.first())) return false; 1161 } 1162 1163 for (Handle<JSFunction> const function : functions) { 1164 function->ReplaceCode(shared->code()); 1165 } 1166 1167 for (Handle<JSGeneratorObject> const generator_obj : suspended_generators) { 1168 int index = generator_obj->continuation(); 1169 int pc_offset = ComputePcOffsetFromContinuationIndex(shared->code(), index); 1170 generator_obj->set_continuation(pc_offset); 1171 } 1172 1173 // Update PCs on the stack to point to recompiled code. 1174 RedirectActiveFunctions redirect_visitor(*shared); 1175 redirect_visitor.VisitThread(isolate_, isolate_->thread_local_top()); 1176 isolate_->thread_manager()->IterateArchivedThreads(&redirect_visitor); 1177 1178 return true; 1179 } 1180 1181 1182 class SharedFunctionInfoFinder { 1183 public: 1184 explicit SharedFunctionInfoFinder(int target_position) 1185 : current_candidate_(NULL), 1186 current_candidate_closure_(NULL), 1187 current_start_position_(RelocInfo::kNoPosition), 1188 target_position_(target_position) {} 1189 1190 void NewCandidate(SharedFunctionInfo* shared, JSFunction* closure = NULL) { 1191 if (!shared->IsSubjectToDebugging()) return; 1192 int start_position = shared->function_token_position(); 1193 if (start_position == RelocInfo::kNoPosition) { 1194 start_position = shared->start_position(); 1195 } 1196 1197 if (start_position > target_position_) return; 1198 if (target_position_ > shared->end_position()) return; 1199 1200 if (current_candidate_ != NULL) { 1201 if (current_start_position_ == start_position && 1202 shared->end_position() == current_candidate_->end_position()) { 1203 // If we already have a matching closure, do not throw it away. 1204 if (current_candidate_closure_ != NULL && closure == NULL) return; 1205 // If a top-level function contains only one function 1206 // declaration the source for the top-level and the function 1207 // is the same. In that case prefer the non top-level function. 1208 if (!current_candidate_->is_toplevel() && shared->is_toplevel()) return; 1209 } else if (start_position < current_start_position_ || 1210 current_candidate_->end_position() < shared->end_position()) { 1211 return; 1212 } 1213 } 1214 1215 current_start_position_ = start_position; 1216 current_candidate_ = shared; 1217 current_candidate_closure_ = closure; 1218 } 1219 1220 SharedFunctionInfo* Result() { return current_candidate_; } 1221 1222 JSFunction* ResultClosure() { return current_candidate_closure_; } 1223 1224 private: 1225 SharedFunctionInfo* current_candidate_; 1226 JSFunction* current_candidate_closure_; 1227 int current_start_position_; 1228 int target_position_; 1229 DisallowHeapAllocation no_gc_; 1230 }; 1231 1232 1233 // We need to find a SFI for a literal that may not yet have been compiled yet, 1234 // and there may not be a JSFunction referencing it. Find the SFI closest to 1235 // the given position, compile it to reveal possible inner SFIs and repeat. 1236 // While we are at this, also ensure code with debug break slots so that we do 1237 // not have to compile a SFI without JSFunction, which is paifu for those that 1238 // cannot be compiled without context (need to find outer compilable SFI etc.) 1239 Handle<Object> Debug::FindSharedFunctionInfoInScript(Handle<Script> script, 1240 int position) { 1241 for (int iteration = 0;; iteration++) { 1242 // Go through all shared function infos associated with this script to 1243 // find the inner most function containing this position. 1244 // If there is no shared function info for this script at all, there is 1245 // no point in looking for it by walking the heap. 1246 if (!script->shared_function_infos()->IsWeakFixedArray()) break; 1247 1248 SharedFunctionInfo* shared; 1249 { 1250 SharedFunctionInfoFinder finder(position); 1251 WeakFixedArray::Iterator iterator(script->shared_function_infos()); 1252 SharedFunctionInfo* candidate; 1253 while ((candidate = iterator.Next<SharedFunctionInfo>())) { 1254 finder.NewCandidate(candidate); 1255 } 1256 shared = finder.Result(); 1257 if (shared == NULL) break; 1258 // We found it if it's already compiled and has debug code. 1259 if (shared->HasDebugCode()) { 1260 Handle<SharedFunctionInfo> shared_handle(shared); 1261 // If the iteration count is larger than 1, we had to compile the outer 1262 // function in order to create this shared function info. So there can 1263 // be no JSFunction referencing it. We can anticipate creating a debug 1264 // info while bypassing PrepareFunctionForBreakpoints. 1265 if (iteration > 1) { 1266 AllowHeapAllocation allow_before_return; 1267 CreateDebugInfo(shared_handle); 1268 } 1269 return shared_handle; 1270 } 1271 } 1272 // If not, compile to reveal inner functions, if possible. 1273 if (shared->allows_lazy_compilation_without_context()) { 1274 HandleScope scope(isolate_); 1275 if (!Compiler::CompileDebugCode(handle(shared))) break; 1276 continue; 1277 } 1278 1279 // If not possible, comb the heap for the best suitable compile target. 1280 JSFunction* closure; 1281 { 1282 HeapIterator it(isolate_->heap()); 1283 SharedFunctionInfoFinder finder(position); 1284 while (HeapObject* object = it.next()) { 1285 JSFunction* candidate_closure = NULL; 1286 SharedFunctionInfo* candidate = NULL; 1287 if (object->IsJSFunction()) { 1288 candidate_closure = JSFunction::cast(object); 1289 candidate = candidate_closure->shared(); 1290 } else if (object->IsSharedFunctionInfo()) { 1291 candidate = SharedFunctionInfo::cast(object); 1292 if (!candidate->allows_lazy_compilation_without_context()) continue; 1293 } else { 1294 continue; 1295 } 1296 if (candidate->script() == *script) { 1297 finder.NewCandidate(candidate, candidate_closure); 1298 } 1299 } 1300 closure = finder.ResultClosure(); 1301 shared = finder.Result(); 1302 } 1303 if (shared == NULL) break; 1304 HandleScope scope(isolate_); 1305 if (closure == NULL) { 1306 if (!Compiler::CompileDebugCode(handle(shared))) break; 1307 } else { 1308 if (!Compiler::CompileDebugCode(handle(closure))) break; 1309 } 1310 } 1311 return isolate_->factory()->undefined_value(); 1312 } 1313 1314 1315 // Ensures the debug information is present for shared. 1316 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, 1317 Handle<JSFunction> function) { 1318 if (!shared->IsSubjectToDebugging()) return false; 1319 1320 // Return if we already have the debug info for shared. 1321 if (shared->HasDebugInfo()) return true; 1322 1323 if (function.is_null()) { 1324 DCHECK(shared->HasDebugCode()); 1325 } else if (!Compiler::Compile(function, CLEAR_EXCEPTION)) { 1326 return false; 1327 } 1328 1329 if (!PrepareFunctionForBreakPoints(shared)) return false; 1330 1331 CreateDebugInfo(shared); 1332 1333 return true; 1334 } 1335 1336 1337 void Debug::CreateDebugInfo(Handle<SharedFunctionInfo> shared) { 1338 // Create the debug info object. 1339 DCHECK(shared->HasDebugCode()); 1340 Handle<DebugInfo> debug_info = isolate_->factory()->NewDebugInfo(shared); 1341 1342 // Add debug info to the list. 1343 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); 1344 node->set_next(debug_info_list_); 1345 debug_info_list_ = node; 1346 } 1347 1348 1349 void Debug::RemoveDebugInfoAndClearFromShared(Handle<DebugInfo> debug_info) { 1350 HandleScope scope(isolate_); 1351 Handle<SharedFunctionInfo> shared(debug_info->shared()); 1352 1353 DCHECK_NOT_NULL(debug_info_list_); 1354 // Run through the debug info objects to find this one and remove it. 1355 DebugInfoListNode* prev = NULL; 1356 DebugInfoListNode* current = debug_info_list_; 1357 while (current != NULL) { 1358 if (current->debug_info().is_identical_to(debug_info)) { 1359 // Unlink from list. If prev is NULL we are looking at the first element. 1360 if (prev == NULL) { 1361 debug_info_list_ = current->next(); 1362 } else { 1363 prev->set_next(current->next()); 1364 } 1365 delete current; 1366 shared->set_debug_info(isolate_->heap()->undefined_value()); 1367 return; 1368 } 1369 // Move to next in list. 1370 prev = current; 1371 current = current->next(); 1372 } 1373 1374 UNREACHABLE(); 1375 } 1376 1377 1378 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { 1379 after_break_target_ = NULL; 1380 1381 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job. 1382 1383 // Continue just after the slot. 1384 after_break_target_ = frame->pc(); 1385 } 1386 1387 1388 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { 1389 HandleScope scope(isolate_); 1390 1391 // Get the executing function in which the debug break occurred. 1392 Handle<JSFunction> function(JSFunction::cast(frame->function())); 1393 Handle<SharedFunctionInfo> shared(function->shared()); 1394 1395 // With no debug info there are no break points, so we can't be at a return. 1396 if (!shared->HasDebugInfo()) return false; 1397 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 1398 Handle<Code> code(debug_info->code()); 1399 #ifdef DEBUG 1400 // Get the code which is actually executing. 1401 Handle<Code> frame_code(frame->LookupCode()); 1402 DCHECK(frame_code.is_identical_to(code)); 1403 #endif 1404 1405 // Find the reloc info matching the start of the debug break slot. 1406 Address slot_pc = frame->pc() - Assembler::kDebugBreakSlotLength; 1407 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT_AT_RETURN); 1408 for (RelocIterator it(*code, mask); !it.done(); it.next()) { 1409 if (it.rinfo()->pc() == slot_pc) return true; 1410 } 1411 return false; 1412 } 1413 1414 1415 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, 1416 LiveEdit::FrameDropMode mode) { 1417 if (mode != LiveEdit::CURRENTLY_SET_MODE) { 1418 thread_local_.frame_drop_mode_ = mode; 1419 } 1420 thread_local_.break_frame_id_ = new_break_frame_id; 1421 } 1422 1423 1424 bool Debug::IsDebugGlobal(JSGlobalObject* global) { 1425 return is_loaded() && global == debug_context()->global_object(); 1426 } 1427 1428 1429 void Debug::ClearMirrorCache() { 1430 PostponeInterruptsScope postpone(isolate_); 1431 HandleScope scope(isolate_); 1432 CallFunction("ClearMirrorCache", 0, NULL); 1433 } 1434 1435 1436 Handle<FixedArray> Debug::GetLoadedScripts() { 1437 isolate_->heap()->CollectAllGarbage(); 1438 Factory* factory = isolate_->factory(); 1439 if (!factory->script_list()->IsWeakFixedArray()) { 1440 return factory->empty_fixed_array(); 1441 } 1442 Handle<WeakFixedArray> array = 1443 Handle<WeakFixedArray>::cast(factory->script_list()); 1444 Handle<FixedArray> results = factory->NewFixedArray(array->Length()); 1445 int length = 0; 1446 { 1447 Script::Iterator iterator(isolate_); 1448 Script* script; 1449 while ((script = iterator.Next())) { 1450 if (script->HasValidSource()) results->set(length++, script); 1451 } 1452 } 1453 results->Shrink(length); 1454 return results; 1455 } 1456 1457 1458 void Debug::GetStepinPositions(JavaScriptFrame* frame, StackFrame::Id frame_id, 1459 List<int>* results_out) { 1460 FrameSummary summary = GetFirstFrameSummary(frame); 1461 1462 Handle<JSFunction> fun = Handle<JSFunction>(summary.function()); 1463 Handle<SharedFunctionInfo> shared = Handle<SharedFunctionInfo>(fun->shared()); 1464 1465 if (!EnsureDebugInfo(shared, fun)) return; 1466 1467 Handle<DebugInfo> debug_info(shared->GetDebugInfo()); 1468 // Refresh frame summary if the code has been recompiled for debugging. 1469 if (shared->code() != *summary.code()) summary = GetFirstFrameSummary(frame); 1470 1471 // Find range of break points starting from the break point where execution 1472 // has stopped. 1473 Address call_pc = summary.pc() - 1; 1474 List<BreakLocation> locations; 1475 BreakLocation::FromAddressSameStatement(debug_info, call_pc, &locations); 1476 1477 for (BreakLocation location : locations) { 1478 if (location.pc() <= summary.pc()) { 1479 // The break point is near our pc. Could be a step-in possibility, 1480 // that is currently taken by active debugger call. 1481 if (break_frame_id() == StackFrame::NO_ID) { 1482 continue; // We are not stepping. 1483 } else { 1484 JavaScriptFrameIterator frame_it(isolate_, break_frame_id()); 1485 // If our frame is a top frame and we are stepping, we can do step-in 1486 // at this place. 1487 if (frame_it.frame()->id() != frame_id) continue; 1488 } 1489 } 1490 if (location.IsCall()) results_out->Add(location.position()); 1491 } 1492 } 1493 1494 1495 void Debug::RecordEvalCaller(Handle<Script> script) { 1496 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL); 1497 // For eval scripts add information on the function from which eval was 1498 // called. 1499 StackTraceFrameIterator it(script->GetIsolate()); 1500 if (!it.done()) { 1501 script->set_eval_from_shared(it.frame()->function()->shared()); 1502 Code* code = it.frame()->LookupCode(); 1503 int offset = static_cast<int>( 1504 it.frame()->pc() - code->instruction_start()); 1505 script->set_eval_from_instructions_offset(offset); 1506 } 1507 } 1508 1509 1510 MaybeHandle<Object> Debug::MakeExecutionState() { 1511 // Create the execution state object. 1512 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) }; 1513 return CallFunction("MakeExecutionState", arraysize(argv), argv); 1514 } 1515 1516 1517 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) { 1518 // Create the new break event object. 1519 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()), 1520 break_points_hit }; 1521 return CallFunction("MakeBreakEvent", arraysize(argv), argv); 1522 } 1523 1524 1525 MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception, 1526 bool uncaught, 1527 Handle<Object> promise) { 1528 // Create the new exception event object. 1529 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()), 1530 exception, 1531 isolate_->factory()->ToBoolean(uncaught), 1532 promise }; 1533 return CallFunction("MakeExceptionEvent", arraysize(argv), argv); 1534 } 1535 1536 1537 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script, 1538 v8::DebugEvent type) { 1539 // Create the compile event object. 1540 Handle<Object> script_wrapper = Script::GetWrapper(script); 1541 Handle<Object> argv[] = { script_wrapper, 1542 isolate_->factory()->NewNumberFromInt(type) }; 1543 return CallFunction("MakeCompileEvent", arraysize(argv), argv); 1544 } 1545 1546 1547 MaybeHandle<Object> Debug::MakePromiseEvent(Handle<JSObject> event_data) { 1548 // Create the promise event object. 1549 Handle<Object> argv[] = { event_data }; 1550 return CallFunction("MakePromiseEvent", arraysize(argv), argv); 1551 } 1552 1553 1554 MaybeHandle<Object> Debug::MakeAsyncTaskEvent(Handle<JSObject> task_event) { 1555 // Create the async task event object. 1556 Handle<Object> argv[] = { task_event }; 1557 return CallFunction("MakeAsyncTaskEvent", arraysize(argv), argv); 1558 } 1559 1560 1561 void Debug::OnThrow(Handle<Object> exception) { 1562 if (in_debug_scope() || ignore_events()) return; 1563 PrepareStepOnThrow(); 1564 // Temporarily clear any scheduled_exception to allow evaluating 1565 // JavaScript from the debug event handler. 1566 HandleScope scope(isolate_); 1567 Handle<Object> scheduled_exception; 1568 if (isolate_->has_scheduled_exception()) { 1569 scheduled_exception = handle(isolate_->scheduled_exception(), isolate_); 1570 isolate_->clear_scheduled_exception(); 1571 } 1572 OnException(exception, isolate_->GetPromiseOnStackOnThrow()); 1573 if (!scheduled_exception.is_null()) { 1574 isolate_->thread_local_top()->scheduled_exception_ = *scheduled_exception; 1575 } 1576 } 1577 1578 1579 void Debug::OnPromiseReject(Handle<JSObject> promise, Handle<Object> value) { 1580 if (in_debug_scope() || ignore_events()) return; 1581 HandleScope scope(isolate_); 1582 // Check whether the promise has been marked as having triggered a message. 1583 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); 1584 if (JSReceiver::GetDataProperty(promise, key)->IsUndefined()) { 1585 OnException(value, promise); 1586 } 1587 } 1588 1589 1590 MaybeHandle<Object> Debug::PromiseHasUserDefinedRejectHandler( 1591 Handle<JSObject> promise) { 1592 Handle<JSFunction> fun = isolate_->promise_has_user_defined_reject_handler(); 1593 return Execution::Call(isolate_, fun, promise, 0, NULL); 1594 } 1595 1596 1597 void Debug::OnException(Handle<Object> exception, Handle<Object> promise) { 1598 // In our prediction, try-finally is not considered to catch. 1599 Isolate::CatchType catch_type = isolate_->PredictExceptionCatcher(); 1600 bool uncaught = (catch_type == Isolate::NOT_CAUGHT); 1601 if (promise->IsJSObject()) { 1602 Handle<JSObject> jspromise = Handle<JSObject>::cast(promise); 1603 // Mark the promise as already having triggered a message. 1604 Handle<Symbol> key = isolate_->factory()->promise_debug_marker_symbol(); 1605 JSObject::SetProperty(jspromise, key, key, STRICT).Assert(); 1606 // Check whether the promise reject is considered an uncaught exception. 1607 Handle<Object> has_reject_handler; 1608 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1609 isolate_, has_reject_handler, 1610 PromiseHasUserDefinedRejectHandler(jspromise), /* void */); 1611 uncaught = has_reject_handler->IsFalse(); 1612 } 1613 // Bail out if exception breaks are not active 1614 if (uncaught) { 1615 // Uncaught exceptions are reported by either flags. 1616 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; 1617 } else { 1618 // Caught exceptions are reported is activated. 1619 if (!break_on_exception_) return; 1620 } 1621 1622 DebugScope debug_scope(this); 1623 if (debug_scope.failed()) return; 1624 1625 // Create the event data object. 1626 Handle<Object> event_data; 1627 // Bail out and don't call debugger if exception. 1628 if (!MakeExceptionEvent( 1629 exception, uncaught, promise).ToHandle(&event_data)) { 1630 return; 1631 } 1632 1633 // Process debug event. 1634 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); 1635 // Return to continue execution from where the exception was thrown. 1636 } 1637 1638 1639 void Debug::OnDebugBreak(Handle<Object> break_points_hit, 1640 bool auto_continue) { 1641 // The caller provided for DebugScope. 1642 AssertDebugContext(); 1643 // Bail out if there is no listener for this event 1644 if (ignore_events()) return; 1645 1646 HandleScope scope(isolate_); 1647 // Create the event data object. 1648 Handle<Object> event_data; 1649 // Bail out and don't call debugger if exception. 1650 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; 1651 1652 // Process debug event. 1653 ProcessDebugEvent(v8::Break, 1654 Handle<JSObject>::cast(event_data), 1655 auto_continue); 1656 } 1657 1658 1659 void Debug::OnCompileError(Handle<Script> script) { 1660 ProcessCompileEvent(v8::CompileError, script); 1661 } 1662 1663 1664 void Debug::OnBeforeCompile(Handle<Script> script) { 1665 ProcessCompileEvent(v8::BeforeCompile, script); 1666 } 1667 1668 1669 // Handle debugger actions when a new script is compiled. 1670 void Debug::OnAfterCompile(Handle<Script> script) { 1671 ProcessCompileEvent(v8::AfterCompile, script); 1672 } 1673 1674 1675 void Debug::OnPromiseEvent(Handle<JSObject> data) { 1676 if (in_debug_scope() || ignore_events()) return; 1677 1678 HandleScope scope(isolate_); 1679 DebugScope debug_scope(this); 1680 if (debug_scope.failed()) return; 1681 1682 // Create the script collected state object. 1683 Handle<Object> event_data; 1684 // Bail out and don't call debugger if exception. 1685 if (!MakePromiseEvent(data).ToHandle(&event_data)) return; 1686 1687 // Process debug event. 1688 ProcessDebugEvent(v8::PromiseEvent, 1689 Handle<JSObject>::cast(event_data), 1690 true); 1691 } 1692 1693 1694 void Debug::OnAsyncTaskEvent(Handle<JSObject> data) { 1695 if (in_debug_scope() || ignore_events()) return; 1696 1697 HandleScope scope(isolate_); 1698 DebugScope debug_scope(this); 1699 if (debug_scope.failed()) return; 1700 1701 // Create the script collected state object. 1702 Handle<Object> event_data; 1703 // Bail out and don't call debugger if exception. 1704 if (!MakeAsyncTaskEvent(data).ToHandle(&event_data)) return; 1705 1706 // Process debug event. 1707 ProcessDebugEvent(v8::AsyncTaskEvent, 1708 Handle<JSObject>::cast(event_data), 1709 true); 1710 } 1711 1712 1713 void Debug::ProcessDebugEvent(v8::DebugEvent event, 1714 Handle<JSObject> event_data, 1715 bool auto_continue) { 1716 HandleScope scope(isolate_); 1717 1718 // Create the execution state. 1719 Handle<Object> exec_state; 1720 // Bail out and don't call debugger if exception. 1721 if (!MakeExecutionState().ToHandle(&exec_state)) return; 1722 1723 // First notify the message handler if any. 1724 if (message_handler_ != NULL) { 1725 NotifyMessageHandler(event, 1726 Handle<JSObject>::cast(exec_state), 1727 event_data, 1728 auto_continue); 1729 } 1730 // Notify registered debug event listener. This can be either a C or 1731 // a JavaScript function. Don't call event listener for v8::Break 1732 // here, if it's only a debug command -- they will be processed later. 1733 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) { 1734 CallEventCallback(event, exec_state, event_data, NULL); 1735 } 1736 } 1737 1738 1739 void Debug::CallEventCallback(v8::DebugEvent event, 1740 Handle<Object> exec_state, 1741 Handle<Object> event_data, 1742 v8::Debug::ClientData* client_data) { 1743 // Prevent other interrupts from triggering, for example API callbacks, 1744 // while dispatching event listners. 1745 PostponeInterruptsScope postpone(isolate_); 1746 bool previous = in_debug_event_listener_; 1747 in_debug_event_listener_ = true; 1748 if (event_listener_->IsForeign()) { 1749 // Invoke the C debug event listener. 1750 v8::Debug::EventCallback callback = 1751 FUNCTION_CAST<v8::Debug::EventCallback>( 1752 Handle<Foreign>::cast(event_listener_)->foreign_address()); 1753 EventDetailsImpl event_details(event, 1754 Handle<JSObject>::cast(exec_state), 1755 Handle<JSObject>::cast(event_data), 1756 event_listener_data_, 1757 client_data); 1758 callback(event_details); 1759 DCHECK(!isolate_->has_scheduled_exception()); 1760 } else { 1761 // Invoke the JavaScript debug event listener. 1762 DCHECK(event_listener_->IsJSFunction()); 1763 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), 1764 exec_state, 1765 event_data, 1766 event_listener_data_ }; 1767 Handle<JSReceiver> global(isolate_->global_proxy()); 1768 Execution::TryCall(isolate_, Handle<JSFunction>::cast(event_listener_), 1769 global, arraysize(argv), argv); 1770 } 1771 in_debug_event_listener_ = previous; 1772 } 1773 1774 1775 void Debug::ProcessCompileEvent(v8::DebugEvent event, Handle<Script> script) { 1776 if (ignore_events()) return; 1777 SuppressDebug while_processing(this); 1778 1779 bool in_nested_debug_scope = in_debug_scope(); 1780 HandleScope scope(isolate_); 1781 DebugScope debug_scope(this); 1782 if (debug_scope.failed()) return; 1783 1784 if (event == v8::AfterCompile) { 1785 // If debugging there might be script break points registered for this 1786 // script. Make sure that these break points are set. 1787 Handle<Object> argv[] = {Script::GetWrapper(script)}; 1788 if (CallFunction("UpdateScriptBreakPoints", arraysize(argv), argv) 1789 .is_null()) { 1790 return; 1791 } 1792 } 1793 1794 // Create the compile state object. 1795 Handle<Object> event_data; 1796 // Bail out and don't call debugger if exception. 1797 if (!MakeCompileEvent(script, event).ToHandle(&event_data)) return; 1798 1799 // Don't call NotifyMessageHandler if already in debug scope to avoid running 1800 // nested command loop. 1801 if (in_nested_debug_scope) { 1802 if (event_listener_.is_null()) return; 1803 // Create the execution state. 1804 Handle<Object> exec_state; 1805 // Bail out and don't call debugger if exception. 1806 if (!MakeExecutionState().ToHandle(&exec_state)) return; 1807 1808 CallEventCallback(event, exec_state, event_data, NULL); 1809 } else { 1810 // Process debug event. 1811 ProcessDebugEvent(event, Handle<JSObject>::cast(event_data), true); 1812 } 1813 } 1814 1815 1816 Handle<Context> Debug::GetDebugContext() { 1817 if (!is_loaded()) return Handle<Context>(); 1818 DebugScope debug_scope(this); 1819 if (debug_scope.failed()) return Handle<Context>(); 1820 // The global handle may be destroyed soon after. Return it reboxed. 1821 return handle(*debug_context(), isolate_); 1822 } 1823 1824 1825 void Debug::NotifyMessageHandler(v8::DebugEvent event, 1826 Handle<JSObject> exec_state, 1827 Handle<JSObject> event_data, 1828 bool auto_continue) { 1829 // Prevent other interrupts from triggering, for example API callbacks, 1830 // while dispatching message handler callbacks. 1831 PostponeInterruptsScope no_interrupts(isolate_); 1832 DCHECK(is_active_); 1833 HandleScope scope(isolate_); 1834 // Process the individual events. 1835 bool sendEventMessage = false; 1836 switch (event) { 1837 case v8::Break: 1838 sendEventMessage = !auto_continue; 1839 break; 1840 case v8::NewFunction: 1841 case v8::BeforeCompile: 1842 case v8::CompileError: 1843 case v8::PromiseEvent: 1844 case v8::AsyncTaskEvent: 1845 break; 1846 case v8::Exception: 1847 case v8::AfterCompile: 1848 sendEventMessage = true; 1849 break; 1850 } 1851 1852 // The debug command interrupt flag might have been set when the command was 1853 // added. It should be enough to clear the flag only once while we are in the 1854 // debugger. 1855 DCHECK(in_debug_scope()); 1856 isolate_->stack_guard()->ClearDebugCommand(); 1857 1858 // Notify the debugger that a debug event has occurred unless auto continue is 1859 // active in which case no event is send. 1860 if (sendEventMessage) { 1861 MessageImpl message = MessageImpl::NewEvent( 1862 event, 1863 auto_continue, 1864 Handle<JSObject>::cast(exec_state), 1865 Handle<JSObject>::cast(event_data)); 1866 InvokeMessageHandler(message); 1867 } 1868 1869 // If auto continue don't make the event cause a break, but process messages 1870 // in the queue if any. For script collected events don't even process 1871 // messages in the queue as the execution state might not be what is expected 1872 // by the client. 1873 if (auto_continue && !has_commands()) return; 1874 1875 // DebugCommandProcessor goes here. 1876 bool running = auto_continue; 1877 1878 Handle<Object> cmd_processor_ctor = Object::GetProperty( 1879 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked(); 1880 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) }; 1881 Handle<Object> cmd_processor = Execution::Call( 1882 isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked(); 1883 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast( 1884 Object::GetProperty( 1885 isolate_, cmd_processor, "processDebugRequest").ToHandleChecked()); 1886 Handle<Object> is_running = Object::GetProperty( 1887 isolate_, cmd_processor, "isRunning").ToHandleChecked(); 1888 1889 // Process requests from the debugger. 1890 do { 1891 // Wait for new command in the queue. 1892 command_received_.Wait(); 1893 1894 // Get the command from the queue. 1895 CommandMessage command = command_queue_.Get(); 1896 isolate_->logger()->DebugTag( 1897 "Got request from command queue, in interactive loop."); 1898 if (!is_active()) { 1899 // Delete command text and user data. 1900 command.Dispose(); 1901 return; 1902 } 1903 1904 Vector<const uc16> command_text( 1905 const_cast<const uc16*>(command.text().start()), 1906 command.text().length()); 1907 Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte( 1908 command_text).ToHandleChecked(); 1909 Handle<Object> request_args[] = { request_text }; 1910 Handle<Object> answer_value; 1911 Handle<String> answer; 1912 MaybeHandle<Object> maybe_exception; 1913 MaybeHandle<Object> maybe_result = 1914 Execution::TryCall(isolate_, process_debug_request, cmd_processor, 1, 1915 request_args, &maybe_exception); 1916 1917 if (maybe_result.ToHandle(&answer_value)) { 1918 if (answer_value->IsUndefined()) { 1919 answer = isolate_->factory()->empty_string(); 1920 } else { 1921 answer = Handle<String>::cast(answer_value); 1922 } 1923 1924 // Log the JSON request/response. 1925 if (FLAG_trace_debug_json) { 1926 PrintF("%s\n", request_text->ToCString().get()); 1927 PrintF("%s\n", answer->ToCString().get()); 1928 } 1929 1930 Handle<Object> is_running_args[] = { answer }; 1931 maybe_result = Execution::Call( 1932 isolate_, is_running, cmd_processor, 1, is_running_args); 1933 Handle<Object> result; 1934 if (!maybe_result.ToHandle(&result)) break; 1935 running = result->IsTrue(); 1936 } else { 1937 Handle<Object> exception; 1938 if (!maybe_exception.ToHandle(&exception)) break; 1939 Handle<Object> result; 1940 if (!Object::ToString(isolate_, exception).ToHandle(&result)) break; 1941 answer = Handle<String>::cast(result); 1942 } 1943 1944 // Return the result. 1945 MessageImpl message = MessageImpl::NewResponse( 1946 event, running, exec_state, event_data, answer, command.client_data()); 1947 InvokeMessageHandler(message); 1948 command.Dispose(); 1949 1950 // Return from debug event processing if either the VM is put into the 1951 // running state (through a continue command) or auto continue is active 1952 // and there are no more commands queued. 1953 } while (!running || has_commands()); 1954 command_queue_.Clear(); 1955 } 1956 1957 1958 void Debug::SetEventListener(Handle<Object> callback, 1959 Handle<Object> data) { 1960 GlobalHandles* global_handles = isolate_->global_handles(); 1961 1962 // Remove existing entry. 1963 GlobalHandles::Destroy(event_listener_.location()); 1964 event_listener_ = Handle<Object>(); 1965 GlobalHandles::Destroy(event_listener_data_.location()); 1966 event_listener_data_ = Handle<Object>(); 1967 1968 // Set new entry. 1969 if (!callback->IsUndefined() && !callback->IsNull()) { 1970 event_listener_ = global_handles->Create(*callback); 1971 if (data.is_null()) data = isolate_->factory()->undefined_value(); 1972 event_listener_data_ = global_handles->Create(*data); 1973 } 1974 1975 UpdateState(); 1976 } 1977 1978 1979 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { 1980 message_handler_ = handler; 1981 UpdateState(); 1982 if (handler == NULL && in_debug_scope()) { 1983 // Send an empty command to the debugger if in a break to make JavaScript 1984 // run again if the debugger is closed. 1985 EnqueueCommandMessage(Vector<const uint16_t>::empty()); 1986 } 1987 } 1988 1989 1990 1991 void Debug::UpdateState() { 1992 bool is_active = message_handler_ != NULL || !event_listener_.is_null(); 1993 if (is_active || in_debug_scope()) { 1994 // Note that the debug context could have already been loaded to 1995 // bootstrap test cases. 1996 isolate_->compilation_cache()->Disable(); 1997 is_active = Load(); 1998 } else if (is_loaded()) { 1999 isolate_->compilation_cache()->Enable(); 2000 Unload(); 2001 } 2002 is_active_ = is_active; 2003 } 2004 2005 2006 // Calls the registered debug message handler. This callback is part of the 2007 // public API. 2008 void Debug::InvokeMessageHandler(MessageImpl message) { 2009 if (message_handler_ != NULL) message_handler_(message); 2010 } 2011 2012 2013 // Puts a command coming from the public API on the queue. Creates 2014 // a copy of the command string managed by the debugger. Up to this 2015 // point, the command data was managed by the API client. Called 2016 // by the API client thread. 2017 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command, 2018 v8::Debug::ClientData* client_data) { 2019 // Need to cast away const. 2020 CommandMessage message = CommandMessage::New( 2021 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), 2022 command.length()), 2023 client_data); 2024 isolate_->logger()->DebugTag("Put command on command_queue."); 2025 command_queue_.Put(message); 2026 command_received_.Signal(); 2027 2028 // Set the debug command break flag to have the command processed. 2029 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand(); 2030 } 2031 2032 2033 MaybeHandle<Object> Debug::Call(Handle<Object> fun, Handle<Object> data) { 2034 DebugScope debug_scope(this); 2035 if (debug_scope.failed()) return isolate_->factory()->undefined_value(); 2036 2037 // Create the execution state. 2038 Handle<Object> exec_state; 2039 if (!MakeExecutionState().ToHandle(&exec_state)) { 2040 return isolate_->factory()->undefined_value(); 2041 } 2042 2043 Handle<Object> argv[] = { exec_state, data }; 2044 return Execution::Call( 2045 isolate_, 2046 fun, 2047 Handle<Object>(debug_context()->global_proxy(), isolate_), 2048 arraysize(argv), 2049 argv); 2050 } 2051 2052 2053 void Debug::HandleDebugBreak() { 2054 // Ignore debug break during bootstrapping. 2055 if (isolate_->bootstrapper()->IsActive()) return; 2056 // Just continue if breaks are disabled. 2057 if (break_disabled()) return; 2058 // Ignore debug break if debugger is not active. 2059 if (!is_active()) return; 2060 2061 StackLimitCheck check(isolate_); 2062 if (check.HasOverflowed()) return; 2063 2064 { JavaScriptFrameIterator it(isolate_); 2065 DCHECK(!it.done()); 2066 Object* fun = it.frame()->function(); 2067 if (fun && fun->IsJSFunction()) { 2068 // Don't stop in builtin functions. 2069 if (!JSFunction::cast(fun)->shared()->IsSubjectToDebugging()) return; 2070 JSGlobalObject* global = 2071 JSFunction::cast(fun)->context()->global_object(); 2072 // Don't stop in debugger functions. 2073 if (IsDebugGlobal(global)) return; 2074 } 2075 } 2076 2077 // Collect the break state before clearing the flags. 2078 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() && 2079 !isolate_->stack_guard()->CheckDebugBreak(); 2080 2081 isolate_->stack_guard()->ClearDebugBreak(); 2082 2083 // Clear stepping to avoid duplicate breaks. 2084 ClearStepping(); 2085 2086 ProcessDebugMessages(debug_command_only); 2087 } 2088 2089 2090 void Debug::ProcessDebugMessages(bool debug_command_only) { 2091 isolate_->stack_guard()->ClearDebugCommand(); 2092 2093 StackLimitCheck check(isolate_); 2094 if (check.HasOverflowed()) return; 2095 2096 HandleScope scope(isolate_); 2097 DebugScope debug_scope(this); 2098 if (debug_scope.failed()) return; 2099 2100 // Notify the debug event listeners. Indicate auto continue if the break was 2101 // a debug command break. 2102 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); 2103 } 2104 2105 2106 DebugScope::DebugScope(Debug* debug) 2107 : debug_(debug), 2108 prev_(debug->debugger_entry()), 2109 save_(debug_->isolate_), 2110 no_termination_exceptons_(debug_->isolate_, 2111 StackGuard::TERMINATE_EXECUTION) { 2112 // Link recursive debugger entry. 2113 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, 2114 reinterpret_cast<base::AtomicWord>(this)); 2115 2116 // Store the previous break id and frame id. 2117 break_id_ = debug_->break_id(); 2118 break_frame_id_ = debug_->break_frame_id(); 2119 2120 // Create the new break info. If there is no JavaScript frames there is no 2121 // break frame id. 2122 JavaScriptFrameIterator it(isolate()); 2123 bool has_js_frames = !it.done(); 2124 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id() 2125 : StackFrame::NO_ID; 2126 debug_->SetNextBreakId(); 2127 2128 debug_->UpdateState(); 2129 // Make sure that debugger is loaded and enter the debugger context. 2130 // The previous context is kept in save_. 2131 failed_ = !debug_->is_loaded(); 2132 if (!failed_) isolate()->set_context(*debug->debug_context()); 2133 } 2134 2135 2136 DebugScope::~DebugScope() { 2137 if (!failed_ && prev_ == NULL) { 2138 // Clear mirror cache when leaving the debugger. Skip this if there is a 2139 // pending exception as clearing the mirror cache calls back into 2140 // JavaScript. This can happen if the v8::Debug::Call is used in which 2141 // case the exception should end up in the calling code. 2142 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); 2143 2144 // If there are commands in the queue when leaving the debugger request 2145 // that these commands are processed. 2146 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand(); 2147 } 2148 2149 // Leaving this debugger entry. 2150 base::NoBarrier_Store(&debug_->thread_local_.current_debug_scope_, 2151 reinterpret_cast<base::AtomicWord>(prev_)); 2152 2153 // Restore to the previous break state. 2154 debug_->thread_local_.break_frame_id_ = break_frame_id_; 2155 debug_->thread_local_.break_id_ = break_id_; 2156 2157 debug_->UpdateState(); 2158 } 2159 2160 2161 MessageImpl MessageImpl::NewEvent(DebugEvent event, 2162 bool running, 2163 Handle<JSObject> exec_state, 2164 Handle<JSObject> event_data) { 2165 MessageImpl message(true, event, running, 2166 exec_state, event_data, Handle<String>(), NULL); 2167 return message; 2168 } 2169 2170 2171 MessageImpl MessageImpl::NewResponse(DebugEvent event, 2172 bool running, 2173 Handle<JSObject> exec_state, 2174 Handle<JSObject> event_data, 2175 Handle<String> response_json, 2176 v8::Debug::ClientData* client_data) { 2177 MessageImpl message(false, event, running, 2178 exec_state, event_data, response_json, client_data); 2179 return message; 2180 } 2181 2182 2183 MessageImpl::MessageImpl(bool is_event, 2184 DebugEvent event, 2185 bool running, 2186 Handle<JSObject> exec_state, 2187 Handle<JSObject> event_data, 2188 Handle<String> response_json, 2189 v8::Debug::ClientData* client_data) 2190 : is_event_(is_event), 2191 event_(event), 2192 running_(running), 2193 exec_state_(exec_state), 2194 event_data_(event_data), 2195 response_json_(response_json), 2196 client_data_(client_data) {} 2197 2198 2199 bool MessageImpl::IsEvent() const { 2200 return is_event_; 2201 } 2202 2203 2204 bool MessageImpl::IsResponse() const { 2205 return !is_event_; 2206 } 2207 2208 2209 DebugEvent MessageImpl::GetEvent() const { 2210 return event_; 2211 } 2212 2213 2214 bool MessageImpl::WillStartRunning() const { 2215 return running_; 2216 } 2217 2218 2219 v8::Local<v8::Object> MessageImpl::GetExecutionState() const { 2220 return v8::Utils::ToLocal(exec_state_); 2221 } 2222 2223 2224 v8::Isolate* MessageImpl::GetIsolate() const { 2225 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); 2226 } 2227 2228 2229 v8::Local<v8::Object> MessageImpl::GetEventData() const { 2230 return v8::Utils::ToLocal(event_data_); 2231 } 2232 2233 2234 v8::Local<v8::String> MessageImpl::GetJSON() const { 2235 Isolate* isolate = event_data_->GetIsolate(); 2236 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate)); 2237 2238 if (IsEvent()) { 2239 // Call toJSONProtocol on the debug event object. 2240 Handle<Object> fun = Object::GetProperty( 2241 isolate, event_data_, "toJSONProtocol").ToHandleChecked(); 2242 if (!fun->IsJSFunction()) { 2243 return v8::Local<v8::String>(); 2244 } 2245 2246 MaybeHandle<Object> maybe_json = 2247 Execution::TryCall(isolate, fun, event_data_, 0, NULL); 2248 Handle<Object> json; 2249 if (!maybe_json.ToHandle(&json) || !json->IsString()) { 2250 return v8::Local<v8::String>(); 2251 } 2252 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); 2253 } else { 2254 return v8::Utils::ToLocal(response_json_); 2255 } 2256 } 2257 2258 2259 v8::Local<v8::Context> MessageImpl::GetEventContext() const { 2260 Isolate* isolate = event_data_->GetIsolate(); 2261 v8::Local<v8::Context> context = GetDebugEventContext(isolate); 2262 // Isolate::context() may be NULL when "script collected" event occurs. 2263 DCHECK(!context.IsEmpty()); 2264 return context; 2265 } 2266 2267 2268 v8::Debug::ClientData* MessageImpl::GetClientData() const { 2269 return client_data_; 2270 } 2271 2272 2273 EventDetailsImpl::EventDetailsImpl(DebugEvent event, 2274 Handle<JSObject> exec_state, 2275 Handle<JSObject> event_data, 2276 Handle<Object> callback_data, 2277 v8::Debug::ClientData* client_data) 2278 : event_(event), 2279 exec_state_(exec_state), 2280 event_data_(event_data), 2281 callback_data_(callback_data), 2282 client_data_(client_data) {} 2283 2284 2285 DebugEvent EventDetailsImpl::GetEvent() const { 2286 return event_; 2287 } 2288 2289 2290 v8::Local<v8::Object> EventDetailsImpl::GetExecutionState() const { 2291 return v8::Utils::ToLocal(exec_state_); 2292 } 2293 2294 2295 v8::Local<v8::Object> EventDetailsImpl::GetEventData() const { 2296 return v8::Utils::ToLocal(event_data_); 2297 } 2298 2299 2300 v8::Local<v8::Context> EventDetailsImpl::GetEventContext() const { 2301 return GetDebugEventContext(exec_state_->GetIsolate()); 2302 } 2303 2304 2305 v8::Local<v8::Value> EventDetailsImpl::GetCallbackData() const { 2306 return v8::Utils::ToLocal(callback_data_); 2307 } 2308 2309 2310 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const { 2311 return client_data_; 2312 } 2313 2314 2315 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()), 2316 client_data_(NULL) { 2317 } 2318 2319 2320 CommandMessage::CommandMessage(const Vector<uint16_t>& text, 2321 v8::Debug::ClientData* data) 2322 : text_(text), 2323 client_data_(data) { 2324 } 2325 2326 2327 void CommandMessage::Dispose() { 2328 text_.Dispose(); 2329 delete client_data_; 2330 client_data_ = NULL; 2331 } 2332 2333 2334 CommandMessage CommandMessage::New(const Vector<uint16_t>& command, 2335 v8::Debug::ClientData* data) { 2336 return CommandMessage(command.Clone(), data); 2337 } 2338 2339 2340 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0), 2341 size_(size) { 2342 messages_ = NewArray<CommandMessage>(size); 2343 } 2344 2345 2346 CommandMessageQueue::~CommandMessageQueue() { 2347 while (!IsEmpty()) Get().Dispose(); 2348 DeleteArray(messages_); 2349 } 2350 2351 2352 CommandMessage CommandMessageQueue::Get() { 2353 DCHECK(!IsEmpty()); 2354 int result = start_; 2355 start_ = (start_ + 1) % size_; 2356 return messages_[result]; 2357 } 2358 2359 2360 void CommandMessageQueue::Put(const CommandMessage& message) { 2361 if ((end_ + 1) % size_ == start_) { 2362 Expand(); 2363 } 2364 messages_[end_] = message; 2365 end_ = (end_ + 1) % size_; 2366 } 2367 2368 2369 void CommandMessageQueue::Expand() { 2370 CommandMessageQueue new_queue(size_ * 2); 2371 while (!IsEmpty()) { 2372 new_queue.Put(Get()); 2373 } 2374 CommandMessage* array_to_free = messages_; 2375 *this = new_queue; 2376 new_queue.messages_ = array_to_free; 2377 // Make the new_queue empty so that it doesn't call Dispose on any messages. 2378 new_queue.start_ = new_queue.end_; 2379 // Automatic destructor called on new_queue, freeing array_to_free. 2380 } 2381 2382 2383 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size) 2384 : logger_(logger), queue_(size) {} 2385 2386 2387 bool LockingCommandMessageQueue::IsEmpty() const { 2388 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2389 return queue_.IsEmpty(); 2390 } 2391 2392 2393 CommandMessage LockingCommandMessageQueue::Get() { 2394 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2395 CommandMessage result = queue_.Get(); 2396 logger_->DebugEvent("Get", result.text()); 2397 return result; 2398 } 2399 2400 2401 void LockingCommandMessageQueue::Put(const CommandMessage& message) { 2402 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2403 queue_.Put(message); 2404 logger_->DebugEvent("Put", message.text()); 2405 } 2406 2407 2408 void LockingCommandMessageQueue::Clear() { 2409 base::LockGuard<base::Mutex> lock_guard(&mutex_); 2410 queue_.Clear(); 2411 } 2412 2413 } // namespace internal 2414 } // namespace v8 2415