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