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