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