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/v8.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/debug.h" 15 #include "src/deoptimizer.h" 16 #include "src/execution.h" 17 #include "src/full-codegen.h" 18 #include "src/global-handles.h" 19 #include "src/ic.h" 20 #include "src/ic-inl.h" 21 #include "src/isolate-inl.h" 22 #include "src/list.h" 23 #include "src/messages.h" 24 #include "src/natives.h" 25 #include "src/stub-cache.h" 26 #include "src/log.h" 27 28 #include "include/v8-debug.h" 29 30 namespace v8 { 31 namespace internal { 32 33 Debug::Debug(Isolate* isolate) 34 : debug_context_(Handle<Context>()), 35 event_listener_(Handle<Object>()), 36 event_listener_data_(Handle<Object>()), 37 message_handler_(NULL), 38 command_received_(0), 39 command_queue_(isolate->logger(), kQueueInitialSize), 40 event_command_queue_(isolate->logger(), kQueueInitialSize), 41 is_active_(false), 42 is_suppressed_(false), 43 live_edit_enabled_(true), // TODO(yangguo): set to false by default. 44 has_break_points_(false), 45 break_disabled_(false), 46 break_on_exception_(false), 47 break_on_uncaught_exception_(false), 48 script_cache_(NULL), 49 debug_info_list_(NULL), 50 isolate_(isolate) { 51 ThreadInit(); 52 } 53 54 55 static v8::Handle<v8::Context> GetDebugEventContext(Isolate* isolate) { 56 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext(); 57 // Isolate::context() may have been NULL when "script collected" event 58 // occured. 59 if (context.is_null()) return v8::Local<v8::Context>(); 60 Handle<Context> native_context(context->native_context()); 61 return v8::Utils::ToLocal(native_context); 62 } 63 64 65 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info, 66 BreakLocatorType type) { 67 debug_info_ = debug_info; 68 type_ = type; 69 reloc_iterator_ = NULL; 70 reloc_iterator_original_ = NULL; 71 Reset(); // Initialize the rest of the member variables. 72 } 73 74 75 BreakLocationIterator::~BreakLocationIterator() { 76 ASSERT(reloc_iterator_ != NULL); 77 ASSERT(reloc_iterator_original_ != NULL); 78 delete reloc_iterator_; 79 delete reloc_iterator_original_; 80 } 81 82 83 // Check whether a code stub with the specified major key is a possible break 84 // point location when looking for source break locations. 85 static bool IsSourceBreakStub(Code* code) { 86 CodeStub::Major major_key = CodeStub::GetMajorKey(code); 87 return major_key == CodeStub::CallFunction; 88 } 89 90 91 // Check whether a code stub with the specified major key is a possible break 92 // location. 93 static bool IsBreakStub(Code* code) { 94 CodeStub::Major major_key = CodeStub::GetMajorKey(code); 95 return major_key == CodeStub::CallFunction; 96 } 97 98 99 void BreakLocationIterator::Next() { 100 DisallowHeapAllocation no_gc; 101 ASSERT(!RinfoDone()); 102 103 // Iterate through reloc info for code and original code stopping at each 104 // breakable code target. 105 bool first = break_point_ == -1; 106 while (!RinfoDone()) { 107 if (!first) RinfoNext(); 108 first = false; 109 if (RinfoDone()) return; 110 111 // Whenever a statement position or (plain) position is passed update the 112 // current value of these. 113 if (RelocInfo::IsPosition(rmode())) { 114 if (RelocInfo::IsStatementPosition(rmode())) { 115 statement_position_ = static_cast<int>( 116 rinfo()->data() - debug_info_->shared()->start_position()); 117 } 118 // Always update the position as we don't want that to be before the 119 // statement position. 120 position_ = static_cast<int>( 121 rinfo()->data() - debug_info_->shared()->start_position()); 122 ASSERT(position_ >= 0); 123 ASSERT(statement_position_ >= 0); 124 } 125 126 if (IsDebugBreakSlot()) { 127 // There is always a possible break point at a debug break slot. 128 break_point_++; 129 return; 130 } else if (RelocInfo::IsCodeTarget(rmode())) { 131 // Check for breakable code target. Look in the original code as setting 132 // break points can cause the code targets in the running (debugged) code 133 // to be of a different kind than in the original code. 134 Address target = original_rinfo()->target_address(); 135 Code* code = Code::GetCodeFromTargetAddress(target); 136 if ((code->is_inline_cache_stub() && 137 !code->is_binary_op_stub() && 138 !code->is_compare_ic_stub() && 139 !code->is_to_boolean_ic_stub()) || 140 RelocInfo::IsConstructCall(rmode())) { 141 break_point_++; 142 return; 143 } 144 if (code->kind() == Code::STUB) { 145 if (IsDebuggerStatement()) { 146 break_point_++; 147 return; 148 } else if (type_ == ALL_BREAK_LOCATIONS) { 149 if (IsBreakStub(code)) { 150 break_point_++; 151 return; 152 } 153 } else { 154 ASSERT(type_ == SOURCE_BREAK_LOCATIONS); 155 if (IsSourceBreakStub(code)) { 156 break_point_++; 157 return; 158 } 159 } 160 } 161 } 162 163 // Check for break at return. 164 if (RelocInfo::IsJSReturn(rmode())) { 165 // Set the positions to the end of the function. 166 if (debug_info_->shared()->HasSourceCode()) { 167 position_ = debug_info_->shared()->end_position() - 168 debug_info_->shared()->start_position() - 1; 169 } else { 170 position_ = 0; 171 } 172 statement_position_ = position_; 173 break_point_++; 174 return; 175 } 176 } 177 } 178 179 180 void BreakLocationIterator::Next(int count) { 181 while (count > 0) { 182 Next(); 183 count--; 184 } 185 } 186 187 188 // Find the break point at the supplied address, or the closest one before 189 // the address. 190 void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) { 191 // Run through all break points to locate the one closest to the address. 192 int closest_break_point = 0; 193 int distance = kMaxInt; 194 while (!Done()) { 195 // Check if this break point is closer that what was previously found. 196 if (this->pc() <= pc && pc - this->pc() < distance) { 197 closest_break_point = break_point(); 198 distance = static_cast<int>(pc - this->pc()); 199 // Check whether we can't get any closer. 200 if (distance == 0) break; 201 } 202 Next(); 203 } 204 205 // Move to the break point found. 206 Reset(); 207 Next(closest_break_point); 208 } 209 210 211 // Find the break point closest to the supplied source position. 212 void BreakLocationIterator::FindBreakLocationFromPosition(int position, 213 BreakPositionAlignment alignment) { 214 // Run through all break points to locate the one closest to the source 215 // position. 216 int closest_break_point = 0; 217 int distance = kMaxInt; 218 219 while (!Done()) { 220 int next_position; 221 switch (alignment) { 222 case STATEMENT_ALIGNED: 223 next_position = this->statement_position(); 224 break; 225 case BREAK_POSITION_ALIGNED: 226 next_position = this->position(); 227 break; 228 default: 229 UNREACHABLE(); 230 next_position = this->statement_position(); 231 } 232 // Check if this break point is closer that what was previously found. 233 if (position <= next_position && next_position - position < distance) { 234 closest_break_point = break_point(); 235 distance = next_position - position; 236 // Check whether we can't get any closer. 237 if (distance == 0) break; 238 } 239 Next(); 240 } 241 242 // Move to the break point found. 243 Reset(); 244 Next(closest_break_point); 245 } 246 247 248 void BreakLocationIterator::Reset() { 249 // Create relocation iterators for the two code objects. 250 if (reloc_iterator_ != NULL) delete reloc_iterator_; 251 if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_; 252 reloc_iterator_ = new RelocIterator( 253 debug_info_->code(), 254 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)); 255 reloc_iterator_original_ = new RelocIterator( 256 debug_info_->original_code(), 257 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE)); 258 259 // Position at the first break point. 260 break_point_ = -1; 261 position_ = 1; 262 statement_position_ = 1; 263 Next(); 264 } 265 266 267 bool BreakLocationIterator::Done() const { 268 return RinfoDone(); 269 } 270 271 272 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) { 273 // If there is not already a real break point here patch code with debug 274 // break. 275 if (!HasBreakPoint()) SetDebugBreak(); 276 ASSERT(IsDebugBreak() || IsDebuggerStatement()); 277 // Set the break point information. 278 DebugInfo::SetBreakPoint(debug_info_, code_position(), 279 position(), statement_position(), 280 break_point_object); 281 } 282 283 284 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) { 285 // Clear the break point information. 286 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object); 287 // If there are no more break points here remove the debug break. 288 if (!HasBreakPoint()) { 289 ClearDebugBreak(); 290 ASSERT(!IsDebugBreak()); 291 } 292 } 293 294 295 void BreakLocationIterator::SetOneShot() { 296 // Debugger statement always calls debugger. No need to modify it. 297 if (IsDebuggerStatement()) return; 298 299 // If there is a real break point here no more to do. 300 if (HasBreakPoint()) { 301 ASSERT(IsDebugBreak()); 302 return; 303 } 304 305 // Patch code with debug break. 306 SetDebugBreak(); 307 } 308 309 310 void BreakLocationIterator::ClearOneShot() { 311 // Debugger statement always calls debugger. No need to modify it. 312 if (IsDebuggerStatement()) return; 313 314 // If there is a real break point here no more to do. 315 if (HasBreakPoint()) { 316 ASSERT(IsDebugBreak()); 317 return; 318 } 319 320 // Patch code removing debug break. 321 ClearDebugBreak(); 322 ASSERT(!IsDebugBreak()); 323 } 324 325 326 void BreakLocationIterator::SetDebugBreak() { 327 // Debugger statement always calls debugger. No need to modify it. 328 if (IsDebuggerStatement()) return; 329 330 // If there is already a break point here just return. This might happen if 331 // the same code is flooded with break points twice. Flooding the same 332 // function twice might happen when stepping in a function with an exception 333 // handler as the handler and the function is the same. 334 if (IsDebugBreak()) return; 335 336 if (RelocInfo::IsJSReturn(rmode())) { 337 // Patch the frame exit code with a break point. 338 SetDebugBreakAtReturn(); 339 } else if (IsDebugBreakSlot()) { 340 // Patch the code in the break slot. 341 SetDebugBreakAtSlot(); 342 } else { 343 // Patch the IC call. 344 SetDebugBreakAtIC(); 345 } 346 ASSERT(IsDebugBreak()); 347 } 348 349 350 void BreakLocationIterator::ClearDebugBreak() { 351 // Debugger statement always calls debugger. No need to modify it. 352 if (IsDebuggerStatement()) return; 353 354 if (RelocInfo::IsJSReturn(rmode())) { 355 // Restore the frame exit code. 356 ClearDebugBreakAtReturn(); 357 } else if (IsDebugBreakSlot()) { 358 // Restore the code in the break slot. 359 ClearDebugBreakAtSlot(); 360 } else { 361 // Patch the IC call. 362 ClearDebugBreakAtIC(); 363 } 364 ASSERT(!IsDebugBreak()); 365 } 366 367 368 bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) { 369 if (RelocInfo::IsConstructCall(original_rmode())) { 370 return true; 371 } else if (RelocInfo::IsCodeTarget(rmode())) { 372 HandleScope scope(debug_info_->GetIsolate()); 373 Address target = original_rinfo()->target_address(); 374 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); 375 if (target_code->kind() == Code::STUB) { 376 return target_code->major_key() == CodeStub::CallFunction; 377 } 378 return target_code->is_call_stub(); 379 } 380 return false; 381 } 382 383 384 void BreakLocationIterator::PrepareStepIn(Isolate* isolate) { 385 #ifdef DEBUG 386 HandleScope scope(isolate); 387 // Step in can only be prepared if currently positioned on an IC call, 388 // construct call or CallFunction stub call. 389 Address target = rinfo()->target_address(); 390 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); 391 // All the following stuff is needed only for assertion checks so the code 392 // is wrapped in ifdef. 393 Handle<Code> maybe_call_function_stub = target_code; 394 if (IsDebugBreak()) { 395 Address original_target = original_rinfo()->target_address(); 396 maybe_call_function_stub = 397 Handle<Code>(Code::GetCodeFromTargetAddress(original_target)); 398 } 399 bool is_call_function_stub = 400 (maybe_call_function_stub->kind() == Code::STUB && 401 maybe_call_function_stub->major_key() == CodeStub::CallFunction); 402 403 // Step in through construct call requires no changes to the running code. 404 // Step in through getters/setters should already be prepared as well 405 // because caller of this function (Debug::PrepareStep) is expected to 406 // flood the top frame's function with one shot breakpoints. 407 // Step in through CallFunction stub should also be prepared by caller of 408 // this function (Debug::PrepareStep) which should flood target function 409 // with breakpoints. 410 ASSERT(RelocInfo::IsConstructCall(rmode()) || 411 target_code->is_inline_cache_stub() || 412 is_call_function_stub); 413 #endif 414 } 415 416 417 // Check whether the break point is at a position which will exit the function. 418 bool BreakLocationIterator::IsExit() const { 419 return (RelocInfo::IsJSReturn(rmode())); 420 } 421 422 423 bool BreakLocationIterator::HasBreakPoint() { 424 return debug_info_->HasBreakPoint(code_position()); 425 } 426 427 428 // Check whether there is a debug break at the current position. 429 bool BreakLocationIterator::IsDebugBreak() { 430 if (RelocInfo::IsJSReturn(rmode())) { 431 return IsDebugBreakAtReturn(); 432 } else if (IsDebugBreakSlot()) { 433 return IsDebugBreakAtSlot(); 434 } else { 435 return Debug::IsDebugBreak(rinfo()->target_address()); 436 } 437 } 438 439 440 // Find the builtin to use for invoking the debug break 441 static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) { 442 Isolate* isolate = code->GetIsolate(); 443 444 // Find the builtin debug break function matching the calling convention 445 // used by the call site. 446 if (code->is_inline_cache_stub()) { 447 switch (code->kind()) { 448 case Code::CALL_IC: 449 return isolate->builtins()->CallICStub_DebugBreak(); 450 451 case Code::LOAD_IC: 452 return isolate->builtins()->LoadIC_DebugBreak(); 453 454 case Code::STORE_IC: 455 return isolate->builtins()->StoreIC_DebugBreak(); 456 457 case Code::KEYED_LOAD_IC: 458 return isolate->builtins()->KeyedLoadIC_DebugBreak(); 459 460 case Code::KEYED_STORE_IC: 461 return isolate->builtins()->KeyedStoreIC_DebugBreak(); 462 463 case Code::COMPARE_NIL_IC: 464 return isolate->builtins()->CompareNilIC_DebugBreak(); 465 466 default: 467 UNREACHABLE(); 468 } 469 } 470 if (RelocInfo::IsConstructCall(mode)) { 471 if (code->has_function_cache()) { 472 return isolate->builtins()->CallConstructStub_Recording_DebugBreak(); 473 } else { 474 return isolate->builtins()->CallConstructStub_DebugBreak(); 475 } 476 } 477 if (code->kind() == Code::STUB) { 478 ASSERT(code->major_key() == CodeStub::CallFunction); 479 return isolate->builtins()->CallFunctionStub_DebugBreak(); 480 } 481 482 UNREACHABLE(); 483 return Handle<Code>::null(); 484 } 485 486 487 void BreakLocationIterator::SetDebugBreakAtIC() { 488 // Patch the original code with the current address as the current address 489 // might have changed by the inline caching since the code was copied. 490 original_rinfo()->set_target_address(rinfo()->target_address()); 491 492 RelocInfo::Mode mode = rmode(); 493 if (RelocInfo::IsCodeTarget(mode)) { 494 Address target = rinfo()->target_address(); 495 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); 496 497 // Patch the code to invoke the builtin debug break function matching the 498 // calling convention used by the call site. 499 Handle<Code> dbgbrk_code = DebugBreakForIC(target_code, mode); 500 rinfo()->set_target_address(dbgbrk_code->entry()); 501 } 502 } 503 504 505 void BreakLocationIterator::ClearDebugBreakAtIC() { 506 // Patch the code to the original invoke. 507 rinfo()->set_target_address(original_rinfo()->target_address()); 508 } 509 510 511 bool BreakLocationIterator::IsDebuggerStatement() { 512 return RelocInfo::DEBUG_BREAK == rmode(); 513 } 514 515 516 bool BreakLocationIterator::IsDebugBreakSlot() { 517 return RelocInfo::DEBUG_BREAK_SLOT == rmode(); 518 } 519 520 521 Object* BreakLocationIterator::BreakPointObjects() { 522 return debug_info_->GetBreakPointObjects(code_position()); 523 } 524 525 526 // Clear out all the debug break code. This is ONLY supposed to be used when 527 // shutting down the debugger as it will leave the break point information in 528 // DebugInfo even though the code is patched back to the non break point state. 529 void BreakLocationIterator::ClearAllDebugBreak() { 530 while (!Done()) { 531 ClearDebugBreak(); 532 Next(); 533 } 534 } 535 536 537 bool BreakLocationIterator::RinfoDone() const { 538 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); 539 return reloc_iterator_->done(); 540 } 541 542 543 void BreakLocationIterator::RinfoNext() { 544 reloc_iterator_->next(); 545 reloc_iterator_original_->next(); 546 #ifdef DEBUG 547 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done()); 548 if (!reloc_iterator_->done()) { 549 ASSERT(rmode() == original_rmode()); 550 } 551 #endif 552 } 553 554 555 // Threading support. 556 void Debug::ThreadInit() { 557 thread_local_.break_count_ = 0; 558 thread_local_.break_id_ = 0; 559 thread_local_.break_frame_id_ = StackFrame::NO_ID; 560 thread_local_.last_step_action_ = StepNone; 561 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; 562 thread_local_.step_count_ = 0; 563 thread_local_.last_fp_ = 0; 564 thread_local_.queued_step_count_ = 0; 565 thread_local_.step_into_fp_ = 0; 566 thread_local_.step_out_fp_ = 0; 567 // TODO(isolates): frames_are_dropped_? 568 thread_local_.current_debug_scope_ = NULL; 569 thread_local_.restarter_frame_function_pointer_ = NULL; 570 thread_local_.promise_on_stack_ = NULL; 571 } 572 573 574 char* Debug::ArchiveDebug(char* storage) { 575 char* to = storage; 576 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); 577 ThreadInit(); 578 return storage + ArchiveSpacePerThread(); 579 } 580 581 582 char* Debug::RestoreDebug(char* storage) { 583 char* from = storage; 584 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); 585 return storage + ArchiveSpacePerThread(); 586 } 587 588 589 int Debug::ArchiveSpacePerThread() { 590 return sizeof(ThreadLocal); 591 } 592 593 594 ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch), 595 isolate_(isolate), 596 collected_scripts_(10) { 597 Heap* heap = isolate_->heap(); 598 HandleScope scope(isolate_); 599 600 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets 601 // rid of all the cached script wrappers and the second gets rid of the 602 // scripts which are no longer referenced. 603 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); 604 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); 605 606 // Scan heap for Script objects. 607 HeapIterator iterator(heap); 608 DisallowHeapAllocation no_allocation; 609 610 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { 611 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { 612 Add(Handle<Script>(Script::cast(obj))); 613 } 614 } 615 } 616 617 618 void ScriptCache::Add(Handle<Script> script) { 619 GlobalHandles* global_handles = isolate_->global_handles(); 620 // Create an entry in the hash map for the script. 621 int id = script->id()->value(); 622 HashMap::Entry* entry = 623 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true); 624 if (entry->value != NULL) { 625 ASSERT(*script == *reinterpret_cast<Script**>(entry->value)); 626 return; 627 } 628 // Globalize the script object, make it weak and use the location of the 629 // global handle as the value in the hash map. 630 Handle<Script> script_ = 631 Handle<Script>::cast(global_handles->Create(*script)); 632 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(script_.location()), 633 this, 634 ScriptCache::HandleWeakScript); 635 entry->value = script_.location(); 636 } 637 638 639 Handle<FixedArray> ScriptCache::GetScripts() { 640 Factory* factory = isolate_->factory(); 641 Handle<FixedArray> instances = factory->NewFixedArray(occupancy()); 642 int count = 0; 643 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) { 644 ASSERT(entry->value != NULL); 645 if (entry->value != NULL) { 646 instances->set(count, *reinterpret_cast<Script**>(entry->value)); 647 count++; 648 } 649 } 650 return instances; 651 } 652 653 654 void ScriptCache::ProcessCollectedScripts() { 655 Debug* debug = isolate_->debug(); 656 for (int i = 0; i < collected_scripts_.length(); i++) { 657 debug->OnScriptCollected(collected_scripts_[i]); 658 } 659 collected_scripts_.Clear(); 660 } 661 662 663 void ScriptCache::Clear() { 664 // Iterate the script cache to get rid of all the weak handles. 665 for (HashMap::Entry* entry = Start(); entry != NULL; entry = Next(entry)) { 666 ASSERT(entry != NULL); 667 Object** location = reinterpret_cast<Object**>(entry->value); 668 ASSERT((*location)->IsScript()); 669 GlobalHandles::ClearWeakness(location); 670 GlobalHandles::Destroy(location); 671 } 672 // Clear the content of the hash map. 673 HashMap::Clear(); 674 } 675 676 677 void ScriptCache::HandleWeakScript( 678 const v8::WeakCallbackData<v8::Value, void>& data) { 679 // Retrieve the script identifier. 680 Handle<Object> object = Utils::OpenHandle(*data.GetValue()); 681 int id = Handle<Script>::cast(object)->id()->value(); 682 void* key = reinterpret_cast<void*>(id); 683 uint32_t hash = Hash(id); 684 685 // Remove the corresponding entry from the cache. 686 ScriptCache* script_cache = 687 reinterpret_cast<ScriptCache*>(data.GetParameter()); 688 HashMap::Entry* entry = script_cache->Lookup(key, hash, false); 689 Object** location = reinterpret_cast<Object**>(entry->value); 690 script_cache->Remove(key, hash); 691 script_cache->collected_scripts_.Add(id); 692 693 // Clear the weak handle. 694 GlobalHandles::Destroy(location); 695 } 696 697 698 void Debug::HandleWeakDebugInfo( 699 const v8::WeakCallbackData<v8::Value, void>& data) { 700 Debug* debug = reinterpret_cast<Isolate*>(data.GetIsolate())->debug(); 701 DebugInfoListNode* node = 702 reinterpret_cast<DebugInfoListNode*>(data.GetParameter()); 703 // We need to clear all breakpoints associated with the function to restore 704 // original code and avoid patching the code twice later because 705 // the function will live in the heap until next gc, and can be found by 706 // Debug::FindSharedFunctionInfoInScript. 707 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); 708 it.ClearAllDebugBreak(); 709 debug->RemoveDebugInfo(node->debug_info()); 710 #ifdef DEBUG 711 for (DebugInfoListNode* n = debug->debug_info_list_; 712 n != NULL; 713 n = n->next()) { 714 ASSERT(n != node); 715 } 716 #endif 717 } 718 719 720 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) { 721 // Globalize the request debug info object and make it weak. 722 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles(); 723 debug_info_ = Handle<DebugInfo>::cast(global_handles->Create(debug_info)); 724 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()), 725 this, 726 Debug::HandleWeakDebugInfo); 727 } 728 729 730 DebugInfoListNode::~DebugInfoListNode() { 731 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location())); 732 } 733 734 735 bool Debug::CompileDebuggerScript(Isolate* isolate, int index) { 736 Factory* factory = isolate->factory(); 737 HandleScope scope(isolate); 738 739 // Bail out if the index is invalid. 740 if (index == -1) return false; 741 742 // Find source and name for the requested script. 743 Handle<String> source_code = 744 isolate->bootstrapper()->NativesSourceLookup(index); 745 Vector<const char> name = Natives::GetScriptName(index); 746 Handle<String> script_name = 747 factory->NewStringFromAscii(name).ToHandleChecked(); 748 Handle<Context> context = isolate->native_context(); 749 750 // Compile the script. 751 Handle<SharedFunctionInfo> function_info; 752 function_info = Compiler::CompileScript(source_code, 753 script_name, 0, 0, 754 false, 755 context, 756 NULL, NULL, NO_CACHED_DATA, 757 NATIVES_CODE); 758 759 // Silently ignore stack overflows during compilation. 760 if (function_info.is_null()) { 761 ASSERT(isolate->has_pending_exception()); 762 isolate->clear_pending_exception(); 763 return false; 764 } 765 766 // Execute the shared function in the debugger context. 767 Handle<JSFunction> function = 768 factory->NewFunctionFromSharedFunctionInfo(function_info, context); 769 770 Handle<Object> exception; 771 MaybeHandle<Object> result = 772 Execution::TryCall(function, 773 Handle<Object>(context->global_object(), isolate), 774 0, 775 NULL, 776 &exception); 777 778 // Check for caught exceptions. 779 if (result.is_null()) { 780 ASSERT(!isolate->has_pending_exception()); 781 MessageLocation computed_location; 782 isolate->ComputeLocation(&computed_location); 783 Handle<Object> message = MessageHandler::MakeMessageObject( 784 isolate, "error_loading_debugger", &computed_location, 785 Vector<Handle<Object> >::empty(), Handle<JSArray>()); 786 ASSERT(!isolate->has_pending_exception()); 787 if (!exception.is_null()) { 788 isolate->set_pending_exception(*exception); 789 MessageHandler::ReportMessage(isolate, NULL, message); 790 isolate->clear_pending_exception(); 791 } 792 return false; 793 } 794 795 // Mark this script as native and return successfully. 796 Handle<Script> script(Script::cast(function->shared()->script())); 797 script->set_type(Smi::FromInt(Script::TYPE_NATIVE)); 798 return true; 799 } 800 801 802 bool Debug::Load() { 803 // Return if debugger is already loaded. 804 if (is_loaded()) return true; 805 806 // Bail out if we're already in the process of compiling the native 807 // JavaScript source code for the debugger. 808 if (is_suppressed_) return false; 809 SuppressDebug while_loading(this); 810 811 // Disable breakpoints and interrupts while compiling and running the 812 // debugger scripts including the context creation code. 813 DisableBreak disable(this, true); 814 PostponeInterruptsScope postpone(isolate_); 815 816 // Create the debugger context. 817 HandleScope scope(isolate_); 818 ExtensionConfiguration no_extensions; 819 Handle<Context> context = 820 isolate_->bootstrapper()->CreateEnvironment( 821 Handle<Object>::null(), 822 v8::Handle<ObjectTemplate>(), 823 &no_extensions); 824 825 // Fail if no context could be created. 826 if (context.is_null()) return false; 827 828 // Use the debugger context. 829 SaveContext save(isolate_); 830 isolate_->set_context(*context); 831 832 // Expose the builtins object in the debugger context. 833 Handle<String> key = isolate_->factory()->InternalizeOneByteString( 834 STATIC_ASCII_VECTOR("builtins")); 835 Handle<GlobalObject> global = 836 Handle<GlobalObject>(context->global_object(), isolate_); 837 Handle<JSBuiltinsObject> builtin = 838 Handle<JSBuiltinsObject>(global->builtins(), isolate_); 839 RETURN_ON_EXCEPTION_VALUE( 840 isolate_, 841 JSReceiver::SetProperty(global, key, builtin, NONE, SLOPPY), 842 false); 843 844 // Compile the JavaScript for the debugger in the debugger context. 845 bool caught_exception = 846 !CompileDebuggerScript(isolate_, Natives::GetIndex("mirror")) || 847 !CompileDebuggerScript(isolate_, Natives::GetIndex("debug")); 848 849 if (FLAG_enable_liveedit) { 850 caught_exception = caught_exception || 851 !CompileDebuggerScript(isolate_, Natives::GetIndex("liveedit")); 852 } 853 // Check for caught exceptions. 854 if (caught_exception) return false; 855 856 debug_context_ = Handle<Context>::cast( 857 isolate_->global_handles()->Create(*context)); 858 return true; 859 } 860 861 862 void Debug::Unload() { 863 ClearAllBreakPoints(); 864 ClearStepping(); 865 866 // Match unmatched PromiseHandlePrologue calls. 867 while (thread_local_.promise_on_stack_) PromiseHandleEpilogue(); 868 869 // Return debugger is not loaded. 870 if (!is_loaded()) return; 871 872 // Clear the script cache. 873 if (script_cache_ != NULL) { 874 delete script_cache_; 875 script_cache_ = NULL; 876 } 877 878 // Clear debugger context global handle. 879 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); 880 debug_context_ = Handle<Context>(); 881 } 882 883 884 void Debug::Break(Arguments args, JavaScriptFrame* frame) { 885 Heap* heap = isolate_->heap(); 886 HandleScope scope(isolate_); 887 ASSERT(args.length() == 0); 888 889 // Initialize LiveEdit. 890 LiveEdit::InitializeThreadLocal(this); 891 892 // Just continue if breaks are disabled or debugger cannot be loaded. 893 if (break_disabled_) return; 894 895 // Enter the debugger. 896 DebugScope debug_scope(this); 897 if (debug_scope.failed()) return; 898 899 // Postpone interrupt during breakpoint processing. 900 PostponeInterruptsScope postpone(isolate_); 901 902 // Get the debug info (create it if it does not exist). 903 Handle<SharedFunctionInfo> shared = 904 Handle<SharedFunctionInfo>(frame->function()->shared()); 905 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 906 907 // Find the break point where execution has stopped. 908 BreakLocationIterator break_location_iterator(debug_info, 909 ALL_BREAK_LOCATIONS); 910 // pc points to the instruction after the current one, possibly a break 911 // location as well. So the "- 1" to exclude it from the search. 912 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1); 913 914 // Check whether step next reached a new statement. 915 if (!StepNextContinue(&break_location_iterator, frame)) { 916 // Decrease steps left if performing multiple steps. 917 if (thread_local_.step_count_ > 0) { 918 thread_local_.step_count_--; 919 } 920 } 921 922 // If there is one or more real break points check whether any of these are 923 // triggered. 924 Handle<Object> break_points_hit(heap->undefined_value(), isolate_); 925 if (break_location_iterator.HasBreakPoint()) { 926 Handle<Object> break_point_objects = 927 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_); 928 break_points_hit = CheckBreakPoints(break_point_objects); 929 } 930 931 // If step out is active skip everything until the frame where we need to step 932 // out to is reached, unless real breakpoint is hit. 933 if (StepOutActive() && 934 frame->fp() != thread_local_.step_out_fp_ && 935 break_points_hit->IsUndefined() ) { 936 // Step count should always be 0 for StepOut. 937 ASSERT(thread_local_.step_count_ == 0); 938 } else if (!break_points_hit->IsUndefined() || 939 (thread_local_.last_step_action_ != StepNone && 940 thread_local_.step_count_ == 0)) { 941 // Notify debugger if a real break point is triggered or if performing 942 // single stepping with no more steps to perform. Otherwise do another step. 943 944 // Clear all current stepping setup. 945 ClearStepping(); 946 947 if (thread_local_.queued_step_count_ > 0) { 948 // Perform queued steps 949 int step_count = thread_local_.queued_step_count_; 950 951 // Clear queue 952 thread_local_.queued_step_count_ = 0; 953 954 PrepareStep(StepNext, step_count, StackFrame::NO_ID); 955 } else { 956 // Notify the debug event listeners. 957 OnDebugBreak(break_points_hit, false); 958 } 959 } else if (thread_local_.last_step_action_ != StepNone) { 960 // Hold on to last step action as it is cleared by the call to 961 // ClearStepping. 962 StepAction step_action = thread_local_.last_step_action_; 963 int step_count = thread_local_.step_count_; 964 965 // If StepNext goes deeper in code, StepOut until original frame 966 // and keep step count queued up in the meantime. 967 if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) { 968 // Count frames until target frame 969 int count = 0; 970 JavaScriptFrameIterator it(isolate_); 971 while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) { 972 count++; 973 it.Advance(); 974 } 975 976 // Check that we indeed found the frame we are looking for. 977 CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_)); 978 if (step_count > 1) { 979 // Save old count and action to continue stepping after StepOut. 980 thread_local_.queued_step_count_ = step_count - 1; 981 } 982 983 // Set up for StepOut to reach target frame. 984 step_action = StepOut; 985 step_count = count; 986 } 987 988 // Clear all current stepping setup. 989 ClearStepping(); 990 991 // Set up for the remaining steps. 992 PrepareStep(step_action, step_count, StackFrame::NO_ID); 993 } 994 } 995 996 997 RUNTIME_FUNCTION(Debug_Break) { 998 // Get the top-most JavaScript frame. 999 JavaScriptFrameIterator it(isolate); 1000 isolate->debug()->Break(args, it.frame()); 1001 isolate->debug()->SetAfterBreakTarget(it.frame()); 1002 return isolate->heap()->undefined_value(); 1003 } 1004 1005 1006 // Check the break point objects for whether one or more are actually 1007 // triggered. This function returns a JSArray with the break point objects 1008 // which is triggered. 1009 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) { 1010 Factory* factory = isolate_->factory(); 1011 1012 // Count the number of break points hit. If there are multiple break points 1013 // they are in a FixedArray. 1014 Handle<FixedArray> break_points_hit; 1015 int break_points_hit_count = 0; 1016 ASSERT(!break_point_objects->IsUndefined()); 1017 if (break_point_objects->IsFixedArray()) { 1018 Handle<FixedArray> array(FixedArray::cast(*break_point_objects)); 1019 break_points_hit = factory->NewFixedArray(array->length()); 1020 for (int i = 0; i < array->length(); i++) { 1021 Handle<Object> o(array->get(i), isolate_); 1022 if (CheckBreakPoint(o)) { 1023 break_points_hit->set(break_points_hit_count++, *o); 1024 } 1025 } 1026 } else { 1027 break_points_hit = factory->NewFixedArray(1); 1028 if (CheckBreakPoint(break_point_objects)) { 1029 break_points_hit->set(break_points_hit_count++, *break_point_objects); 1030 } 1031 } 1032 1033 // Return undefined if no break points were triggered. 1034 if (break_points_hit_count == 0) { 1035 return factory->undefined_value(); 1036 } 1037 // Return break points hit as a JSArray. 1038 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit); 1039 result->set_length(Smi::FromInt(break_points_hit_count)); 1040 return result; 1041 } 1042 1043 1044 // Check whether a single break point object is triggered. 1045 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) { 1046 Factory* factory = isolate_->factory(); 1047 HandleScope scope(isolate_); 1048 1049 // Ignore check if break point object is not a JSObject. 1050 if (!break_point_object->IsJSObject()) return true; 1051 1052 // Get the function IsBreakPointTriggered (defined in debug-debugger.js). 1053 Handle<String> is_break_point_triggered_string = 1054 factory->InternalizeOneByteString( 1055 STATIC_ASCII_VECTOR("IsBreakPointTriggered")); 1056 Handle<GlobalObject> debug_global(debug_context()->global_object()); 1057 Handle<JSFunction> check_break_point = 1058 Handle<JSFunction>::cast(Object::GetProperty( 1059 debug_global, is_break_point_triggered_string).ToHandleChecked()); 1060 1061 // Get the break id as an object. 1062 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id()); 1063 1064 // Call HandleBreakPointx. 1065 Handle<Object> argv[] = { break_id, break_point_object }; 1066 Handle<Object> result; 1067 if (!Execution::TryCall(check_break_point, 1068 isolate_->js_builtins_object(), 1069 ARRAY_SIZE(argv), 1070 argv).ToHandle(&result)) { 1071 return false; 1072 } 1073 1074 // Return whether the break point is triggered. 1075 return result->IsTrue(); 1076 } 1077 1078 1079 // Check whether the function has debug information. 1080 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) { 1081 return !shared->debug_info()->IsUndefined(); 1082 } 1083 1084 1085 // Return the debug info for this function. EnsureDebugInfo must be called 1086 // prior to ensure the debug info has been generated for shared. 1087 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) { 1088 ASSERT(HasDebugInfo(shared)); 1089 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info())); 1090 } 1091 1092 1093 bool Debug::SetBreakPoint(Handle<JSFunction> function, 1094 Handle<Object> break_point_object, 1095 int* source_position) { 1096 HandleScope scope(isolate_); 1097 1098 PrepareForBreakPoints(); 1099 1100 // Make sure the function is compiled and has set up the debug info. 1101 Handle<SharedFunctionInfo> shared(function->shared()); 1102 if (!EnsureDebugInfo(shared, function)) { 1103 // Return if retrieving debug info failed. 1104 return true; 1105 } 1106 1107 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 1108 // Source positions starts with zero. 1109 ASSERT(*source_position >= 0); 1110 1111 // Find the break point and change it. 1112 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); 1113 it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED); 1114 it.SetBreakPoint(break_point_object); 1115 1116 *source_position = it.position(); 1117 1118 // At least one active break point now. 1119 return debug_info->GetBreakPointCount() > 0; 1120 } 1121 1122 1123 bool Debug::SetBreakPointForScript(Handle<Script> script, 1124 Handle<Object> break_point_object, 1125 int* source_position, 1126 BreakPositionAlignment alignment) { 1127 HandleScope scope(isolate_); 1128 1129 PrepareForBreakPoints(); 1130 1131 // Obtain shared function info for the function. 1132 Object* result = FindSharedFunctionInfoInScript(script, *source_position); 1133 if (result->IsUndefined()) return false; 1134 1135 // Make sure the function has set up the debug info. 1136 Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(result)); 1137 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) { 1138 // Return if retrieving debug info failed. 1139 return false; 1140 } 1141 1142 // Find position within function. The script position might be before the 1143 // source position of the first function. 1144 int position; 1145 if (shared->start_position() > *source_position) { 1146 position = 0; 1147 } else { 1148 position = *source_position - shared->start_position(); 1149 } 1150 1151 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 1152 // Source positions starts with zero. 1153 ASSERT(position >= 0); 1154 1155 // Find the break point and change it. 1156 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); 1157 it.FindBreakLocationFromPosition(position, alignment); 1158 it.SetBreakPoint(break_point_object); 1159 1160 *source_position = it.position() + shared->start_position(); 1161 1162 // At least one active break point now. 1163 ASSERT(debug_info->GetBreakPointCount() > 0); 1164 return true; 1165 } 1166 1167 1168 void Debug::ClearBreakPoint(Handle<Object> break_point_object) { 1169 HandleScope scope(isolate_); 1170 1171 DebugInfoListNode* node = debug_info_list_; 1172 while (node != NULL) { 1173 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(), 1174 break_point_object); 1175 if (!result->IsUndefined()) { 1176 // Get information in the break point. 1177 BreakPointInfo* break_point_info = BreakPointInfo::cast(result); 1178 Handle<DebugInfo> debug_info = node->debug_info(); 1179 1180 // Find the break point and clear it. 1181 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS); 1182 it.FindBreakLocationFromAddress(debug_info->code()->entry() + 1183 break_point_info->code_position()->value()); 1184 it.ClearBreakPoint(break_point_object); 1185 1186 // If there are no more break points left remove the debug info for this 1187 // function. 1188 if (debug_info->GetBreakPointCount() == 0) { 1189 RemoveDebugInfo(debug_info); 1190 } 1191 1192 return; 1193 } 1194 node = node->next(); 1195 } 1196 } 1197 1198 1199 void Debug::ClearAllBreakPoints() { 1200 DebugInfoListNode* node = debug_info_list_; 1201 while (node != NULL) { 1202 // Remove all debug break code. 1203 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); 1204 it.ClearAllDebugBreak(); 1205 node = node->next(); 1206 } 1207 1208 // Remove all debug info. 1209 while (debug_info_list_ != NULL) { 1210 RemoveDebugInfo(debug_info_list_->debug_info()); 1211 } 1212 } 1213 1214 1215 void Debug::FloodWithOneShot(Handle<JSFunction> function) { 1216 PrepareForBreakPoints(); 1217 1218 // Make sure the function is compiled and has set up the debug info. 1219 Handle<SharedFunctionInfo> shared(function->shared()); 1220 if (!EnsureDebugInfo(shared, function)) { 1221 // Return if we failed to retrieve the debug info. 1222 return; 1223 } 1224 1225 // Flood the function with break points. 1226 BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS); 1227 while (!it.Done()) { 1228 it.SetOneShot(); 1229 it.Next(); 1230 } 1231 } 1232 1233 1234 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction> function) { 1235 Handle<FixedArray> new_bindings(function->function_bindings()); 1236 Handle<Object> bindee(new_bindings->get(JSFunction::kBoundFunctionIndex), 1237 isolate_); 1238 1239 if (!bindee.is_null() && bindee->IsJSFunction() && 1240 !JSFunction::cast(*bindee)->IsNative()) { 1241 Handle<JSFunction> bindee_function(JSFunction::cast(*bindee)); 1242 Debug::FloodWithOneShot(bindee_function); 1243 } 1244 } 1245 1246 1247 void Debug::FloodHandlerWithOneShot() { 1248 // Iterate through the JavaScript stack looking for handlers. 1249 StackFrame::Id id = break_frame_id(); 1250 if (id == StackFrame::NO_ID) { 1251 // If there is no JavaScript stack don't do anything. 1252 return; 1253 } 1254 for (JavaScriptFrameIterator it(isolate_, id); !it.done(); it.Advance()) { 1255 JavaScriptFrame* frame = it.frame(); 1256 if (frame->HasHandler()) { 1257 // Flood the function with the catch block with break points 1258 FloodWithOneShot(Handle<JSFunction>(frame->function())); 1259 return; 1260 } 1261 } 1262 } 1263 1264 1265 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) { 1266 if (type == BreakUncaughtException) { 1267 break_on_uncaught_exception_ = enable; 1268 } else { 1269 break_on_exception_ = enable; 1270 } 1271 } 1272 1273 1274 bool Debug::IsBreakOnException(ExceptionBreakType type) { 1275 if (type == BreakUncaughtException) { 1276 return break_on_uncaught_exception_; 1277 } else { 1278 return break_on_exception_; 1279 } 1280 } 1281 1282 1283 PromiseOnStack::PromiseOnStack(Isolate* isolate, 1284 PromiseOnStack* prev, 1285 Handle<JSFunction> getter) 1286 : isolate_(isolate), prev_(prev) { 1287 handler_ = StackHandler::FromAddress( 1288 Isolate::handler(isolate->thread_local_top())); 1289 getter_ = Handle<JSFunction>::cast( 1290 isolate->global_handles()->Create(*getter)); 1291 } 1292 1293 1294 PromiseOnStack::~PromiseOnStack() { 1295 isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location()); 1296 } 1297 1298 1299 void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) { 1300 PromiseOnStack* prev = thread_local_.promise_on_stack_; 1301 thread_local_.promise_on_stack_ = 1302 new PromiseOnStack(isolate_, prev, promise_getter); 1303 } 1304 1305 1306 void Debug::PromiseHandleEpilogue() { 1307 if (thread_local_.promise_on_stack_ == NULL) return; 1308 PromiseOnStack* prev = thread_local_.promise_on_stack_->prev(); 1309 delete thread_local_.promise_on_stack_; 1310 thread_local_.promise_on_stack_ = prev; 1311 } 1312 1313 1314 Handle<Object> Debug::GetPromiseForUncaughtException() { 1315 Handle<Object> undefined = isolate_->factory()->undefined_value(); 1316 if (thread_local_.promise_on_stack_ == NULL) return undefined; 1317 Handle<JSFunction> promise_getter = thread_local_.promise_on_stack_->getter(); 1318 StackHandler* promise_catch = thread_local_.promise_on_stack_->handler(); 1319 // Find the top-most try-catch handler. 1320 StackHandler* handler = StackHandler::FromAddress( 1321 Isolate::handler(isolate_->thread_local_top())); 1322 while (handler != NULL && !handler->is_catch()) { 1323 handler = handler->next(); 1324 } 1325 #ifdef DEBUG 1326 // Make sure that our promise catch handler is in the list of handlers, 1327 // even if it's not the top-most try-catch handler. 1328 StackHandler* temp = handler; 1329 while (temp != promise_catch && !temp->is_catch()) { 1330 temp = temp->next(); 1331 CHECK(temp != NULL); 1332 } 1333 #endif // DEBUG 1334 1335 if (handler == promise_catch) { 1336 return Execution::Call( 1337 isolate_, promise_getter, undefined, 0, NULL).ToHandleChecked(); 1338 } 1339 return undefined; 1340 } 1341 1342 1343 void Debug::PrepareStep(StepAction step_action, 1344 int step_count, 1345 StackFrame::Id frame_id) { 1346 HandleScope scope(isolate_); 1347 1348 PrepareForBreakPoints(); 1349 1350 ASSERT(in_debug_scope()); 1351 1352 // Remember this step action and count. 1353 thread_local_.last_step_action_ = step_action; 1354 if (step_action == StepOut) { 1355 // For step out target frame will be found on the stack so there is no need 1356 // to set step counter for it. It's expected to always be 0 for StepOut. 1357 thread_local_.step_count_ = 0; 1358 } else { 1359 thread_local_.step_count_ = step_count; 1360 } 1361 1362 // Get the frame where the execution has stopped and skip the debug frame if 1363 // any. The debug frame will only be present if execution was stopped due to 1364 // hitting a break point. In other situations (e.g. unhandled exception) the 1365 // debug frame is not present. 1366 StackFrame::Id id = break_frame_id(); 1367 if (id == StackFrame::NO_ID) { 1368 // If there is no JavaScript stack don't do anything. 1369 return; 1370 } 1371 if (frame_id != StackFrame::NO_ID) { 1372 id = frame_id; 1373 } 1374 JavaScriptFrameIterator frames_it(isolate_, id); 1375 JavaScriptFrame* frame = frames_it.frame(); 1376 1377 // First of all ensure there is one-shot break points in the top handler 1378 // if any. 1379 FloodHandlerWithOneShot(); 1380 1381 // If the function on the top frame is unresolved perform step out. This will 1382 // be the case when calling unknown functions and having the debugger stopped 1383 // in an unhandled exception. 1384 if (!frame->function()->IsJSFunction()) { 1385 // Step out: Find the calling JavaScript frame and flood it with 1386 // breakpoints. 1387 frames_it.Advance(); 1388 // Fill the function to return to with one-shot break points. 1389 JSFunction* function = frames_it.frame()->function(); 1390 FloodWithOneShot(Handle<JSFunction>(function)); 1391 return; 1392 } 1393 1394 // Get the debug info (create it if it does not exist). 1395 Handle<JSFunction> function(frame->function()); 1396 Handle<SharedFunctionInfo> shared(function->shared()); 1397 if (!EnsureDebugInfo(shared, function)) { 1398 // Return if ensuring debug info failed. 1399 return; 1400 } 1401 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 1402 1403 // Find the break location where execution has stopped. 1404 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS); 1405 // pc points to the instruction after the current one, possibly a break 1406 // location as well. So the "- 1" to exclude it from the search. 1407 it.FindBreakLocationFromAddress(frame->pc() - 1); 1408 1409 // Compute whether or not the target is a call target. 1410 bool is_load_or_store = false; 1411 bool is_inline_cache_stub = false; 1412 bool is_at_restarted_function = false; 1413 Handle<Code> call_function_stub; 1414 1415 if (thread_local_.restarter_frame_function_pointer_ == NULL) { 1416 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) { 1417 bool is_call_target = false; 1418 Address target = it.rinfo()->target_address(); 1419 Code* code = Code::GetCodeFromTargetAddress(target); 1420 if (code->is_call_stub()) { 1421 is_call_target = true; 1422 } 1423 if (code->is_inline_cache_stub()) { 1424 is_inline_cache_stub = true; 1425 is_load_or_store = !is_call_target; 1426 } 1427 1428 // Check if target code is CallFunction stub. 1429 Code* maybe_call_function_stub = code; 1430 // If there is a breakpoint at this line look at the original code to 1431 // check if it is a CallFunction stub. 1432 if (it.IsDebugBreak()) { 1433 Address original_target = it.original_rinfo()->target_address(); 1434 maybe_call_function_stub = 1435 Code::GetCodeFromTargetAddress(original_target); 1436 } 1437 if ((maybe_call_function_stub->kind() == Code::STUB && 1438 maybe_call_function_stub->major_key() == CodeStub::CallFunction) || 1439 maybe_call_function_stub->kind() == Code::CALL_IC) { 1440 // Save reference to the code as we may need it to find out arguments 1441 // count for 'step in' later. 1442 call_function_stub = Handle<Code>(maybe_call_function_stub); 1443 } 1444 } 1445 } else { 1446 is_at_restarted_function = true; 1447 } 1448 1449 // If this is the last break code target step out is the only possibility. 1450 if (it.IsExit() || step_action == StepOut) { 1451 if (step_action == StepOut) { 1452 // Skip step_count frames starting with the current one. 1453 while (step_count-- > 0 && !frames_it.done()) { 1454 frames_it.Advance(); 1455 } 1456 } else { 1457 ASSERT(it.IsExit()); 1458 frames_it.Advance(); 1459 } 1460 // Skip builtin functions on the stack. 1461 while (!frames_it.done() && frames_it.frame()->function()->IsNative()) { 1462 frames_it.Advance(); 1463 } 1464 // Step out: If there is a JavaScript caller frame, we need to 1465 // flood it with breakpoints. 1466 if (!frames_it.done()) { 1467 // Fill the function to return to with one-shot break points. 1468 JSFunction* function = frames_it.frame()->function(); 1469 FloodWithOneShot(Handle<JSFunction>(function)); 1470 // Set target frame pointer. 1471 ActivateStepOut(frames_it.frame()); 1472 } 1473 } else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) || 1474 !call_function_stub.is_null() || is_at_restarted_function) 1475 || step_action == StepNext || step_action == StepMin) { 1476 // Step next or step min. 1477 1478 // Fill the current function with one-shot break points. 1479 FloodWithOneShot(function); 1480 1481 // Remember source position and frame to handle step next. 1482 thread_local_.last_statement_position_ = 1483 debug_info->code()->SourceStatementPosition(frame->pc()); 1484 thread_local_.last_fp_ = frame->UnpaddedFP(); 1485 } else { 1486 // If there's restarter frame on top of the stack, just get the pointer 1487 // to function which is going to be restarted. 1488 if (is_at_restarted_function) { 1489 Handle<JSFunction> restarted_function( 1490 JSFunction::cast(*thread_local_.restarter_frame_function_pointer_)); 1491 FloodWithOneShot(restarted_function); 1492 } else if (!call_function_stub.is_null()) { 1493 // If it's CallFunction stub ensure target function is compiled and flood 1494 // it with one shot breakpoints. 1495 bool is_call_ic = call_function_stub->kind() == Code::CALL_IC; 1496 1497 // Find out number of arguments from the stub minor key. 1498 // Reverse lookup required as the minor key cannot be retrieved 1499 // from the code object. 1500 Handle<Object> obj( 1501 isolate_->heap()->code_stubs()->SlowReverseLookup( 1502 *call_function_stub), 1503 isolate_); 1504 ASSERT(!obj.is_null()); 1505 ASSERT(!(*obj)->IsUndefined()); 1506 ASSERT(obj->IsSmi()); 1507 // Get the STUB key and extract major and minor key. 1508 uint32_t key = Smi::cast(*obj)->value(); 1509 // Argc in the stub is the number of arguments passed - not the 1510 // expected arguments of the called function. 1511 int call_function_arg_count = is_call_ic 1512 ? CallICStub::ExtractArgcFromMinorKey(CodeStub::MinorKeyFromKey(key)) 1513 : CallFunctionStub::ExtractArgcFromMinorKey( 1514 CodeStub::MinorKeyFromKey(key)); 1515 1516 ASSERT(is_call_ic || 1517 call_function_stub->major_key() == CodeStub::MajorKeyFromKey(key)); 1518 1519 // Find target function on the expression stack. 1520 // Expression stack looks like this (top to bottom): 1521 // argN 1522 // ... 1523 // arg0 1524 // Receiver 1525 // Function to call 1526 int expressions_count = frame->ComputeExpressionsCount(); 1527 ASSERT(expressions_count - 2 - call_function_arg_count >= 0); 1528 Object* fun = frame->GetExpression( 1529 expressions_count - 2 - call_function_arg_count); 1530 1531 // Flood the actual target of call/apply. 1532 if (fun->IsJSFunction()) { 1533 Isolate* isolate = JSFunction::cast(fun)->GetIsolate(); 1534 Code* apply = isolate->builtins()->builtin(Builtins::kFunctionApply); 1535 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall); 1536 while (fun->IsJSFunction()) { 1537 Code* code = JSFunction::cast(fun)->shared()->code(); 1538 if (code != apply && code != call) break; 1539 fun = frame->GetExpression( 1540 expressions_count - 1 - call_function_arg_count); 1541 } 1542 } 1543 1544 if (fun->IsJSFunction()) { 1545 Handle<JSFunction> js_function(JSFunction::cast(fun)); 1546 if (js_function->shared()->bound()) { 1547 Debug::FloodBoundFunctionWithOneShot(js_function); 1548 } else if (!js_function->IsNative()) { 1549 // Don't step into builtins. 1550 // It will also compile target function if it's not compiled yet. 1551 FloodWithOneShot(js_function); 1552 } 1553 } 1554 } 1555 1556 // Fill the current function with one-shot break points even for step in on 1557 // a call target as the function called might be a native function for 1558 // which step in will not stop. It also prepares for stepping in 1559 // getters/setters. 1560 FloodWithOneShot(function); 1561 1562 if (is_load_or_store) { 1563 // Remember source position and frame to handle step in getter/setter. If 1564 // there is a custom getter/setter it will be handled in 1565 // Object::Get/SetPropertyWithCallback, otherwise the step action will be 1566 // propagated on the next Debug::Break. 1567 thread_local_.last_statement_position_ = 1568 debug_info->code()->SourceStatementPosition(frame->pc()); 1569 thread_local_.last_fp_ = frame->UnpaddedFP(); 1570 } 1571 1572 // Step in or Step in min 1573 it.PrepareStepIn(isolate_); 1574 ActivateStepIn(frame); 1575 } 1576 } 1577 1578 1579 // Check whether the current debug break should be reported to the debugger. It 1580 // is used to have step next and step in only report break back to the debugger 1581 // if on a different frame or in a different statement. In some situations 1582 // there will be several break points in the same statement when the code is 1583 // flooded with one-shot break points. This function helps to perform several 1584 // steps before reporting break back to the debugger. 1585 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator, 1586 JavaScriptFrame* frame) { 1587 // StepNext and StepOut shouldn't bring us deeper in code, so last frame 1588 // shouldn't be a parent of current frame. 1589 if (thread_local_.last_step_action_ == StepNext || 1590 thread_local_.last_step_action_ == StepOut) { 1591 if (frame->fp() < thread_local_.last_fp_) return true; 1592 } 1593 1594 // If the step last action was step next or step in make sure that a new 1595 // statement is hit. 1596 if (thread_local_.last_step_action_ == StepNext || 1597 thread_local_.last_step_action_ == StepIn) { 1598 // Never continue if returning from function. 1599 if (break_location_iterator->IsExit()) return false; 1600 1601 // Continue if we are still on the same frame and in the same statement. 1602 int current_statement_position = 1603 break_location_iterator->code()->SourceStatementPosition(frame->pc()); 1604 return thread_local_.last_fp_ == frame->UnpaddedFP() && 1605 thread_local_.last_statement_position_ == current_statement_position; 1606 } 1607 1608 // No step next action - don't continue. 1609 return false; 1610 } 1611 1612 1613 // Check whether the code object at the specified address is a debug break code 1614 // object. 1615 bool Debug::IsDebugBreak(Address addr) { 1616 Code* code = Code::GetCodeFromTargetAddress(addr); 1617 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK; 1618 } 1619 1620 1621 1622 1623 1624 // Simple function for returning the source positions for active break points. 1625 Handle<Object> Debug::GetSourceBreakLocations( 1626 Handle<SharedFunctionInfo> shared, 1627 BreakPositionAlignment position_alignment) { 1628 Isolate* isolate = shared->GetIsolate(); 1629 Heap* heap = isolate->heap(); 1630 if (!HasDebugInfo(shared)) { 1631 return Handle<Object>(heap->undefined_value(), isolate); 1632 } 1633 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 1634 if (debug_info->GetBreakPointCount() == 0) { 1635 return Handle<Object>(heap->undefined_value(), isolate); 1636 } 1637 Handle<FixedArray> locations = 1638 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount()); 1639 int count = 0; 1640 for (int i = 0; i < debug_info->break_points()->length(); i++) { 1641 if (!debug_info->break_points()->get(i)->IsUndefined()) { 1642 BreakPointInfo* break_point_info = 1643 BreakPointInfo::cast(debug_info->break_points()->get(i)); 1644 if (break_point_info->GetBreakPointCount() > 0) { 1645 Smi* position; 1646 switch (position_alignment) { 1647 case STATEMENT_ALIGNED: 1648 position = break_point_info->statement_position(); 1649 break; 1650 case BREAK_POSITION_ALIGNED: 1651 position = break_point_info->source_position(); 1652 break; 1653 default: 1654 UNREACHABLE(); 1655 position = break_point_info->statement_position(); 1656 } 1657 1658 locations->set(count++, position); 1659 } 1660 } 1661 } 1662 return locations; 1663 } 1664 1665 1666 // Handle stepping into a function. 1667 void Debug::HandleStepIn(Handle<JSFunction> function, 1668 Handle<Object> holder, 1669 Address fp, 1670 bool is_constructor) { 1671 Isolate* isolate = function->GetIsolate(); 1672 // If the frame pointer is not supplied by the caller find it. 1673 if (fp == 0) { 1674 StackFrameIterator it(isolate); 1675 it.Advance(); 1676 // For constructor functions skip another frame. 1677 if (is_constructor) { 1678 ASSERT(it.frame()->is_construct()); 1679 it.Advance(); 1680 } 1681 fp = it.frame()->fp(); 1682 } 1683 1684 // Flood the function with one-shot break points if it is called from where 1685 // step into was requested. 1686 if (fp == thread_local_.step_into_fp_) { 1687 if (function->shared()->bound()) { 1688 // Handle Function.prototype.bind 1689 Debug::FloodBoundFunctionWithOneShot(function); 1690 } else if (!function->IsNative()) { 1691 // Don't allow step into functions in the native context. 1692 if (function->shared()->code() == 1693 isolate->builtins()->builtin(Builtins::kFunctionApply) || 1694 function->shared()->code() == 1695 isolate->builtins()->builtin(Builtins::kFunctionCall)) { 1696 // Handle function.apply and function.call separately to flood the 1697 // function to be called and not the code for Builtins::FunctionApply or 1698 // Builtins::FunctionCall. The receiver of call/apply is the target 1699 // function. 1700 if (!holder.is_null() && holder->IsJSFunction()) { 1701 Handle<JSFunction> js_function = Handle<JSFunction>::cast(holder); 1702 if (!js_function->IsNative()) { 1703 Debug::FloodWithOneShot(js_function); 1704 } else if (js_function->shared()->bound()) { 1705 // Handle Function.prototype.bind 1706 Debug::FloodBoundFunctionWithOneShot(js_function); 1707 } 1708 } 1709 } else { 1710 Debug::FloodWithOneShot(function); 1711 } 1712 } 1713 } 1714 } 1715 1716 1717 void Debug::ClearStepping() { 1718 // Clear the various stepping setup. 1719 ClearOneShot(); 1720 ClearStepIn(); 1721 ClearStepOut(); 1722 ClearStepNext(); 1723 1724 // Clear multiple step counter. 1725 thread_local_.step_count_ = 0; 1726 } 1727 1728 1729 // Clears all the one-shot break points that are currently set. Normally this 1730 // function is called each time a break point is hit as one shot break points 1731 // are used to support stepping. 1732 void Debug::ClearOneShot() { 1733 // The current implementation just runs through all the breakpoints. When the 1734 // last break point for a function is removed that function is automatically 1735 // removed from the list. 1736 1737 DebugInfoListNode* node = debug_info_list_; 1738 while (node != NULL) { 1739 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS); 1740 while (!it.Done()) { 1741 it.ClearOneShot(); 1742 it.Next(); 1743 } 1744 node = node->next(); 1745 } 1746 } 1747 1748 1749 void Debug::ActivateStepIn(StackFrame* frame) { 1750 ASSERT(!StepOutActive()); 1751 thread_local_.step_into_fp_ = frame->UnpaddedFP(); 1752 } 1753 1754 1755 void Debug::ClearStepIn() { 1756 thread_local_.step_into_fp_ = 0; 1757 } 1758 1759 1760 void Debug::ActivateStepOut(StackFrame* frame) { 1761 ASSERT(!StepInActive()); 1762 thread_local_.step_out_fp_ = frame->UnpaddedFP(); 1763 } 1764 1765 1766 void Debug::ClearStepOut() { 1767 thread_local_.step_out_fp_ = 0; 1768 } 1769 1770 1771 void Debug::ClearStepNext() { 1772 thread_local_.last_step_action_ = StepNone; 1773 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; 1774 thread_local_.last_fp_ = 0; 1775 } 1776 1777 1778 static void CollectActiveFunctionsFromThread( 1779 Isolate* isolate, 1780 ThreadLocalTop* top, 1781 List<Handle<JSFunction> >* active_functions, 1782 Object* active_code_marker) { 1783 // Find all non-optimized code functions with activation frames 1784 // on the stack. This includes functions which have optimized 1785 // activations (including inlined functions) on the stack as the 1786 // non-optimized code is needed for the lazy deoptimization. 1787 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { 1788 JavaScriptFrame* frame = it.frame(); 1789 if (frame->is_optimized()) { 1790 List<JSFunction*> functions(FLAG_max_inlining_levels + 1); 1791 frame->GetFunctions(&functions); 1792 for (int i = 0; i < functions.length(); i++) { 1793 JSFunction* function = functions[i]; 1794 active_functions->Add(Handle<JSFunction>(function)); 1795 function->shared()->code()->set_gc_metadata(active_code_marker); 1796 } 1797 } else if (frame->function()->IsJSFunction()) { 1798 JSFunction* function = frame->function(); 1799 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION); 1800 active_functions->Add(Handle<JSFunction>(function)); 1801 function->shared()->code()->set_gc_metadata(active_code_marker); 1802 } 1803 } 1804 } 1805 1806 1807 // Figure out how many bytes of "pc_offset" correspond to actual code by 1808 // subtracting off the bytes that correspond to constant/veneer pools. See 1809 // Assembler::CheckConstPool() and Assembler::CheckVeneerPool(). Note that this 1810 // is only useful for architectures using constant pools or veneer pools. 1811 static int ComputeCodeOffsetFromPcOffset(Code *code, int pc_offset) { 1812 ASSERT_EQ(code->kind(), Code::FUNCTION); 1813 ASSERT(!code->has_debug_break_slots()); 1814 ASSERT_LE(0, pc_offset); 1815 ASSERT_LT(pc_offset, code->instruction_end() - code->instruction_start()); 1816 1817 int mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) | 1818 RelocInfo::ModeMask(RelocInfo::VENEER_POOL); 1819 byte *pc = code->instruction_start() + pc_offset; 1820 int code_offset = pc_offset; 1821 for (RelocIterator it(code, mask); !it.done(); it.next()) { 1822 RelocInfo* info = it.rinfo(); 1823 if (info->pc() >= pc) break; 1824 ASSERT(RelocInfo::IsConstPool(info->rmode())); 1825 code_offset -= static_cast<int>(info->data()); 1826 ASSERT_LE(0, code_offset); 1827 } 1828 1829 return code_offset; 1830 } 1831 1832 1833 // The inverse of ComputeCodeOffsetFromPcOffset. 1834 static int ComputePcOffsetFromCodeOffset(Code *code, int code_offset) { 1835 ASSERT_EQ(code->kind(), Code::FUNCTION); 1836 1837 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) | 1838 RelocInfo::ModeMask(RelocInfo::CONST_POOL) | 1839 RelocInfo::ModeMask(RelocInfo::VENEER_POOL); 1840 int reloc = 0; 1841 for (RelocIterator it(code, mask); !it.done(); it.next()) { 1842 RelocInfo* info = it.rinfo(); 1843 if (info->pc() - code->instruction_start() - reloc >= code_offset) break; 1844 if (RelocInfo::IsDebugBreakSlot(info->rmode())) { 1845 reloc += Assembler::kDebugBreakSlotLength; 1846 } else { 1847 ASSERT(RelocInfo::IsConstPool(info->rmode())); 1848 reloc += static_cast<int>(info->data()); 1849 } 1850 } 1851 1852 int pc_offset = code_offset + reloc; 1853 1854 ASSERT_LT(code->instruction_start() + pc_offset, code->instruction_end()); 1855 1856 return pc_offset; 1857 } 1858 1859 1860 static void RedirectActivationsToRecompiledCodeOnThread( 1861 Isolate* isolate, 1862 ThreadLocalTop* top) { 1863 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) { 1864 JavaScriptFrame* frame = it.frame(); 1865 1866 if (frame->is_optimized() || !frame->function()->IsJSFunction()) continue; 1867 1868 JSFunction* function = frame->function(); 1869 1870 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION); 1871 1872 Handle<Code> frame_code(frame->LookupCode()); 1873 if (frame_code->has_debug_break_slots()) continue; 1874 1875 Handle<Code> new_code(function->shared()->code()); 1876 if (new_code->kind() != Code::FUNCTION || 1877 !new_code->has_debug_break_slots()) { 1878 continue; 1879 } 1880 1881 int old_pc_offset = 1882 static_cast<int>(frame->pc() - frame_code->instruction_start()); 1883 int code_offset = ComputeCodeOffsetFromPcOffset(*frame_code, old_pc_offset); 1884 int new_pc_offset = ComputePcOffsetFromCodeOffset(*new_code, code_offset); 1885 1886 // Compute the equivalent pc in the new code. 1887 byte* new_pc = new_code->instruction_start() + new_pc_offset; 1888 1889 if (FLAG_trace_deopt) { 1890 PrintF("Replacing code %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " 1891 "with %08" V8PRIxPTR " - %08" V8PRIxPTR " (%d) " 1892 "for debugging, " 1893 "changing pc from %08" V8PRIxPTR " to %08" V8PRIxPTR "\n", 1894 reinterpret_cast<intptr_t>( 1895 frame_code->instruction_start()), 1896 reinterpret_cast<intptr_t>( 1897 frame_code->instruction_start()) + 1898 frame_code->instruction_size(), 1899 frame_code->instruction_size(), 1900 reinterpret_cast<intptr_t>(new_code->instruction_start()), 1901 reinterpret_cast<intptr_t>(new_code->instruction_start()) + 1902 new_code->instruction_size(), 1903 new_code->instruction_size(), 1904 reinterpret_cast<intptr_t>(frame->pc()), 1905 reinterpret_cast<intptr_t>(new_pc)); 1906 } 1907 1908 // Patch the return address to return into the code with 1909 // debug break slots. 1910 frame->set_pc(new_pc); 1911 } 1912 } 1913 1914 1915 class ActiveFunctionsCollector : public ThreadVisitor { 1916 public: 1917 explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions, 1918 Object* active_code_marker) 1919 : active_functions_(active_functions), 1920 active_code_marker_(active_code_marker) { } 1921 1922 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { 1923 CollectActiveFunctionsFromThread(isolate, 1924 top, 1925 active_functions_, 1926 active_code_marker_); 1927 } 1928 1929 private: 1930 List<Handle<JSFunction> >* active_functions_; 1931 Object* active_code_marker_; 1932 }; 1933 1934 1935 class ActiveFunctionsRedirector : public ThreadVisitor { 1936 public: 1937 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { 1938 RedirectActivationsToRecompiledCodeOnThread(isolate, top); 1939 } 1940 }; 1941 1942 1943 static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) { 1944 if (function->code()->kind() == Code::FUNCTION && 1945 function->code()->has_debug_break_slots()) { 1946 // Nothing to do. Function code already had debug break slots. 1947 return; 1948 } 1949 // Make sure that the shared full code is compiled with debug 1950 // break slots. 1951 if (!function->shared()->code()->has_debug_break_slots()) { 1952 MaybeHandle<Code> code = Compiler::GetCodeForDebugging(function); 1953 // Recompilation can fail. In that case leave the code as it was. 1954 if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked()); 1955 } else { 1956 // Simply use shared code if it has debug break slots. 1957 function->ReplaceCode(function->shared()->code()); 1958 } 1959 } 1960 1961 1962 static void RecompileAndRelocateSuspendedGenerators( 1963 const List<Handle<JSGeneratorObject> > &generators) { 1964 for (int i = 0; i < generators.length(); i++) { 1965 Handle<JSFunction> fun(generators[i]->function()); 1966 1967 EnsureFunctionHasDebugBreakSlots(fun); 1968 1969 int code_offset = generators[i]->continuation(); 1970 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset); 1971 generators[i]->set_continuation(pc_offset); 1972 } 1973 } 1974 1975 1976 void Debug::PrepareForBreakPoints() { 1977 // If preparing for the first break point make sure to deoptimize all 1978 // functions as debugging does not work with optimized code. 1979 if (!has_break_points_) { 1980 if (isolate_->concurrent_recompilation_enabled()) { 1981 isolate_->optimizing_compiler_thread()->Flush(); 1982 } 1983 1984 Deoptimizer::DeoptimizeAll(isolate_); 1985 1986 Handle<Code> lazy_compile = isolate_->builtins()->CompileUnoptimized(); 1987 1988 // There will be at least one break point when we are done. 1989 has_break_points_ = true; 1990 1991 // Keep the list of activated functions in a handlified list as it 1992 // is used both in GC and non-GC code. 1993 List<Handle<JSFunction> > active_functions(100); 1994 1995 // A list of all suspended generators. 1996 List<Handle<JSGeneratorObject> > suspended_generators; 1997 1998 // A list of all generator functions. We need to recompile all functions, 1999 // but we don't know until after visiting the whole heap which generator 2000 // functions have suspended activations and which do not. As in the case of 2001 // functions with activations on the stack, we need to be careful with 2002 // generator functions with suspended activations because although they 2003 // should be recompiled, recompilation can fail, and we need to avoid 2004 // leaving the heap in an inconsistent state. 2005 // 2006 // We could perhaps avoid this list and instead re-use the GC metadata 2007 // links. 2008 List<Handle<JSFunction> > generator_functions; 2009 2010 { 2011 // We are going to iterate heap to find all functions without 2012 // debug break slots. 2013 Heap* heap = isolate_->heap(); 2014 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, 2015 "preparing for breakpoints"); 2016 HeapIterator iterator(heap); 2017 2018 // Ensure no GC in this scope as we are going to use gc_metadata 2019 // field in the Code object to mark active functions. 2020 DisallowHeapAllocation no_allocation; 2021 2022 Object* active_code_marker = heap->the_hole_value(); 2023 2024 CollectActiveFunctionsFromThread(isolate_, 2025 isolate_->thread_local_top(), 2026 &active_functions, 2027 active_code_marker); 2028 ActiveFunctionsCollector active_functions_collector(&active_functions, 2029 active_code_marker); 2030 isolate_->thread_manager()->IterateArchivedThreads( 2031 &active_functions_collector); 2032 2033 // Scan the heap for all non-optimized functions which have no 2034 // debug break slots and are not active or inlined into an active 2035 // function and mark them for lazy compilation. 2036 HeapObject* obj = NULL; 2037 while (((obj = iterator.next()) != NULL)) { 2038 if (obj->IsJSFunction()) { 2039 JSFunction* function = JSFunction::cast(obj); 2040 SharedFunctionInfo* shared = function->shared(); 2041 2042 if (!shared->allows_lazy_compilation()) continue; 2043 if (!shared->script()->IsScript()) continue; 2044 if (function->IsNative()) continue; 2045 if (shared->code()->gc_metadata() == active_code_marker) continue; 2046 2047 if (shared->is_generator()) { 2048 generator_functions.Add(Handle<JSFunction>(function, isolate_)); 2049 continue; 2050 } 2051 2052 Code::Kind kind = function->code()->kind(); 2053 if (kind == Code::FUNCTION && 2054 !function->code()->has_debug_break_slots()) { 2055 function->ReplaceCode(*lazy_compile); 2056 function->shared()->ReplaceCode(*lazy_compile); 2057 } else if (kind == Code::BUILTIN && 2058 (function->IsInOptimizationQueue() || 2059 function->IsMarkedForOptimization() || 2060 function->IsMarkedForConcurrentOptimization())) { 2061 // Abort in-flight compilation. 2062 Code* shared_code = function->shared()->code(); 2063 if (shared_code->kind() == Code::FUNCTION && 2064 shared_code->has_debug_break_slots()) { 2065 function->ReplaceCode(shared_code); 2066 } else { 2067 function->ReplaceCode(*lazy_compile); 2068 function->shared()->ReplaceCode(*lazy_compile); 2069 } 2070 } 2071 } else if (obj->IsJSGeneratorObject()) { 2072 JSGeneratorObject* gen = JSGeneratorObject::cast(obj); 2073 if (!gen->is_suspended()) continue; 2074 2075 JSFunction* fun = gen->function(); 2076 ASSERT_EQ(fun->code()->kind(), Code::FUNCTION); 2077 if (fun->code()->has_debug_break_slots()) continue; 2078 2079 int pc_offset = gen->continuation(); 2080 ASSERT_LT(0, pc_offset); 2081 2082 int code_offset = 2083 ComputeCodeOffsetFromPcOffset(fun->code(), pc_offset); 2084 2085 // This will be fixed after we recompile the functions. 2086 gen->set_continuation(code_offset); 2087 2088 suspended_generators.Add(Handle<JSGeneratorObject>(gen, isolate_)); 2089 } 2090 } 2091 2092 // Clear gc_metadata field. 2093 for (int i = 0; i < active_functions.length(); i++) { 2094 Handle<JSFunction> function = active_functions[i]; 2095 function->shared()->code()->set_gc_metadata(Smi::FromInt(0)); 2096 } 2097 } 2098 2099 // Recompile generator functions that have suspended activations, and 2100 // relocate those activations. 2101 RecompileAndRelocateSuspendedGenerators(suspended_generators); 2102 2103 // Mark generator functions that didn't have suspended activations for lazy 2104 // recompilation. Note that this set does not include any active functions. 2105 for (int i = 0; i < generator_functions.length(); i++) { 2106 Handle<JSFunction> &function = generator_functions[i]; 2107 if (function->code()->kind() != Code::FUNCTION) continue; 2108 if (function->code()->has_debug_break_slots()) continue; 2109 function->ReplaceCode(*lazy_compile); 2110 function->shared()->ReplaceCode(*lazy_compile); 2111 } 2112 2113 // Now recompile all functions with activation frames and and 2114 // patch the return address to run in the new compiled code. It could be 2115 // that some active functions were recompiled already by the suspended 2116 // generator recompilation pass above; a generator with suspended 2117 // activations could also have active activations. That's fine. 2118 for (int i = 0; i < active_functions.length(); i++) { 2119 Handle<JSFunction> function = active_functions[i]; 2120 Handle<SharedFunctionInfo> shared(function->shared()); 2121 2122 // If recompilation is not possible just skip it. 2123 if (shared->is_toplevel()) continue; 2124 if (!shared->allows_lazy_compilation()) continue; 2125 if (shared->code()->kind() == Code::BUILTIN) continue; 2126 2127 EnsureFunctionHasDebugBreakSlots(function); 2128 } 2129 2130 RedirectActivationsToRecompiledCodeOnThread(isolate_, 2131 isolate_->thread_local_top()); 2132 2133 ActiveFunctionsRedirector active_functions_redirector; 2134 isolate_->thread_manager()->IterateArchivedThreads( 2135 &active_functions_redirector); 2136 } 2137 } 2138 2139 2140 Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script, 2141 int position) { 2142 // Iterate the heap looking for SharedFunctionInfo generated from the 2143 // script. The inner most SharedFunctionInfo containing the source position 2144 // for the requested break point is found. 2145 // NOTE: This might require several heap iterations. If the SharedFunctionInfo 2146 // which is found is not compiled it is compiled and the heap is iterated 2147 // again as the compilation might create inner functions from the newly 2148 // compiled function and the actual requested break point might be in one of 2149 // these functions. 2150 // NOTE: The below fix-point iteration depends on all functions that cannot be 2151 // compiled lazily without a context to not be compiled at all. Compilation 2152 // will be triggered at points where we do not need a context. 2153 bool done = false; 2154 // The current candidate for the source position: 2155 int target_start_position = RelocInfo::kNoPosition; 2156 Handle<JSFunction> target_function; 2157 Handle<SharedFunctionInfo> target; 2158 Heap* heap = isolate_->heap(); 2159 while (!done) { 2160 { // Extra scope for iterator. 2161 HeapIterator iterator(heap); 2162 for (HeapObject* obj = iterator.next(); 2163 obj != NULL; obj = iterator.next()) { 2164 bool found_next_candidate = false; 2165 Handle<JSFunction> function; 2166 Handle<SharedFunctionInfo> shared; 2167 if (obj->IsJSFunction()) { 2168 function = Handle<JSFunction>(JSFunction::cast(obj)); 2169 shared = Handle<SharedFunctionInfo>(function->shared()); 2170 ASSERT(shared->allows_lazy_compilation() || shared->is_compiled()); 2171 found_next_candidate = true; 2172 } else if (obj->IsSharedFunctionInfo()) { 2173 shared = Handle<SharedFunctionInfo>(SharedFunctionInfo::cast(obj)); 2174 // Skip functions that we cannot compile lazily without a context, 2175 // which is not available here, because there is no closure. 2176 found_next_candidate = shared->is_compiled() || 2177 shared->allows_lazy_compilation_without_context(); 2178 } 2179 if (!found_next_candidate) continue; 2180 if (shared->script() == *script) { 2181 // If the SharedFunctionInfo found has the requested script data and 2182 // contains the source position it is a candidate. 2183 int start_position = shared->function_token_position(); 2184 if (start_position == RelocInfo::kNoPosition) { 2185 start_position = shared->start_position(); 2186 } 2187 if (start_position <= position && 2188 position <= shared->end_position()) { 2189 // If there is no candidate or this function is within the current 2190 // candidate this is the new candidate. 2191 if (target.is_null()) { 2192 target_start_position = start_position; 2193 target_function = function; 2194 target = shared; 2195 } else { 2196 if (target_start_position == start_position && 2197 shared->end_position() == target->end_position()) { 2198 // If a top-level function contains only one function 2199 // declaration the source for the top-level and the function 2200 // is the same. In that case prefer the non top-level function. 2201 if (!shared->is_toplevel()) { 2202 target_start_position = start_position; 2203 target_function = function; 2204 target = shared; 2205 } 2206 } else if (target_start_position <= start_position && 2207 shared->end_position() <= target->end_position()) { 2208 // This containment check includes equality as a function 2209 // inside a top-level function can share either start or end 2210 // position with the top-level function. 2211 target_start_position = start_position; 2212 target_function = function; 2213 target = shared; 2214 } 2215 } 2216 } 2217 } 2218 } // End for loop. 2219 } // End no-allocation scope. 2220 2221 if (target.is_null()) return heap->undefined_value(); 2222 2223 // There will be at least one break point when we are done. 2224 has_break_points_ = true; 2225 2226 // If the candidate found is compiled we are done. 2227 done = target->is_compiled(); 2228 if (!done) { 2229 // If the candidate is not compiled, compile it to reveal any inner 2230 // functions which might contain the requested source position. This 2231 // will compile all inner functions that cannot be compiled without a 2232 // context, because Compiler::BuildFunctionInfo checks whether the 2233 // debugger is active. 2234 MaybeHandle<Code> maybe_result = target_function.is_null() 2235 ? Compiler::GetUnoptimizedCode(target) 2236 : Compiler::GetUnoptimizedCode(target_function); 2237 if (maybe_result.is_null()) return isolate_->heap()->undefined_value(); 2238 } 2239 } // End while loop. 2240 2241 return *target; 2242 } 2243 2244 2245 // Ensures the debug information is present for shared. 2246 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared, 2247 Handle<JSFunction> function) { 2248 Isolate* isolate = shared->GetIsolate(); 2249 2250 // Return if we already have the debug info for shared. 2251 if (HasDebugInfo(shared)) { 2252 ASSERT(shared->is_compiled()); 2253 return true; 2254 } 2255 2256 // There will be at least one break point when we are done. 2257 has_break_points_ = true; 2258 2259 // Ensure function is compiled. Return false if this failed. 2260 if (!function.is_null() && 2261 !Compiler::EnsureCompiled(function, CLEAR_EXCEPTION)) { 2262 return false; 2263 } 2264 2265 // Create the debug info object. 2266 Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared); 2267 2268 // Add debug info to the list. 2269 DebugInfoListNode* node = new DebugInfoListNode(*debug_info); 2270 node->set_next(debug_info_list_); 2271 debug_info_list_ = node; 2272 2273 return true; 2274 } 2275 2276 2277 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) { 2278 ASSERT(debug_info_list_ != NULL); 2279 // Run through the debug info objects to find this one and remove it. 2280 DebugInfoListNode* prev = NULL; 2281 DebugInfoListNode* current = debug_info_list_; 2282 while (current != NULL) { 2283 if (*current->debug_info() == *debug_info) { 2284 // Unlink from list. If prev is NULL we are looking at the first element. 2285 if (prev == NULL) { 2286 debug_info_list_ = current->next(); 2287 } else { 2288 prev->set_next(current->next()); 2289 } 2290 current->debug_info()->shared()->set_debug_info( 2291 isolate_->heap()->undefined_value()); 2292 delete current; 2293 2294 // If there are no more debug info objects there are not more break 2295 // points. 2296 has_break_points_ = debug_info_list_ != NULL; 2297 2298 return; 2299 } 2300 // Move to next in list. 2301 prev = current; 2302 current = current->next(); 2303 } 2304 UNREACHABLE(); 2305 } 2306 2307 2308 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) { 2309 after_break_target_ = NULL; 2310 2311 if (LiveEdit::SetAfterBreakTarget(this)) return; // LiveEdit did the job. 2312 2313 HandleScope scope(isolate_); 2314 PrepareForBreakPoints(); 2315 2316 // Get the executing function in which the debug break occurred. 2317 Handle<JSFunction> function(JSFunction::cast(frame->function())); 2318 Handle<SharedFunctionInfo> shared(function->shared()); 2319 if (!EnsureDebugInfo(shared, function)) { 2320 // Return if we failed to retrieve the debug info. 2321 return; 2322 } 2323 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 2324 Handle<Code> code(debug_info->code()); 2325 Handle<Code> original_code(debug_info->original_code()); 2326 #ifdef DEBUG 2327 // Get the code which is actually executing. 2328 Handle<Code> frame_code(frame->LookupCode()); 2329 ASSERT(frame_code.is_identical_to(code)); 2330 #endif 2331 2332 // Find the call address in the running code. This address holds the call to 2333 // either a DebugBreakXXX or to the debug break return entry code if the 2334 // break point is still active after processing the break point. 2335 Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset; 2336 2337 // Check if the location is at JS exit or debug break slot. 2338 bool at_js_return = false; 2339 bool break_at_js_return_active = false; 2340 bool at_debug_break_slot = false; 2341 RelocIterator it(debug_info->code()); 2342 while (!it.done() && !at_js_return && !at_debug_break_slot) { 2343 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) { 2344 at_js_return = (it.rinfo()->pc() == 2345 addr - Assembler::kPatchReturnSequenceAddressOffset); 2346 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence(); 2347 } 2348 if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) { 2349 at_debug_break_slot = (it.rinfo()->pc() == 2350 addr - Assembler::kPatchDebugBreakSlotAddressOffset); 2351 } 2352 it.next(); 2353 } 2354 2355 // Handle the jump to continue execution after break point depending on the 2356 // break location. 2357 if (at_js_return) { 2358 // If the break point as return is still active jump to the corresponding 2359 // place in the original code. If not the break point was removed during 2360 // break point processing. 2361 if (break_at_js_return_active) { 2362 addr += original_code->instruction_start() - code->instruction_start(); 2363 } 2364 2365 // Move back to where the call instruction sequence started. 2366 after_break_target_ = addr - Assembler::kPatchReturnSequenceAddressOffset; 2367 } else if (at_debug_break_slot) { 2368 // Address of where the debug break slot starts. 2369 addr = addr - Assembler::kPatchDebugBreakSlotAddressOffset; 2370 2371 // Continue just after the slot. 2372 after_break_target_ = addr + Assembler::kDebugBreakSlotLength; 2373 } else if (IsDebugBreak(Assembler::target_address_at(addr, *code))) { 2374 // We now know that there is still a debug break call at the target address, 2375 // so the break point is still there and the original code will hold the 2376 // address to jump to in order to complete the call which is replaced by a 2377 // call to DebugBreakXXX. 2378 2379 // Find the corresponding address in the original code. 2380 addr += original_code->instruction_start() - code->instruction_start(); 2381 2382 // Install jump to the call address in the original code. This will be the 2383 // call which was overwritten by the call to DebugBreakXXX. 2384 after_break_target_ = Assembler::target_address_at(addr, *original_code); 2385 } else { 2386 // There is no longer a break point present. Don't try to look in the 2387 // original code as the running code will have the right address. This takes 2388 // care of the case where the last break point is removed from the function 2389 // and therefore no "original code" is available. 2390 after_break_target_ = Assembler::target_address_at(addr, *code); 2391 } 2392 } 2393 2394 2395 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) { 2396 HandleScope scope(isolate_); 2397 2398 // If there are no break points this cannot be break at return, as 2399 // the debugger statement and stack guard bebug break cannot be at 2400 // return. 2401 if (!has_break_points_) { 2402 return false; 2403 } 2404 2405 PrepareForBreakPoints(); 2406 2407 // Get the executing function in which the debug break occurred. 2408 Handle<JSFunction> function(JSFunction::cast(frame->function())); 2409 Handle<SharedFunctionInfo> shared(function->shared()); 2410 if (!EnsureDebugInfo(shared, function)) { 2411 // Return if we failed to retrieve the debug info. 2412 return false; 2413 } 2414 Handle<DebugInfo> debug_info = GetDebugInfo(shared); 2415 Handle<Code> code(debug_info->code()); 2416 #ifdef DEBUG 2417 // Get the code which is actually executing. 2418 Handle<Code> frame_code(frame->LookupCode()); 2419 ASSERT(frame_code.is_identical_to(code)); 2420 #endif 2421 2422 // Find the call address in the running code. 2423 Address addr = frame->pc() - Assembler::kPatchDebugBreakSlotReturnOffset; 2424 2425 // Check if the location is at JS return. 2426 RelocIterator it(debug_info->code()); 2427 while (!it.done()) { 2428 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) { 2429 return (it.rinfo()->pc() == 2430 addr - Assembler::kPatchReturnSequenceAddressOffset); 2431 } 2432 it.next(); 2433 } 2434 return false; 2435 } 2436 2437 2438 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id, 2439 LiveEdit::FrameDropMode mode, 2440 Object** restarter_frame_function_pointer) { 2441 if (mode != LiveEdit::CURRENTLY_SET_MODE) { 2442 thread_local_.frame_drop_mode_ = mode; 2443 } 2444 thread_local_.break_frame_id_ = new_break_frame_id; 2445 thread_local_.restarter_frame_function_pointer_ = 2446 restarter_frame_function_pointer; 2447 } 2448 2449 2450 bool Debug::IsDebugGlobal(GlobalObject* global) { 2451 return is_loaded() && global == debug_context()->global_object(); 2452 } 2453 2454 2455 void Debug::ClearMirrorCache() { 2456 PostponeInterruptsScope postpone(isolate_); 2457 HandleScope scope(isolate_); 2458 AssertDebugContext(); 2459 Factory* factory = isolate_->factory(); 2460 JSObject::SetProperty(isolate_->global_object(), 2461 factory->NewStringFromAsciiChecked("next_handle_"), 2462 handle(Smi::FromInt(0), isolate_), 2463 NONE, 2464 SLOPPY).Check(); 2465 JSObject::SetProperty(isolate_->global_object(), 2466 factory->NewStringFromAsciiChecked("mirror_cache_"), 2467 factory->NewJSArray(0, FAST_ELEMENTS), 2468 NONE, 2469 SLOPPY).Check(); 2470 } 2471 2472 2473 Handle<FixedArray> Debug::GetLoadedScripts() { 2474 // Create and fill the script cache when the loaded scripts is requested for 2475 // the first time. 2476 if (script_cache_ == NULL) script_cache_ = new ScriptCache(isolate_); 2477 2478 // Perform GC to get unreferenced scripts evicted from the cache before 2479 // returning the content. 2480 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, 2481 "Debug::GetLoadedScripts"); 2482 2483 // Get the scripts from the cache. 2484 return script_cache_->GetScripts(); 2485 } 2486 2487 2488 void Debug::RecordEvalCaller(Handle<Script> script) { 2489 script->set_compilation_type(Script::COMPILATION_TYPE_EVAL); 2490 // For eval scripts add information on the function from which eval was 2491 // called. 2492 StackTraceFrameIterator it(script->GetIsolate()); 2493 if (!it.done()) { 2494 script->set_eval_from_shared(it.frame()->function()->shared()); 2495 Code* code = it.frame()->LookupCode(); 2496 int offset = static_cast<int>( 2497 it.frame()->pc() - code->instruction_start()); 2498 script->set_eval_from_instructions_offset(Smi::FromInt(offset)); 2499 } 2500 } 2501 2502 2503 void Debug::AfterGarbageCollection() { 2504 // Generate events for collected scripts. 2505 if (script_cache_ != NULL) { 2506 script_cache_->ProcessCollectedScripts(); 2507 } 2508 } 2509 2510 2511 MaybeHandle<Object> Debug::MakeJSObject(const char* constructor_name, 2512 int argc, 2513 Handle<Object> argv[]) { 2514 AssertDebugContext(); 2515 // Create the execution state object. 2516 Handle<Object> constructor = Object::GetProperty( 2517 isolate_, isolate_->global_object(), constructor_name).ToHandleChecked(); 2518 ASSERT(constructor->IsJSFunction()); 2519 if (!constructor->IsJSFunction()) return MaybeHandle<Object>(); 2520 // We do not handle interrupts here. In particular, termination interrupts. 2521 PostponeInterruptsScope no_interrupts(isolate_); 2522 return Execution::TryCall(Handle<JSFunction>::cast(constructor), 2523 Handle<JSObject>(debug_context()->global_object()), 2524 argc, 2525 argv); 2526 } 2527 2528 2529 MaybeHandle<Object> Debug::MakeExecutionState() { 2530 // Create the execution state object. 2531 Handle<Object> argv[] = { isolate_->factory()->NewNumberFromInt(break_id()) }; 2532 return MakeJSObject("MakeExecutionState", ARRAY_SIZE(argv), argv); 2533 } 2534 2535 2536 MaybeHandle<Object> Debug::MakeBreakEvent(Handle<Object> break_points_hit) { 2537 Handle<Object> exec_state; 2538 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); 2539 // Create the new break event object. 2540 Handle<Object> argv[] = { exec_state, break_points_hit }; 2541 return MakeJSObject("MakeBreakEvent", ARRAY_SIZE(argv), argv); 2542 } 2543 2544 2545 MaybeHandle<Object> Debug::MakeExceptionEvent(Handle<Object> exception, 2546 bool uncaught, 2547 Handle<Object> promise) { 2548 Handle<Object> exec_state; 2549 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); 2550 // Create the new exception event object. 2551 Handle<Object> argv[] = { exec_state, 2552 exception, 2553 isolate_->factory()->ToBoolean(uncaught), 2554 promise }; 2555 return MakeJSObject("MakeExceptionEvent", ARRAY_SIZE(argv), argv); 2556 } 2557 2558 2559 MaybeHandle<Object> Debug::MakeCompileEvent(Handle<Script> script, 2560 bool before) { 2561 Handle<Object> exec_state; 2562 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); 2563 // Create the compile event object. 2564 Handle<Object> script_wrapper = Script::GetWrapper(script); 2565 Handle<Object> argv[] = { exec_state, 2566 script_wrapper, 2567 isolate_->factory()->ToBoolean(before) }; 2568 return MakeJSObject("MakeCompileEvent", ARRAY_SIZE(argv), argv); 2569 } 2570 2571 2572 MaybeHandle<Object> Debug::MakeScriptCollectedEvent(int id) { 2573 Handle<Object> exec_state; 2574 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); 2575 // Create the script collected event object. 2576 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); 2577 Handle<Object> argv[] = { exec_state, id_object }; 2578 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); 2579 } 2580 2581 2582 void Debug::OnException(Handle<Object> exception, bool uncaught) { 2583 if (in_debug_scope() || ignore_events()) return; 2584 2585 HandleScope scope(isolate_); 2586 Handle<Object> promise = GetPromiseForUncaughtException(); 2587 uncaught |= !promise->IsUndefined(); 2588 2589 // Bail out if exception breaks are not active 2590 if (uncaught) { 2591 // Uncaught exceptions are reported by either flags. 2592 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; 2593 } else { 2594 // Caught exceptions are reported is activated. 2595 if (!break_on_exception_) return; 2596 } 2597 2598 DebugScope debug_scope(this); 2599 if (debug_scope.failed()) return; 2600 2601 // Clear all current stepping setup. 2602 ClearStepping(); 2603 2604 // Create the event data object. 2605 Handle<Object> event_data; 2606 // Bail out and don't call debugger if exception. 2607 if (!MakeExceptionEvent( 2608 exception, uncaught, promise).ToHandle(&event_data)) { 2609 return; 2610 } 2611 2612 // Process debug event. 2613 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); 2614 // Return to continue execution from where the exception was thrown. 2615 } 2616 2617 2618 void Debug::OnDebugBreak(Handle<Object> break_points_hit, 2619 bool auto_continue) { 2620 // The caller provided for DebugScope. 2621 AssertDebugContext(); 2622 // Bail out if there is no listener for this event 2623 if (ignore_events()) return; 2624 2625 HandleScope scope(isolate_); 2626 // Create the event data object. 2627 Handle<Object> event_data; 2628 // Bail out and don't call debugger if exception. 2629 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; 2630 2631 // Process debug event. 2632 ProcessDebugEvent(v8::Break, 2633 Handle<JSObject>::cast(event_data), 2634 auto_continue); 2635 } 2636 2637 2638 void Debug::OnBeforeCompile(Handle<Script> script) { 2639 if (in_debug_scope() || ignore_events()) return; 2640 2641 HandleScope scope(isolate_); 2642 DebugScope debug_scope(this); 2643 if (debug_scope.failed()) return; 2644 2645 // Create the event data object. 2646 Handle<Object> event_data; 2647 // Bail out and don't call debugger if exception. 2648 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; 2649 2650 // Process debug event. 2651 ProcessDebugEvent(v8::BeforeCompile, 2652 Handle<JSObject>::cast(event_data), 2653 true); 2654 } 2655 2656 2657 // Handle debugger actions when a new script is compiled. 2658 void Debug::OnAfterCompile(Handle<Script> script, 2659 AfterCompileFlags after_compile_flags) { 2660 // Add the newly compiled script to the script cache. 2661 if (script_cache_ != NULL) script_cache_->Add(script); 2662 2663 // No more to do if not debugging. 2664 if (in_debug_scope() || ignore_events()) return; 2665 2666 HandleScope scope(isolate_); 2667 // Store whether in debugger before entering debugger. 2668 bool was_in_scope = in_debug_scope(); 2669 2670 DebugScope debug_scope(this); 2671 if (debug_scope.failed()) return; 2672 2673 // If debugging there might be script break points registered for this 2674 // script. Make sure that these break points are set. 2675 2676 // Get the function UpdateScriptBreakPoints (defined in debug-debugger.js). 2677 Handle<String> update_script_break_points_string = 2678 isolate_->factory()->InternalizeOneByteString( 2679 STATIC_ASCII_VECTOR("UpdateScriptBreakPoints")); 2680 Handle<GlobalObject> debug_global(debug_context()->global_object()); 2681 Handle<Object> update_script_break_points = 2682 Object::GetProperty( 2683 debug_global, update_script_break_points_string).ToHandleChecked(); 2684 if (!update_script_break_points->IsJSFunction()) { 2685 return; 2686 } 2687 ASSERT(update_script_break_points->IsJSFunction()); 2688 2689 // Wrap the script object in a proper JS object before passing it 2690 // to JavaScript. 2691 Handle<Object> wrapper = Script::GetWrapper(script); 2692 2693 // Call UpdateScriptBreakPoints expect no exceptions. 2694 Handle<Object> argv[] = { wrapper }; 2695 if (Execution::TryCall(Handle<JSFunction>::cast(update_script_break_points), 2696 isolate_->js_builtins_object(), 2697 ARRAY_SIZE(argv), 2698 argv).is_null()) { 2699 return; 2700 } 2701 // Bail out based on state or if there is no listener for this event 2702 if (was_in_scope && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0) return; 2703 2704 // Create the compile state object. 2705 Handle<Object> event_data; 2706 // Bail out and don't call debugger if exception. 2707 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return; 2708 2709 // Process debug event. 2710 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); 2711 } 2712 2713 2714 void Debug::OnScriptCollected(int id) { 2715 if (in_debug_scope() || ignore_events()) return; 2716 2717 HandleScope scope(isolate_); 2718 DebugScope debug_scope(this); 2719 if (debug_scope.failed()) return; 2720 2721 // Create the script collected state object. 2722 Handle<Object> event_data; 2723 // Bail out and don't call debugger if exception. 2724 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; 2725 2726 // Process debug event. 2727 ProcessDebugEvent(v8::ScriptCollected, 2728 Handle<JSObject>::cast(event_data), 2729 true); 2730 } 2731 2732 2733 void Debug::ProcessDebugEvent(v8::DebugEvent event, 2734 Handle<JSObject> event_data, 2735 bool auto_continue) { 2736 HandleScope scope(isolate_); 2737 2738 // Create the execution state. 2739 Handle<Object> exec_state; 2740 // Bail out and don't call debugger if exception. 2741 if (!MakeExecutionState().ToHandle(&exec_state)) return; 2742 2743 // First notify the message handler if any. 2744 if (message_handler_ != NULL) { 2745 NotifyMessageHandler(event, 2746 Handle<JSObject>::cast(exec_state), 2747 event_data, 2748 auto_continue); 2749 } 2750 // Notify registered debug event listener. This can be either a C or 2751 // a JavaScript function. Don't call event listener for v8::Break 2752 // here, if it's only a debug command -- they will be processed later. 2753 if ((event != v8::Break || !auto_continue) && !event_listener_.is_null()) { 2754 CallEventCallback(event, exec_state, event_data, NULL); 2755 } 2756 // Process pending debug commands. 2757 if (event == v8::Break) { 2758 while (!event_command_queue_.IsEmpty()) { 2759 CommandMessage command = event_command_queue_.Get(); 2760 if (!event_listener_.is_null()) { 2761 CallEventCallback(v8::BreakForCommand, 2762 exec_state, 2763 event_data, 2764 command.client_data()); 2765 } 2766 command.Dispose(); 2767 } 2768 } 2769 } 2770 2771 2772 void Debug::CallEventCallback(v8::DebugEvent event, 2773 Handle<Object> exec_state, 2774 Handle<Object> event_data, 2775 v8::Debug::ClientData* client_data) { 2776 if (event_listener_->IsForeign()) { 2777 // Invoke the C debug event listener. 2778 v8::Debug::EventCallback callback = 2779 FUNCTION_CAST<v8::Debug::EventCallback>( 2780 Handle<Foreign>::cast(event_listener_)->foreign_address()); 2781 EventDetailsImpl event_details(event, 2782 Handle<JSObject>::cast(exec_state), 2783 Handle<JSObject>::cast(event_data), 2784 event_listener_data_, 2785 client_data); 2786 callback(event_details); 2787 ASSERT(!isolate_->has_scheduled_exception()); 2788 } else { 2789 // Invoke the JavaScript debug event listener. 2790 ASSERT(event_listener_->IsJSFunction()); 2791 Handle<Object> argv[] = { Handle<Object>(Smi::FromInt(event), isolate_), 2792 exec_state, 2793 event_data, 2794 event_listener_data_ }; 2795 Execution::TryCall(Handle<JSFunction>::cast(event_listener_), 2796 isolate_->global_object(), 2797 ARRAY_SIZE(argv), 2798 argv); 2799 } 2800 } 2801 2802 2803 Handle<Context> Debug::GetDebugContext() { 2804 DebugScope debug_scope(this); 2805 // The global handle may be destroyed soon after. Return it reboxed. 2806 return handle(*debug_context(), isolate_); 2807 } 2808 2809 2810 void Debug::NotifyMessageHandler(v8::DebugEvent event, 2811 Handle<JSObject> exec_state, 2812 Handle<JSObject> event_data, 2813 bool auto_continue) { 2814 // Prevent other interrupts from triggering, for example API callbacks, 2815 // while dispatching message handler callbacks. 2816 PostponeInterruptsScope no_interrupts(isolate_); 2817 ASSERT(is_active_); 2818 HandleScope scope(isolate_); 2819 // Process the individual events. 2820 bool sendEventMessage = false; 2821 switch (event) { 2822 case v8::Break: 2823 case v8::BreakForCommand: 2824 sendEventMessage = !auto_continue; 2825 break; 2826 case v8::Exception: 2827 sendEventMessage = true; 2828 break; 2829 case v8::BeforeCompile: 2830 break; 2831 case v8::AfterCompile: 2832 sendEventMessage = true; 2833 break; 2834 case v8::ScriptCollected: 2835 sendEventMessage = true; 2836 break; 2837 case v8::NewFunction: 2838 break; 2839 default: 2840 UNREACHABLE(); 2841 } 2842 2843 // The debug command interrupt flag might have been set when the command was 2844 // added. It should be enough to clear the flag only once while we are in the 2845 // debugger. 2846 ASSERT(in_debug_scope()); 2847 isolate_->stack_guard()->ClearDebugCommand(); 2848 2849 // Notify the debugger that a debug event has occurred unless auto continue is 2850 // active in which case no event is send. 2851 if (sendEventMessage) { 2852 MessageImpl message = MessageImpl::NewEvent( 2853 event, 2854 auto_continue, 2855 Handle<JSObject>::cast(exec_state), 2856 Handle<JSObject>::cast(event_data)); 2857 InvokeMessageHandler(message); 2858 } 2859 2860 // If auto continue don't make the event cause a break, but process messages 2861 // in the queue if any. For script collected events don't even process 2862 // messages in the queue as the execution state might not be what is expected 2863 // by the client. 2864 if ((auto_continue && !has_commands()) || event == v8::ScriptCollected) { 2865 return; 2866 } 2867 2868 // DebugCommandProcessor goes here. 2869 bool running = auto_continue; 2870 2871 Handle<Object> cmd_processor_ctor = Object::GetProperty( 2872 isolate_, exec_state, "debugCommandProcessor").ToHandleChecked(); 2873 Handle<Object> ctor_args[] = { isolate_->factory()->ToBoolean(running) }; 2874 Handle<Object> cmd_processor = Execution::Call( 2875 isolate_, cmd_processor_ctor, exec_state, 1, ctor_args).ToHandleChecked(); 2876 Handle<JSFunction> process_debug_request = Handle<JSFunction>::cast( 2877 Object::GetProperty( 2878 isolate_, cmd_processor, "processDebugRequest").ToHandleChecked()); 2879 Handle<Object> is_running = Object::GetProperty( 2880 isolate_, cmd_processor, "isRunning").ToHandleChecked(); 2881 2882 // Process requests from the debugger. 2883 do { 2884 // Wait for new command in the queue. 2885 command_received_.Wait(); 2886 2887 // Get the command from the queue. 2888 CommandMessage command = command_queue_.Get(); 2889 isolate_->logger()->DebugTag( 2890 "Got request from command queue, in interactive loop."); 2891 if (!is_active()) { 2892 // Delete command text and user data. 2893 command.Dispose(); 2894 return; 2895 } 2896 2897 Vector<const uc16> command_text( 2898 const_cast<const uc16*>(command.text().start()), 2899 command.text().length()); 2900 Handle<String> request_text = isolate_->factory()->NewStringFromTwoByte( 2901 command_text).ToHandleChecked(); 2902 Handle<Object> request_args[] = { request_text }; 2903 Handle<Object> exception; 2904 Handle<Object> answer_value; 2905 Handle<String> answer; 2906 MaybeHandle<Object> maybe_result = Execution::TryCall( 2907 process_debug_request, cmd_processor, 1, request_args, &exception); 2908 2909 if (maybe_result.ToHandle(&answer_value)) { 2910 if (answer_value->IsUndefined()) { 2911 answer = isolate_->factory()->empty_string(); 2912 } else { 2913 answer = Handle<String>::cast(answer_value); 2914 } 2915 2916 // Log the JSON request/response. 2917 if (FLAG_trace_debug_json) { 2918 PrintF("%s\n", request_text->ToCString().get()); 2919 PrintF("%s\n", answer->ToCString().get()); 2920 } 2921 2922 Handle<Object> is_running_args[] = { answer }; 2923 maybe_result = Execution::Call( 2924 isolate_, is_running, cmd_processor, 1, is_running_args); 2925 running = maybe_result.ToHandleChecked()->IsTrue(); 2926 } else { 2927 answer = Handle<String>::cast( 2928 Execution::ToString(isolate_, exception).ToHandleChecked()); 2929 } 2930 2931 // Return the result. 2932 MessageImpl message = MessageImpl::NewResponse( 2933 event, running, exec_state, event_data, answer, command.client_data()); 2934 InvokeMessageHandler(message); 2935 command.Dispose(); 2936 2937 // Return from debug event processing if either the VM is put into the 2938 // running state (through a continue command) or auto continue is active 2939 // and there are no more commands queued. 2940 } while (!running || has_commands()); 2941 } 2942 2943 2944 void Debug::SetEventListener(Handle<Object> callback, 2945 Handle<Object> data) { 2946 GlobalHandles* global_handles = isolate_->global_handles(); 2947 2948 // Remove existing entry. 2949 GlobalHandles::Destroy(event_listener_.location()); 2950 event_listener_ = Handle<Object>(); 2951 GlobalHandles::Destroy(event_listener_data_.location()); 2952 event_listener_data_ = Handle<Object>(); 2953 2954 // Set new entry. 2955 if (!callback->IsUndefined() && !callback->IsNull()) { 2956 event_listener_ = global_handles->Create(*callback); 2957 if (data.is_null()) data = isolate_->factory()->undefined_value(); 2958 event_listener_data_ = global_handles->Create(*data); 2959 } 2960 2961 UpdateState(); 2962 } 2963 2964 2965 void Debug::SetMessageHandler(v8::Debug::MessageHandler handler) { 2966 message_handler_ = handler; 2967 UpdateState(); 2968 if (handler == NULL && in_debug_scope()) { 2969 // Send an empty command to the debugger if in a break to make JavaScript 2970 // run again if the debugger is closed. 2971 EnqueueCommandMessage(Vector<const uint16_t>::empty()); 2972 } 2973 } 2974 2975 2976 2977 void Debug::UpdateState() { 2978 is_active_ = message_handler_ != NULL || !event_listener_.is_null(); 2979 if (is_active_ || in_debug_scope()) { 2980 // Note that the debug context could have already been loaded to 2981 // bootstrap test cases. 2982 isolate_->compilation_cache()->Disable(); 2983 is_active_ = Load(); 2984 } else if (is_loaded()) { 2985 isolate_->compilation_cache()->Enable(); 2986 Unload(); 2987 } 2988 } 2989 2990 2991 // Calls the registered debug message handler. This callback is part of the 2992 // public API. 2993 void Debug::InvokeMessageHandler(MessageImpl message) { 2994 if (message_handler_ != NULL) message_handler_(message); 2995 } 2996 2997 2998 // Puts a command coming from the public API on the queue. Creates 2999 // a copy of the command string managed by the debugger. Up to this 3000 // point, the command data was managed by the API client. Called 3001 // by the API client thread. 3002 void Debug::EnqueueCommandMessage(Vector<const uint16_t> command, 3003 v8::Debug::ClientData* client_data) { 3004 // Need to cast away const. 3005 CommandMessage message = CommandMessage::New( 3006 Vector<uint16_t>(const_cast<uint16_t*>(command.start()), 3007 command.length()), 3008 client_data); 3009 isolate_->logger()->DebugTag("Put command on command_queue."); 3010 command_queue_.Put(message); 3011 command_received_.Signal(); 3012 3013 // Set the debug command break flag to have the command processed. 3014 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand(); 3015 } 3016 3017 3018 void Debug::EnqueueDebugCommand(v8::Debug::ClientData* client_data) { 3019 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data); 3020 event_command_queue_.Put(message); 3021 3022 // Set the debug command break flag to have the command processed. 3023 if (!in_debug_scope()) isolate_->stack_guard()->RequestDebugCommand(); 3024 } 3025 3026 3027 MaybeHandle<Object> Debug::Call(Handle<JSFunction> fun, Handle<Object> data) { 3028 DebugScope debug_scope(this); 3029 if (debug_scope.failed()) return isolate_->factory()->undefined_value(); 3030 3031 // Create the execution state. 3032 Handle<Object> exec_state; 3033 if (!MakeExecutionState().ToHandle(&exec_state)) { 3034 return isolate_->factory()->undefined_value(); 3035 } 3036 3037 Handle<Object> argv[] = { exec_state, data }; 3038 return Execution::Call( 3039 isolate_, 3040 fun, 3041 Handle<Object>(debug_context()->global_proxy(), isolate_), 3042 ARRAY_SIZE(argv), 3043 argv); 3044 } 3045 3046 3047 void Debug::HandleDebugBreak() { 3048 // Ignore debug break during bootstrapping. 3049 if (isolate_->bootstrapper()->IsActive()) return; 3050 // Just continue if breaks are disabled. 3051 if (break_disabled_) return; 3052 // Ignore debug break if debugger is not active. 3053 if (!is_active()) return; 3054 3055 StackLimitCheck check(isolate_); 3056 if (check.HasOverflowed()) return; 3057 3058 { JavaScriptFrameIterator it(isolate_); 3059 ASSERT(!it.done()); 3060 Object* fun = it.frame()->function(); 3061 if (fun && fun->IsJSFunction()) { 3062 // Don't stop in builtin functions. 3063 if (JSFunction::cast(fun)->IsBuiltin()) return; 3064 GlobalObject* global = JSFunction::cast(fun)->context()->global_object(); 3065 // Don't stop in debugger functions. 3066 if (IsDebugGlobal(global)) return; 3067 } 3068 } 3069 3070 // Collect the break state before clearing the flags. 3071 bool debug_command_only = isolate_->stack_guard()->CheckDebugCommand() && 3072 !isolate_->stack_guard()->CheckDebugBreak(); 3073 3074 isolate_->stack_guard()->ClearDebugBreak(); 3075 3076 ProcessDebugMessages(debug_command_only); 3077 } 3078 3079 3080 void Debug::ProcessDebugMessages(bool debug_command_only) { 3081 isolate_->stack_guard()->ClearDebugCommand(); 3082 3083 StackLimitCheck check(isolate_); 3084 if (check.HasOverflowed()) return; 3085 3086 HandleScope scope(isolate_); 3087 DebugScope debug_scope(this); 3088 if (debug_scope.failed()) return; 3089 3090 // Notify the debug event listeners. Indicate auto continue if the break was 3091 // a debug command break. 3092 OnDebugBreak(isolate_->factory()->undefined_value(), debug_command_only); 3093 } 3094 3095 3096 DebugScope::DebugScope(Debug* debug) : debug_(debug), 3097 prev_(debug->debugger_entry()), 3098 save_(debug_->isolate_) { 3099 // Link recursive debugger entry. 3100 debug_->thread_local_.current_debug_scope_ = this; 3101 3102 // Store the previous break id and frame id. 3103 break_id_ = debug_->break_id(); 3104 break_frame_id_ = debug_->break_frame_id(); 3105 3106 // Create the new break info. If there is no JavaScript frames there is no 3107 // break frame id. 3108 JavaScriptFrameIterator it(isolate()); 3109 bool has_js_frames = !it.done(); 3110 debug_->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id() 3111 : StackFrame::NO_ID; 3112 debug_->SetNextBreakId(); 3113 3114 debug_->UpdateState(); 3115 // Make sure that debugger is loaded and enter the debugger context. 3116 // The previous context is kept in save_. 3117 failed_ = !debug_->is_loaded(); 3118 if (!failed_) isolate()->set_context(*debug->debug_context()); 3119 } 3120 3121 3122 3123 DebugScope::~DebugScope() { 3124 if (!failed_ && prev_ == NULL) { 3125 // Clear mirror cache when leaving the debugger. Skip this if there is a 3126 // pending exception as clearing the mirror cache calls back into 3127 // JavaScript. This can happen if the v8::Debug::Call is used in which 3128 // case the exception should end up in the calling code. 3129 if (!isolate()->has_pending_exception()) debug_->ClearMirrorCache(); 3130 3131 // If there are commands in the queue when leaving the debugger request 3132 // that these commands are processed. 3133 if (debug_->has_commands()) isolate()->stack_guard()->RequestDebugCommand(); 3134 } 3135 3136 // Leaving this debugger entry. 3137 debug_->thread_local_.current_debug_scope_ = prev_; 3138 3139 // Restore to the previous break state. 3140 debug_->thread_local_.break_frame_id_ = break_frame_id_; 3141 debug_->thread_local_.break_id_ = break_id_; 3142 3143 debug_->UpdateState(); 3144 } 3145 3146 3147 MessageImpl MessageImpl::NewEvent(DebugEvent event, 3148 bool running, 3149 Handle<JSObject> exec_state, 3150 Handle<JSObject> event_data) { 3151 MessageImpl message(true, event, running, 3152 exec_state, event_data, Handle<String>(), NULL); 3153 return message; 3154 } 3155 3156 3157 MessageImpl MessageImpl::NewResponse(DebugEvent event, 3158 bool running, 3159 Handle<JSObject> exec_state, 3160 Handle<JSObject> event_data, 3161 Handle<String> response_json, 3162 v8::Debug::ClientData* client_data) { 3163 MessageImpl message(false, event, running, 3164 exec_state, event_data, response_json, client_data); 3165 return message; 3166 } 3167 3168 3169 MessageImpl::MessageImpl(bool is_event, 3170 DebugEvent event, 3171 bool running, 3172 Handle<JSObject> exec_state, 3173 Handle<JSObject> event_data, 3174 Handle<String> response_json, 3175 v8::Debug::ClientData* client_data) 3176 : is_event_(is_event), 3177 event_(event), 3178 running_(running), 3179 exec_state_(exec_state), 3180 event_data_(event_data), 3181 response_json_(response_json), 3182 client_data_(client_data) {} 3183 3184 3185 bool MessageImpl::IsEvent() const { 3186 return is_event_; 3187 } 3188 3189 3190 bool MessageImpl::IsResponse() const { 3191 return !is_event_; 3192 } 3193 3194 3195 DebugEvent MessageImpl::GetEvent() const { 3196 return event_; 3197 } 3198 3199 3200 bool MessageImpl::WillStartRunning() const { 3201 return running_; 3202 } 3203 3204 3205 v8::Handle<v8::Object> MessageImpl::GetExecutionState() const { 3206 return v8::Utils::ToLocal(exec_state_); 3207 } 3208 3209 3210 v8::Isolate* MessageImpl::GetIsolate() const { 3211 return reinterpret_cast<v8::Isolate*>(exec_state_->GetIsolate()); 3212 } 3213 3214 3215 v8::Handle<v8::Object> MessageImpl::GetEventData() const { 3216 return v8::Utils::ToLocal(event_data_); 3217 } 3218 3219 3220 v8::Handle<v8::String> MessageImpl::GetJSON() const { 3221 Isolate* isolate = event_data_->GetIsolate(); 3222 v8::EscapableHandleScope scope(reinterpret_cast<v8::Isolate*>(isolate)); 3223 3224 if (IsEvent()) { 3225 // Call toJSONProtocol on the debug event object. 3226 Handle<Object> fun = Object::GetProperty( 3227 isolate, event_data_, "toJSONProtocol").ToHandleChecked(); 3228 if (!fun->IsJSFunction()) { 3229 return v8::Handle<v8::String>(); 3230 } 3231 3232 MaybeHandle<Object> maybe_json = 3233 Execution::TryCall(Handle<JSFunction>::cast(fun), event_data_, 0, NULL); 3234 Handle<Object> json; 3235 if (!maybe_json.ToHandle(&json) || !json->IsString()) { 3236 return v8::Handle<v8::String>(); 3237 } 3238 return scope.Escape(v8::Utils::ToLocal(Handle<String>::cast(json))); 3239 } else { 3240 return v8::Utils::ToLocal(response_json_); 3241 } 3242 } 3243 3244 3245 v8::Handle<v8::Context> MessageImpl::GetEventContext() const { 3246 Isolate* isolate = event_data_->GetIsolate(); 3247 v8::Handle<v8::Context> context = GetDebugEventContext(isolate); 3248 // Isolate::context() may be NULL when "script collected" event occures. 3249 ASSERT(!context.IsEmpty() || event_ == v8::ScriptCollected); 3250 return context; 3251 } 3252 3253 3254 v8::Debug::ClientData* MessageImpl::GetClientData() const { 3255 return client_data_; 3256 } 3257 3258 3259 EventDetailsImpl::EventDetailsImpl(DebugEvent event, 3260 Handle<JSObject> exec_state, 3261 Handle<JSObject> event_data, 3262 Handle<Object> callback_data, 3263 v8::Debug::ClientData* client_data) 3264 : event_(event), 3265 exec_state_(exec_state), 3266 event_data_(event_data), 3267 callback_data_(callback_data), 3268 client_data_(client_data) {} 3269 3270 3271 DebugEvent EventDetailsImpl::GetEvent() const { 3272 return event_; 3273 } 3274 3275 3276 v8::Handle<v8::Object> EventDetailsImpl::GetExecutionState() const { 3277 return v8::Utils::ToLocal(exec_state_); 3278 } 3279 3280 3281 v8::Handle<v8::Object> EventDetailsImpl::GetEventData() const { 3282 return v8::Utils::ToLocal(event_data_); 3283 } 3284 3285 3286 v8::Handle<v8::Context> EventDetailsImpl::GetEventContext() const { 3287 return GetDebugEventContext(exec_state_->GetIsolate()); 3288 } 3289 3290 3291 v8::Handle<v8::Value> EventDetailsImpl::GetCallbackData() const { 3292 return v8::Utils::ToLocal(callback_data_); 3293 } 3294 3295 3296 v8::Debug::ClientData* EventDetailsImpl::GetClientData() const { 3297 return client_data_; 3298 } 3299 3300 3301 CommandMessage::CommandMessage() : text_(Vector<uint16_t>::empty()), 3302 client_data_(NULL) { 3303 } 3304 3305 3306 CommandMessage::CommandMessage(const Vector<uint16_t>& text, 3307 v8::Debug::ClientData* data) 3308 : text_(text), 3309 client_data_(data) { 3310 } 3311 3312 3313 void CommandMessage::Dispose() { 3314 text_.Dispose(); 3315 delete client_data_; 3316 client_data_ = NULL; 3317 } 3318 3319 3320 CommandMessage CommandMessage::New(const Vector<uint16_t>& command, 3321 v8::Debug::ClientData* data) { 3322 return CommandMessage(command.Clone(), data); 3323 } 3324 3325 3326 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0), 3327 size_(size) { 3328 messages_ = NewArray<CommandMessage>(size); 3329 } 3330 3331 3332 CommandMessageQueue::~CommandMessageQueue() { 3333 while (!IsEmpty()) Get().Dispose(); 3334 DeleteArray(messages_); 3335 } 3336 3337 3338 CommandMessage CommandMessageQueue::Get() { 3339 ASSERT(!IsEmpty()); 3340 int result = start_; 3341 start_ = (start_ + 1) % size_; 3342 return messages_[result]; 3343 } 3344 3345 3346 void CommandMessageQueue::Put(const CommandMessage& message) { 3347 if ((end_ + 1) % size_ == start_) { 3348 Expand(); 3349 } 3350 messages_[end_] = message; 3351 end_ = (end_ + 1) % size_; 3352 } 3353 3354 3355 void CommandMessageQueue::Expand() { 3356 CommandMessageQueue new_queue(size_ * 2); 3357 while (!IsEmpty()) { 3358 new_queue.Put(Get()); 3359 } 3360 CommandMessage* array_to_free = messages_; 3361 *this = new_queue; 3362 new_queue.messages_ = array_to_free; 3363 // Make the new_queue empty so that it doesn't call Dispose on any messages. 3364 new_queue.start_ = new_queue.end_; 3365 // Automatic destructor called on new_queue, freeing array_to_free. 3366 } 3367 3368 3369 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size) 3370 : logger_(logger), queue_(size) {} 3371 3372 3373 bool LockingCommandMessageQueue::IsEmpty() const { 3374 LockGuard<Mutex> lock_guard(&mutex_); 3375 return queue_.IsEmpty(); 3376 } 3377 3378 3379 CommandMessage LockingCommandMessageQueue::Get() { 3380 LockGuard<Mutex> lock_guard(&mutex_); 3381 CommandMessage result = queue_.Get(); 3382 logger_->DebugEvent("Get", result.text()); 3383 return result; 3384 } 3385 3386 3387 void LockingCommandMessageQueue::Put(const CommandMessage& message) { 3388 LockGuard<Mutex> lock_guard(&mutex_); 3389 queue_.Put(message); 3390 logger_->DebugEvent("Put", message.text()); 3391 } 3392 3393 3394 void LockingCommandMessageQueue::Clear() { 3395 LockGuard<Mutex> lock_guard(&mutex_); 3396 queue_.Clear(); 3397 } 3398 3399 } } // namespace v8::internal 3400