OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "v8.h" | 5 #include "v8.h" |
6 | 6 |
7 #include "api.h" | 7 #include "api.h" |
8 #include "arguments.h" | 8 #include "arguments.h" |
9 #include "bootstrapper.h" | 9 #include "bootstrapper.h" |
10 #include "code-stubs.h" | 10 #include "code-stubs.h" |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 | 73 |
74 | 74 |
75 BreakLocationIterator::~BreakLocationIterator() { | 75 BreakLocationIterator::~BreakLocationIterator() { |
76 ASSERT(reloc_iterator_ != NULL); | 76 ASSERT(reloc_iterator_ != NULL); |
77 ASSERT(reloc_iterator_original_ != NULL); | 77 ASSERT(reloc_iterator_original_ != NULL); |
78 delete reloc_iterator_; | 78 delete reloc_iterator_; |
79 delete reloc_iterator_original_; | 79 delete reloc_iterator_original_; |
80 } | 80 } |
81 | 81 |
82 | 82 |
| 83 // Check whether a code stub with the specified major key is a possible break |
| 84 // point location when looking for source break locations. |
| 85 static bool IsSourceBreakStub(Code* code) { |
| 86 CodeStub::Major major_key = CodeStub::GetMajorKey(code); |
| 87 return major_key == CodeStub::CallFunction; |
| 88 } |
| 89 |
| 90 |
| 91 // Check whether a code stub with the specified major key is a possible break |
| 92 // location. |
| 93 static bool IsBreakStub(Code* code) { |
| 94 CodeStub::Major major_key = CodeStub::GetMajorKey(code); |
| 95 return major_key == CodeStub::CallFunction; |
| 96 } |
| 97 |
| 98 |
83 void BreakLocationIterator::Next() { | 99 void BreakLocationIterator::Next() { |
84 DisallowHeapAllocation no_gc; | 100 DisallowHeapAllocation no_gc; |
85 ASSERT(!RinfoDone()); | 101 ASSERT(!RinfoDone()); |
86 | 102 |
87 // Iterate through reloc info for code and original code stopping at each | 103 // Iterate through reloc info for code and original code stopping at each |
88 // breakable code target. | 104 // breakable code target. |
89 bool first = break_point_ == -1; | 105 bool first = break_point_ == -1; |
90 while (!RinfoDone()) { | 106 while (!RinfoDone()) { |
91 if (!first) RinfoNext(); | 107 if (!first) RinfoNext(); |
92 first = false; | 108 first = false; |
(...skipping 29 matching lines...) Expand all Loading... |
122 !code->is_compare_ic_stub() && | 138 !code->is_compare_ic_stub() && |
123 !code->is_to_boolean_ic_stub()) || | 139 !code->is_to_boolean_ic_stub()) || |
124 RelocInfo::IsConstructCall(rmode())) { | 140 RelocInfo::IsConstructCall(rmode())) { |
125 break_point_++; | 141 break_point_++; |
126 return; | 142 return; |
127 } | 143 } |
128 if (code->kind() == Code::STUB) { | 144 if (code->kind() == Code::STUB) { |
129 if (IsDebuggerStatement()) { | 145 if (IsDebuggerStatement()) { |
130 break_point_++; | 146 break_point_++; |
131 return; | 147 return; |
132 } | 148 } else if (type_ == ALL_BREAK_LOCATIONS) { |
133 if (type_ == ALL_BREAK_LOCATIONS) { | 149 if (IsBreakStub(code)) { |
134 if (Debug::IsBreakStub(code)) { | |
135 break_point_++; | 150 break_point_++; |
136 return; | 151 return; |
137 } | 152 } |
138 } else { | 153 } else { |
139 ASSERT(type_ == SOURCE_BREAK_LOCATIONS); | 154 ASSERT(type_ == SOURCE_BREAK_LOCATIONS); |
140 if (Debug::IsSourceBreakStub(code)) { | 155 if (IsSourceBreakStub(code)) { |
141 break_point_++; | 156 break_point_++; |
142 return; | 157 return; |
143 } | 158 } |
144 } | 159 } |
145 } | 160 } |
146 } | 161 } |
147 | 162 |
148 // Check for break at return. | 163 // Check for break at return. |
149 if (RelocInfo::IsJSReturn(rmode())) { | 164 if (RelocInfo::IsJSReturn(rmode())) { |
150 // Set the positions to the end of the function. | 165 // Set the positions to the end of the function. |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 if (RelocInfo::IsJSReturn(rmode())) { | 430 if (RelocInfo::IsJSReturn(rmode())) { |
416 return IsDebugBreakAtReturn(); | 431 return IsDebugBreakAtReturn(); |
417 } else if (IsDebugBreakSlot()) { | 432 } else if (IsDebugBreakSlot()) { |
418 return IsDebugBreakAtSlot(); | 433 return IsDebugBreakAtSlot(); |
419 } else { | 434 } else { |
420 return Debug::IsDebugBreak(rinfo()->target_address()); | 435 return Debug::IsDebugBreak(rinfo()->target_address()); |
421 } | 436 } |
422 } | 437 } |
423 | 438 |
424 | 439 |
| 440 // Find the builtin to use for invoking the debug break |
| 441 static Handle<Code> DebugBreakForIC(Handle<Code> code, RelocInfo::Mode mode) { |
| 442 Isolate* isolate = code->GetIsolate(); |
| 443 |
| 444 // Find the builtin debug break function matching the calling convention |
| 445 // used by the call site. |
| 446 if (code->is_inline_cache_stub()) { |
| 447 switch (code->kind()) { |
| 448 case Code::CALL_IC: |
| 449 return isolate->builtins()->CallICStub_DebugBreak(); |
| 450 |
| 451 case Code::LOAD_IC: |
| 452 return isolate->builtins()->LoadIC_DebugBreak(); |
| 453 |
| 454 case Code::STORE_IC: |
| 455 return isolate->builtins()->StoreIC_DebugBreak(); |
| 456 |
| 457 case Code::KEYED_LOAD_IC: |
| 458 return isolate->builtins()->KeyedLoadIC_DebugBreak(); |
| 459 |
| 460 case Code::KEYED_STORE_IC: |
| 461 return isolate->builtins()->KeyedStoreIC_DebugBreak(); |
| 462 |
| 463 case Code::COMPARE_NIL_IC: |
| 464 return isolate->builtins()->CompareNilIC_DebugBreak(); |
| 465 |
| 466 default: |
| 467 UNREACHABLE(); |
| 468 } |
| 469 } |
| 470 if (RelocInfo::IsConstructCall(mode)) { |
| 471 if (code->has_function_cache()) { |
| 472 return isolate->builtins()->CallConstructStub_Recording_DebugBreak(); |
| 473 } else { |
| 474 return isolate->builtins()->CallConstructStub_DebugBreak(); |
| 475 } |
| 476 } |
| 477 if (code->kind() == Code::STUB) { |
| 478 ASSERT(code->major_key() == CodeStub::CallFunction); |
| 479 return isolate->builtins()->CallFunctionStub_DebugBreak(); |
| 480 } |
| 481 |
| 482 UNREACHABLE(); |
| 483 return Handle<Code>::null(); |
| 484 } |
| 485 |
| 486 |
425 void BreakLocationIterator::SetDebugBreakAtIC() { | 487 void BreakLocationIterator::SetDebugBreakAtIC() { |
426 // Patch the original code with the current address as the current address | 488 // Patch the original code with the current address as the current address |
427 // might have changed by the inline caching since the code was copied. | 489 // might have changed by the inline caching since the code was copied. |
428 original_rinfo()->set_target_address(rinfo()->target_address()); | 490 original_rinfo()->set_target_address(rinfo()->target_address()); |
429 | 491 |
430 RelocInfo::Mode mode = rmode(); | 492 RelocInfo::Mode mode = rmode(); |
431 if (RelocInfo::IsCodeTarget(mode)) { | 493 if (RelocInfo::IsCodeTarget(mode)) { |
432 Address target = rinfo()->target_address(); | 494 Address target = rinfo()->target_address(); |
433 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); | 495 Handle<Code> target_code(Code::GetCodeFromTargetAddress(target)); |
434 | 496 |
435 // Patch the code to invoke the builtin debug break function matching the | 497 // Patch the code to invoke the builtin debug break function matching the |
436 // calling convention used by the call site. | 498 // calling convention used by the call site. |
437 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode)); | 499 Handle<Code> dbgbrk_code = DebugBreakForIC(target_code, mode); |
438 rinfo()->set_target_address(dbgbrk_code->entry()); | 500 rinfo()->set_target_address(dbgbrk_code->entry()); |
439 } | 501 } |
440 } | 502 } |
441 | 503 |
442 | 504 |
443 void BreakLocationIterator::ClearDebugBreakAtIC() { | 505 void BreakLocationIterator::ClearDebugBreakAtIC() { |
444 // Patch the code to the original invoke. | 506 // Patch the code to the original invoke. |
445 rinfo()->set_target_address(original_rinfo()->target_address()); | 507 rinfo()->set_target_address(original_rinfo()->target_address()); |
446 } | 508 } |
447 | 509 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
497 thread_local_.break_frame_id_ = StackFrame::NO_ID; | 559 thread_local_.break_frame_id_ = StackFrame::NO_ID; |
498 thread_local_.last_step_action_ = StepNone; | 560 thread_local_.last_step_action_ = StepNone; |
499 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; | 561 thread_local_.last_statement_position_ = RelocInfo::kNoPosition; |
500 thread_local_.step_count_ = 0; | 562 thread_local_.step_count_ = 0; |
501 thread_local_.last_fp_ = 0; | 563 thread_local_.last_fp_ = 0; |
502 thread_local_.queued_step_count_ = 0; | 564 thread_local_.queued_step_count_ = 0; |
503 thread_local_.step_into_fp_ = 0; | 565 thread_local_.step_into_fp_ = 0; |
504 thread_local_.step_out_fp_ = 0; | 566 thread_local_.step_out_fp_ = 0; |
505 // TODO(isolates): frames_are_dropped_? | 567 // TODO(isolates): frames_are_dropped_? |
506 thread_local_.debugger_entry_ = NULL; | 568 thread_local_.debugger_entry_ = NULL; |
507 thread_local_.has_pending_interrupt_ = false; | |
508 thread_local_.restarter_frame_function_pointer_ = NULL; | 569 thread_local_.restarter_frame_function_pointer_ = NULL; |
509 thread_local_.promise_on_stack_ = NULL; | 570 thread_local_.promise_on_stack_ = NULL; |
510 } | 571 } |
511 | 572 |
512 | 573 |
513 char* Debug::ArchiveDebug(char* storage) { | 574 char* Debug::ArchiveDebug(char* storage) { |
514 char* to = storage; | 575 char* to = storage; |
515 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); | 576 MemCopy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal)); |
516 ThreadInit(); | 577 ThreadInit(); |
517 return storage + ArchiveSpacePerThread(); | 578 return storage + ArchiveSpacePerThread(); |
518 } | 579 } |
519 | 580 |
520 | 581 |
521 char* Debug::RestoreDebug(char* storage) { | 582 char* Debug::RestoreDebug(char* storage) { |
522 char* from = storage; | 583 char* from = storage; |
523 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); | 584 MemCopy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal)); |
524 return storage + ArchiveSpacePerThread(); | 585 return storage + ArchiveSpacePerThread(); |
525 } | 586 } |
526 | 587 |
527 | 588 |
528 int Debug::ArchiveSpacePerThread() { | 589 int Debug::ArchiveSpacePerThread() { |
529 return sizeof(ThreadLocal); | 590 return sizeof(ThreadLocal); |
530 } | 591 } |
531 | 592 |
532 | 593 |
| 594 ScriptCache::ScriptCache(Isolate* isolate) : HashMap(HashMap::PointersMatch), |
| 595 isolate_(isolate), |
| 596 collected_scripts_(10) { |
| 597 Heap* heap = isolate_->heap(); |
| 598 HandleScope scope(isolate_); |
| 599 |
| 600 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets |
| 601 // rid of all the cached script wrappers and the second gets rid of the |
| 602 // scripts which are no longer referenced. |
| 603 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); |
| 604 heap->CollectAllGarbage(Heap::kMakeHeapIterableMask, "ScriptCache"); |
| 605 |
| 606 // Scan heap for Script objects. |
| 607 HeapIterator iterator(heap); |
| 608 DisallowHeapAllocation no_allocation; |
| 609 |
| 610 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { |
| 611 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { |
| 612 Add(Handle<Script>(Script::cast(obj))); |
| 613 } |
| 614 } |
| 615 } |
| 616 |
| 617 |
533 void ScriptCache::Add(Handle<Script> script) { | 618 void ScriptCache::Add(Handle<Script> script) { |
534 GlobalHandles* global_handles = isolate_->global_handles(); | 619 GlobalHandles* global_handles = isolate_->global_handles(); |
535 // Create an entry in the hash map for the script. | 620 // Create an entry in the hash map for the script. |
536 int id = script->id()->value(); | 621 int id = script->id()->value(); |
537 HashMap::Entry* entry = | 622 HashMap::Entry* entry = |
538 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true); | 623 HashMap::Lookup(reinterpret_cast<void*>(id), Hash(id), true); |
539 if (entry->value != NULL) { | 624 if (entry->value != NULL) { |
540 ASSERT(*script == *reinterpret_cast<Script**>(entry->value)); | 625 ASSERT(*script == *reinterpret_cast<Script**>(entry->value)); |
541 return; | 626 return; |
542 } | 627 } |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
778 ClearAllBreakPoints(); | 863 ClearAllBreakPoints(); |
779 ClearStepping(); | 864 ClearStepping(); |
780 | 865 |
781 // Match unmatched PromiseHandlePrologue calls. | 866 // Match unmatched PromiseHandlePrologue calls. |
782 while (thread_local_.promise_on_stack_) PromiseHandleEpilogue(); | 867 while (thread_local_.promise_on_stack_) PromiseHandleEpilogue(); |
783 | 868 |
784 // Return debugger is not loaded. | 869 // Return debugger is not loaded. |
785 if (!is_loaded()) return; | 870 if (!is_loaded()) return; |
786 | 871 |
787 // Clear the script cache. | 872 // Clear the script cache. |
788 DestroyScriptCache(); | 873 if (script_cache_ != NULL) { |
| 874 delete script_cache_; |
| 875 script_cache_ = NULL; |
| 876 } |
789 | 877 |
790 // Clear debugger context global handle. | 878 // Clear debugger context global handle. |
791 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); | 879 GlobalHandles::Destroy(Handle<Object>::cast(debug_context_).location()); |
792 debug_context_ = Handle<Context>(); | 880 debug_context_ = Handle<Context>(); |
793 } | 881 } |
794 | 882 |
795 | 883 |
796 void Debug::Break(Arguments args, JavaScriptFrame* frame) { | 884 void Debug::Break(Arguments args, JavaScriptFrame* frame) { |
797 Heap* heap = isolate_->heap(); | 885 Heap* heap = isolate_->heap(); |
798 HandleScope scope(isolate_); | 886 HandleScope scope(isolate_); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 // triggered. | 924 // triggered. |
837 Handle<Object> break_points_hit(heap->undefined_value(), isolate_); | 925 Handle<Object> break_points_hit(heap->undefined_value(), isolate_); |
838 if (break_location_iterator.HasBreakPoint()) { | 926 if (break_location_iterator.HasBreakPoint()) { |
839 Handle<Object> break_point_objects = | 927 Handle<Object> break_point_objects = |
840 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_); | 928 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_); |
841 break_points_hit = CheckBreakPoints(break_point_objects); | 929 break_points_hit = CheckBreakPoints(break_point_objects); |
842 } | 930 } |
843 | 931 |
844 // If step out is active skip everything until the frame where we need to step | 932 // If step out is active skip everything until the frame where we need to step |
845 // out to is reached, unless real breakpoint is hit. | 933 // out to is reached, unless real breakpoint is hit. |
846 if (StepOutActive() && frame->fp() != step_out_fp() && | 934 if (StepOutActive() && |
| 935 frame->fp() != thread_local_.step_out_fp_ && |
847 break_points_hit->IsUndefined() ) { | 936 break_points_hit->IsUndefined() ) { |
848 // Step count should always be 0 for StepOut. | 937 // Step count should always be 0 for StepOut. |
849 ASSERT(thread_local_.step_count_ == 0); | 938 ASSERT(thread_local_.step_count_ == 0); |
850 } else if (!break_points_hit->IsUndefined() || | 939 } else if (!break_points_hit->IsUndefined() || |
851 (thread_local_.last_step_action_ != StepNone && | 940 (thread_local_.last_step_action_ != StepNone && |
852 thread_local_.step_count_ == 0)) { | 941 thread_local_.step_count_ == 0)) { |
853 // Notify debugger if a real break point is triggered or if performing | 942 // Notify debugger if a real break point is triggered or if performing |
854 // single stepping with no more steps to perform. Otherwise do another step. | 943 // single stepping with no more steps to perform. Otherwise do another step. |
855 | 944 |
856 // Clear all current stepping setup. | 945 // Clear all current stepping setup. |
(...skipping 328 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1185 | 1274 |
1186 bool Debug::IsBreakOnException(ExceptionBreakType type) { | 1275 bool Debug::IsBreakOnException(ExceptionBreakType type) { |
1187 if (type == BreakUncaughtException) { | 1276 if (type == BreakUncaughtException) { |
1188 return break_on_uncaught_exception_; | 1277 return break_on_uncaught_exception_; |
1189 } else { | 1278 } else { |
1190 return break_on_exception_; | 1279 return break_on_exception_; |
1191 } | 1280 } |
1192 } | 1281 } |
1193 | 1282 |
1194 | 1283 |
1195 Debug::PromiseOnStack::PromiseOnStack(Isolate* isolate, | 1284 PromiseOnStack::PromiseOnStack(Isolate* isolate, |
1196 PromiseOnStack* prev, | 1285 PromiseOnStack* prev, |
1197 Handle<JSFunction> getter) | 1286 Handle<JSFunction> getter) |
1198 : isolate_(isolate), prev_(prev) { | 1287 : isolate_(isolate), prev_(prev) { |
1199 handler_ = StackHandler::FromAddress( | 1288 handler_ = StackHandler::FromAddress( |
1200 Isolate::handler(isolate->thread_local_top())); | 1289 Isolate::handler(isolate->thread_local_top())); |
1201 getter_ = Handle<JSFunction>::cast( | 1290 getter_ = Handle<JSFunction>::cast( |
1202 isolate->global_handles()->Create(*getter)); | 1291 isolate->global_handles()->Create(*getter)); |
1203 } | 1292 } |
1204 | 1293 |
1205 | 1294 |
1206 Debug::PromiseOnStack::~PromiseOnStack() { | 1295 PromiseOnStack::~PromiseOnStack() { |
1207 isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location()); | 1296 isolate_->global_handles()->Destroy(Handle<Object>::cast(getter_).location()); |
1208 } | 1297 } |
1209 | 1298 |
1210 | 1299 |
1211 void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) { | 1300 void Debug::PromiseHandlePrologue(Handle<JSFunction> promise_getter) { |
1212 PromiseOnStack* prev = thread_local_.promise_on_stack_; | 1301 PromiseOnStack* prev = thread_local_.promise_on_stack_; |
1213 thread_local_.promise_on_stack_ = | 1302 thread_local_.promise_on_stack_ = |
1214 new PromiseOnStack(isolate_, prev, promise_getter); | 1303 new PromiseOnStack(isolate_, prev, promise_getter); |
1215 } | 1304 } |
1216 | 1305 |
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1523 | 1612 |
1524 | 1613 |
1525 // Check whether the code object at the specified address is a debug break code | 1614 // Check whether the code object at the specified address is a debug break code |
1526 // object. | 1615 // object. |
1527 bool Debug::IsDebugBreak(Address addr) { | 1616 bool Debug::IsDebugBreak(Address addr) { |
1528 Code* code = Code::GetCodeFromTargetAddress(addr); | 1617 Code* code = Code::GetCodeFromTargetAddress(addr); |
1529 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK; | 1618 return code->is_debug_stub() && code->extra_ic_state() == DEBUG_BREAK; |
1530 } | 1619 } |
1531 | 1620 |
1532 | 1621 |
1533 // Check whether a code stub with the specified major key is a possible break | |
1534 // point location when looking for source break locations. | |
1535 bool Debug::IsSourceBreakStub(Code* code) { | |
1536 CodeStub::Major major_key = CodeStub::GetMajorKey(code); | |
1537 return major_key == CodeStub::CallFunction; | |
1538 } | |
1539 | 1622 |
1540 | 1623 |
1541 // Check whether a code stub with the specified major key is a possible break | |
1542 // location. | |
1543 bool Debug::IsBreakStub(Code* code) { | |
1544 CodeStub::Major major_key = CodeStub::GetMajorKey(code); | |
1545 return major_key == CodeStub::CallFunction; | |
1546 } | |
1547 | |
1548 | |
1549 // Find the builtin to use for invoking the debug break | |
1550 Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) { | |
1551 Isolate* isolate = code->GetIsolate(); | |
1552 | |
1553 // Find the builtin debug break function matching the calling convention | |
1554 // used by the call site. | |
1555 if (code->is_inline_cache_stub()) { | |
1556 switch (code->kind()) { | |
1557 case Code::CALL_IC: | |
1558 return isolate->builtins()->CallICStub_DebugBreak(); | |
1559 | |
1560 case Code::LOAD_IC: | |
1561 return isolate->builtins()->LoadIC_DebugBreak(); | |
1562 | |
1563 case Code::STORE_IC: | |
1564 return isolate->builtins()->StoreIC_DebugBreak(); | |
1565 | |
1566 case Code::KEYED_LOAD_IC: | |
1567 return isolate->builtins()->KeyedLoadIC_DebugBreak(); | |
1568 | |
1569 case Code::KEYED_STORE_IC: | |
1570 return isolate->builtins()->KeyedStoreIC_DebugBreak(); | |
1571 | |
1572 case Code::COMPARE_NIL_IC: | |
1573 return isolate->builtins()->CompareNilIC_DebugBreak(); | |
1574 | |
1575 default: | |
1576 UNREACHABLE(); | |
1577 } | |
1578 } | |
1579 if (RelocInfo::IsConstructCall(mode)) { | |
1580 if (code->has_function_cache()) { | |
1581 return isolate->builtins()->CallConstructStub_Recording_DebugBreak(); | |
1582 } else { | |
1583 return isolate->builtins()->CallConstructStub_DebugBreak(); | |
1584 } | |
1585 } | |
1586 if (code->kind() == Code::STUB) { | |
1587 ASSERT(code->major_key() == CodeStub::CallFunction); | |
1588 return isolate->builtins()->CallFunctionStub_DebugBreak(); | |
1589 } | |
1590 | |
1591 UNREACHABLE(); | |
1592 return Handle<Code>::null(); | |
1593 } | |
1594 | |
1595 | 1624 |
1596 // Simple function for returning the source positions for active break points. | 1625 // Simple function for returning the source positions for active break points. |
1597 Handle<Object> Debug::GetSourceBreakLocations( | 1626 Handle<Object> Debug::GetSourceBreakLocations( |
1598 Handle<SharedFunctionInfo> shared, | 1627 Handle<SharedFunctionInfo> shared, |
1599 BreakPositionAlignment position_alignment) { | 1628 BreakPositionAlignment position_alignment) { |
1600 Isolate* isolate = shared->GetIsolate(); | 1629 Isolate* isolate = shared->GetIsolate(); |
1601 Heap* heap = isolate->heap(); | 1630 Heap* heap = isolate->heap(); |
1602 if (!HasDebugInfo(shared)) { | 1631 if (!HasDebugInfo(shared)) { |
1603 return Handle<Object>(heap->undefined_value(), isolate); | 1632 return Handle<Object>(heap->undefined_value(), isolate); |
1604 } | 1633 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1648 // For constructor functions skip another frame. | 1677 // For constructor functions skip another frame. |
1649 if (is_constructor) { | 1678 if (is_constructor) { |
1650 ASSERT(it.frame()->is_construct()); | 1679 ASSERT(it.frame()->is_construct()); |
1651 it.Advance(); | 1680 it.Advance(); |
1652 } | 1681 } |
1653 fp = it.frame()->fp(); | 1682 fp = it.frame()->fp(); |
1654 } | 1683 } |
1655 | 1684 |
1656 // Flood the function with one-shot break points if it is called from where | 1685 // Flood the function with one-shot break points if it is called from where |
1657 // step into was requested. | 1686 // step into was requested. |
1658 if (fp == step_in_fp()) { | 1687 if (fp == thread_local_.step_into_fp_) { |
1659 if (function->shared()->bound()) { | 1688 if (function->shared()->bound()) { |
1660 // Handle Function.prototype.bind | 1689 // Handle Function.prototype.bind |
1661 Debug::FloodBoundFunctionWithOneShot(function); | 1690 Debug::FloodBoundFunctionWithOneShot(function); |
1662 } else if (!function->IsNative()) { | 1691 } else if (!function->IsNative()) { |
1663 // Don't allow step into functions in the native context. | 1692 // Don't allow step into functions in the native context. |
1664 if (function->shared()->code() == | 1693 if (function->shared()->code() == |
1665 isolate->builtins()->builtin(Builtins::kFunctionApply) || | 1694 isolate->builtins()->builtin(Builtins::kFunctionApply) || |
1666 function->shared()->code() == | 1695 function->shared()->code() == |
1667 isolate->builtins()->builtin(Builtins::kFunctionCall)) { | 1696 isolate->builtins()->builtin(Builtins::kFunctionCall)) { |
1668 // Handle function.apply and function.call separately to flood the | 1697 // Handle function.apply and function.call separately to flood the |
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1905 | 1934 |
1906 | 1935 |
1907 class ActiveFunctionsRedirector : public ThreadVisitor { | 1936 class ActiveFunctionsRedirector : public ThreadVisitor { |
1908 public: | 1937 public: |
1909 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { | 1938 void VisitThread(Isolate* isolate, ThreadLocalTop* top) { |
1910 RedirectActivationsToRecompiledCodeOnThread(isolate, top); | 1939 RedirectActivationsToRecompiledCodeOnThread(isolate, top); |
1911 } | 1940 } |
1912 }; | 1941 }; |
1913 | 1942 |
1914 | 1943 |
1915 void Debug::EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) { | 1944 static void EnsureFunctionHasDebugBreakSlots(Handle<JSFunction> function) { |
1916 if (function->code()->kind() == Code::FUNCTION && | 1945 if (function->code()->kind() == Code::FUNCTION && |
1917 function->code()->has_debug_break_slots()) { | 1946 function->code()->has_debug_break_slots()) { |
1918 // Nothing to do. Function code already had debug break slots. | 1947 // Nothing to do. Function code already had debug break slots. |
1919 return; | 1948 return; |
1920 } | 1949 } |
1921 // Make sure that the shared full code is compiled with debug | 1950 // Make sure that the shared full code is compiled with debug |
1922 // break slots. | 1951 // break slots. |
1923 if (!function->shared()->code()->has_debug_break_slots()) { | 1952 if (!function->shared()->code()->has_debug_break_slots()) { |
1924 MaybeHandle<Code> code = Compiler::GetCodeForDebugging(function); | 1953 MaybeHandle<Code> code = Compiler::GetCodeForDebugging(function); |
1925 // Recompilation can fail. In that case leave the code as it was. | 1954 // Recompilation can fail. In that case leave the code as it was. |
1926 if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked()); | 1955 if (!code.is_null()) function->ReplaceCode(*code.ToHandleChecked()); |
1927 } else { | 1956 } else { |
1928 // Simply use shared code if it has debug break slots. | 1957 // Simply use shared code if it has debug break slots. |
1929 function->ReplaceCode(function->shared()->code()); | 1958 function->ReplaceCode(function->shared()->code()); |
1930 } | 1959 } |
1931 } | 1960 } |
1932 | 1961 |
1933 | 1962 |
1934 void Debug::RecompileAndRelocateSuspendedGenerators( | 1963 static void RecompileAndRelocateSuspendedGenerators( |
1935 const List<Handle<JSGeneratorObject> > &generators) { | 1964 const List<Handle<JSGeneratorObject> > &generators) { |
1936 for (int i = 0; i < generators.length(); i++) { | 1965 for (int i = 0; i < generators.length(); i++) { |
1937 Handle<JSFunction> fun(generators[i]->function()); | 1966 Handle<JSFunction> fun(generators[i]->function()); |
1938 | 1967 |
1939 EnsureFunctionHasDebugBreakSlots(fun); | 1968 EnsureFunctionHasDebugBreakSlots(fun); |
1940 | 1969 |
1941 int code_offset = generators[i]->continuation(); | 1970 int code_offset = generators[i]->continuation(); |
1942 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset); | 1971 int pc_offset = ComputePcOffsetFromCodeOffset(fun->code(), code_offset); |
1943 generators[i]->set_continuation(pc_offset); | 1972 generators[i]->set_continuation(pc_offset); |
1944 } | 1973 } |
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2437 isolate_->global_object(), | 2466 isolate_->global_object(), |
2438 "ClearMirrorCache").ToHandleChecked(); | 2467 "ClearMirrorCache").ToHandleChecked(); |
2439 ASSERT(fun->IsJSFunction()); | 2468 ASSERT(fun->IsJSFunction()); |
2440 Execution::TryCall(Handle<JSFunction>::cast(fun), | 2469 Execution::TryCall(Handle<JSFunction>::cast(fun), |
2441 Handle<JSObject>(Debug::debug_context()->global_object()), | 2470 Handle<JSObject>(Debug::debug_context()->global_object()), |
2442 0, | 2471 0, |
2443 NULL); | 2472 NULL); |
2444 } | 2473 } |
2445 | 2474 |
2446 | 2475 |
2447 void Debug::CreateScriptCache() { | |
2448 Heap* heap = isolate_->heap(); | |
2449 HandleScope scope(isolate_); | |
2450 | |
2451 // Perform two GCs to get rid of all unreferenced scripts. The first GC gets | |
2452 // rid of all the cached script wrappers and the second gets rid of the | |
2453 // scripts which are no longer referenced. The second also sweeps precisely, | |
2454 // which saves us doing yet another GC to make the heap iterable. | |
2455 heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache"); | |
2456 | |
2457 ASSERT(script_cache_ == NULL); | |
2458 script_cache_ = new ScriptCache(isolate_); | |
2459 | |
2460 // Scan heap for Script objects. | |
2461 int count = 0; | |
2462 HeapIterator iterator(heap); | |
2463 | |
2464 for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) { | |
2465 if (obj->IsScript() && Script::cast(obj)->HasValidSource()) { | |
2466 script_cache_->Add(Handle<Script>(Script::cast(obj))); | |
2467 count++; | |
2468 } | |
2469 } | |
2470 } | |
2471 | |
2472 | |
2473 void Debug::DestroyScriptCache() { | |
2474 // Get rid of the script cache if it was created. | |
2475 if (script_cache_ != NULL) { | |
2476 delete script_cache_; | |
2477 script_cache_ = NULL; | |
2478 } | |
2479 } | |
2480 | |
2481 | |
2482 void Debug::AddScriptToScriptCache(Handle<Script> script) { | |
2483 if (script_cache_ != NULL) { | |
2484 script_cache_->Add(script); | |
2485 } | |
2486 } | |
2487 | |
2488 | |
2489 Handle<FixedArray> Debug::GetLoadedScripts() { | 2476 Handle<FixedArray> Debug::GetLoadedScripts() { |
2490 // Create and fill the script cache when the loaded scripts is requested for | 2477 // Create and fill the script cache when the loaded scripts is requested for |
2491 // the first time. | 2478 // the first time. |
2492 if (script_cache_ == NULL) { | 2479 if (script_cache_ == NULL) script_cache_ = new ScriptCache(isolate_); |
2493 CreateScriptCache(); | |
2494 } | |
2495 | |
2496 // If the script cache is not active just return an empty array. | |
2497 ASSERT(script_cache_ != NULL); | |
2498 if (script_cache_ == NULL) { | |
2499 isolate_->factory()->NewFixedArray(0); | |
2500 } | |
2501 | 2480 |
2502 // Perform GC to get unreferenced scripts evicted from the cache before | 2481 // Perform GC to get unreferenced scripts evicted from the cache before |
2503 // returning the content. | 2482 // returning the content. |
2504 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, | 2483 isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, |
2505 "Debug::GetLoadedScripts"); | 2484 "Debug::GetLoadedScripts"); |
2506 | 2485 |
2507 // Get the scripts from the cache. | 2486 // Get the scripts from the cache. |
2508 return script_cache_->GetScripts(); | 2487 return script_cache_->GetScripts(); |
2509 } | 2488 } |
2510 | 2489 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2597 Handle<Object> exec_state; | 2576 Handle<Object> exec_state; |
2598 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); | 2577 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); |
2599 // Create the script collected event object. | 2578 // Create the script collected event object. |
2600 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); | 2579 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); |
2601 Handle<Object> argv[] = { exec_state, id_object }; | 2580 Handle<Object> argv[] = { exec_state, id_object }; |
2602 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); | 2581 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); |
2603 } | 2582 } |
2604 | 2583 |
2605 | 2584 |
2606 void Debug::OnException(Handle<Object> exception, bool uncaught) { | 2585 void Debug::OnException(Handle<Object> exception, bool uncaught) { |
| 2586 if (is_entered() || ignore_events()) return; |
| 2587 |
2607 HandleScope scope(isolate_); | 2588 HandleScope scope(isolate_); |
2608 | |
2609 // Bail out based on state or if there is no listener for this event | |
2610 if (is_entered()) return; | |
2611 if (!EventActive()) return; | |
2612 | |
2613 Handle<Object> promise = GetPromiseForUncaughtException(); | 2589 Handle<Object> promise = GetPromiseForUncaughtException(); |
2614 uncaught |= !promise->IsUndefined(); | 2590 uncaught |= !promise->IsUndefined(); |
2615 | 2591 |
2616 // Bail out if exception breaks are not active | 2592 // Bail out if exception breaks are not active |
2617 if (uncaught) { | 2593 if (uncaught) { |
2618 // Uncaught exceptions are reported by either flags. | 2594 // Uncaught exceptions are reported by either flags. |
2619 if (!(break_on_uncaught_exception() || break_on_exception())) return; | 2595 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; |
2620 } else { | 2596 } else { |
2621 // Caught exceptions are reported is activated. | 2597 // Caught exceptions are reported is activated. |
2622 if (!break_on_exception()) return; | 2598 if (!break_on_exception_) return; |
2623 } | 2599 } |
2624 | 2600 |
2625 // Enter the debugger. | 2601 // Enter the debugger. |
2626 EnterDebugger debugger(isolate_); | 2602 EnterDebugger debugger(isolate_); |
2627 if (debugger.FailedToEnter()) return; | 2603 if (debugger.FailedToEnter()) return; |
2628 | 2604 |
2629 // Clear all current stepping setup. | 2605 // Clear all current stepping setup. |
2630 ClearStepping(); | 2606 ClearStepping(); |
2631 | 2607 |
2632 // Create the event data object. | 2608 // Create the event data object. |
2633 Handle<Object> event_data; | 2609 Handle<Object> event_data; |
2634 // Bail out and don't call debugger if exception. | 2610 // Bail out and don't call debugger if exception. |
2635 if (!MakeExceptionEvent( | 2611 if (!MakeExceptionEvent( |
2636 exception, uncaught, promise).ToHandle(&event_data)) { | 2612 exception, uncaught, promise).ToHandle(&event_data)) { |
2637 return; | 2613 return; |
2638 } | 2614 } |
2639 | 2615 |
2640 // Process debug event. | 2616 // Process debug event. |
2641 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); | 2617 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); |
2642 // Return to continue execution from where the exception was thrown. | 2618 // Return to continue execution from where the exception was thrown. |
2643 } | 2619 } |
2644 | 2620 |
2645 | 2621 |
2646 void Debug::OnDebugBreak(Handle<Object> break_points_hit, | 2622 void Debug::OnDebugBreak(Handle<Object> break_points_hit, |
2647 bool auto_continue) { | 2623 bool auto_continue) { |
2648 HandleScope scope(isolate_); | |
2649 | |
2650 // Debugger has already been entered by caller. | 2624 // Debugger has already been entered by caller. |
2651 ASSERT(isolate_->context() == *debug_context()); | 2625 ASSERT(isolate_->context() == *debug_context()); |
| 2626 // Bail out if there is no listener for this event |
| 2627 if (ignore_events()) return; |
2652 | 2628 |
2653 // Bail out if there is no listener for this event | 2629 HandleScope scope(isolate_); |
2654 if (!EventActive()) return; | |
2655 | |
2656 // Create the event data object. | 2630 // Create the event data object. |
2657 Handle<Object> event_data; | 2631 Handle<Object> event_data; |
2658 // Bail out and don't call debugger if exception. | 2632 // Bail out and don't call debugger if exception. |
2659 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; | 2633 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; |
2660 | 2634 |
2661 // Process debug event. | 2635 // Process debug event. |
2662 ProcessDebugEvent(v8::Break, | 2636 ProcessDebugEvent(v8::Break, |
2663 Handle<JSObject>::cast(event_data), | 2637 Handle<JSObject>::cast(event_data), |
2664 auto_continue); | 2638 auto_continue); |
2665 } | 2639 } |
2666 | 2640 |
2667 | 2641 |
2668 void Debug::OnBeforeCompile(Handle<Script> script) { | 2642 void Debug::OnBeforeCompile(Handle<Script> script) { |
| 2643 if (is_entered() || ignore_events()) return; |
| 2644 |
2669 HandleScope scope(isolate_); | 2645 HandleScope scope(isolate_); |
2670 | |
2671 // Bail out based on state or if there is no listener for this event | |
2672 if (is_entered()) return; | |
2673 if (!EventActive()) return; | |
2674 | |
2675 // Enter the debugger. | 2646 // Enter the debugger. |
2676 EnterDebugger debugger(isolate_); | 2647 EnterDebugger debugger(isolate_); |
2677 if (debugger.FailedToEnter()) return; | 2648 if (debugger.FailedToEnter()) return; |
2678 | 2649 |
2679 // Create the event data object. | 2650 // Create the event data object. |
2680 Handle<Object> event_data; | 2651 Handle<Object> event_data; |
2681 // Bail out and don't call debugger if exception. | 2652 // Bail out and don't call debugger if exception. |
2682 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; | 2653 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; |
2683 | 2654 |
2684 // Process debug event. | 2655 // Process debug event. |
2685 ProcessDebugEvent(v8::BeforeCompile, | 2656 ProcessDebugEvent(v8::BeforeCompile, |
2686 Handle<JSObject>::cast(event_data), | 2657 Handle<JSObject>::cast(event_data), |
2687 true); | 2658 true); |
2688 } | 2659 } |
2689 | 2660 |
2690 | 2661 |
2691 // Handle debugger actions when a new script is compiled. | 2662 // Handle debugger actions when a new script is compiled. |
2692 void Debug::OnAfterCompile(Handle<Script> script, | 2663 void Debug::OnAfterCompile(Handle<Script> script, |
2693 AfterCompileFlags after_compile_flags) { | 2664 AfterCompileFlags after_compile_flags) { |
2694 HandleScope scope(isolate_); | |
2695 | |
2696 // Add the newly compiled script to the script cache. | 2665 // Add the newly compiled script to the script cache. |
2697 AddScriptToScriptCache(script); | 2666 if (script_cache_ != NULL) script_cache_->Add(script); |
2698 | 2667 |
2699 // No more to do if not debugging. | 2668 // No more to do if not debugging. |
2700 if (!EventActive()) return; | 2669 if (is_entered() || ignore_events()) return; |
2701 | 2670 |
| 2671 HandleScope scope(isolate_); |
2702 // Store whether in debugger before entering debugger. | 2672 // Store whether in debugger before entering debugger. |
2703 bool in_debugger = is_entered(); | 2673 bool in_debugger = is_entered(); |
2704 | 2674 |
2705 // Enter the debugger. | 2675 // Enter the debugger. |
2706 EnterDebugger debugger(isolate_); | 2676 EnterDebugger debugger(isolate_); |
2707 if (debugger.FailedToEnter()) return; | 2677 if (debugger.FailedToEnter()) return; |
2708 | 2678 |
2709 // If debugging there might be script break points registered for this | 2679 // If debugging there might be script break points registered for this |
2710 // script. Make sure that these break points are set. | 2680 // script. Make sure that these break points are set. |
2711 | 2681 |
(...skipping 29 matching lines...) Expand all Loading... |
2741 Handle<Object> event_data; | 2711 Handle<Object> event_data; |
2742 // Bail out and don't call debugger if exception. | 2712 // Bail out and don't call debugger if exception. |
2743 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return; | 2713 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return; |
2744 | 2714 |
2745 // Process debug event. | 2715 // Process debug event. |
2746 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); | 2716 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); |
2747 } | 2717 } |
2748 | 2718 |
2749 | 2719 |
2750 void Debug::OnScriptCollected(int id) { | 2720 void Debug::OnScriptCollected(int id) { |
| 2721 if (is_entered() || ignore_events()) return; |
| 2722 |
2751 HandleScope scope(isolate_); | 2723 HandleScope scope(isolate_); |
2752 | |
2753 // No more to do if not debugging. | |
2754 if (is_entered()) return; | |
2755 if (!EventActive()) return; | |
2756 | |
2757 // Enter the debugger. | 2724 // Enter the debugger. |
2758 EnterDebugger debugger(isolate_); | 2725 EnterDebugger debugger(isolate_); |
2759 if (debugger.FailedToEnter()) return; | 2726 if (debugger.FailedToEnter()) return; |
2760 | 2727 |
2761 // Create the script collected state object. | 2728 // Create the script collected state object. |
2762 Handle<Object> event_data; | 2729 Handle<Object> event_data; |
2763 // Bail out and don't call debugger if exception. | 2730 // Bail out and don't call debugger if exception. |
2764 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; | 2731 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; |
2765 | 2732 |
2766 // Process debug event. | 2733 // Process debug event. |
2767 ProcessDebugEvent(v8::ScriptCollected, | 2734 ProcessDebugEvent(v8::ScriptCollected, |
2768 Handle<JSObject>::cast(event_data), | 2735 Handle<JSObject>::cast(event_data), |
2769 true); | 2736 true); |
2770 } | 2737 } |
2771 | 2738 |
2772 | 2739 |
2773 void Debug::ProcessDebugEvent(v8::DebugEvent event, | 2740 void Debug::ProcessDebugEvent(v8::DebugEvent event, |
2774 Handle<JSObject> event_data, | 2741 Handle<JSObject> event_data, |
2775 bool auto_continue) { | 2742 bool auto_continue) { |
2776 HandleScope scope(isolate_); | 2743 HandleScope scope(isolate_); |
2777 | 2744 |
2778 // Clear any pending debug break if this is a real break. | |
2779 if (!auto_continue) thread_local_.has_pending_interrupt_ = false; | |
2780 | |
2781 // Create the execution state. | 2745 // Create the execution state. |
2782 Handle<Object> exec_state; | 2746 Handle<Object> exec_state; |
2783 // Bail out and don't call debugger if exception. | 2747 // Bail out and don't call debugger if exception. |
2784 if (!MakeExecutionState().ToHandle(&exec_state)) return; | 2748 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
2785 | 2749 |
2786 // First notify the message handler if any. | 2750 // First notify the message handler if any. |
2787 if (message_handler_ != NULL) { | 2751 if (message_handler_ != NULL) { |
2788 NotifyMessageHandler(event, | 2752 NotifyMessageHandler(event, |
2789 Handle<JSObject>::cast(exec_state), | 2753 Handle<JSObject>::cast(exec_state), |
2790 event_data, | 2754 event_data, |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3088 Handle<Object> argv[] = { exec_state, data }; | 3052 Handle<Object> argv[] = { exec_state, data }; |
3089 return Execution::Call( | 3053 return Execution::Call( |
3090 isolate_, | 3054 isolate_, |
3091 fun, | 3055 fun, |
3092 Handle<Object>(debug_context()->global_proxy(), isolate_), | 3056 Handle<Object>(debug_context()->global_proxy(), isolate_), |
3093 ARRAY_SIZE(argv), | 3057 ARRAY_SIZE(argv), |
3094 argv); | 3058 argv); |
3095 } | 3059 } |
3096 | 3060 |
3097 | 3061 |
3098 void Debug::DebugBreakHelper() { | 3062 void Debug::HandleDebugBreak() { |
3099 // Ignore debug break during bootstrapping. | 3063 // Ignore debug break during bootstrapping. |
3100 if (isolate_->bootstrapper()->IsActive()) return; | 3064 if (isolate_->bootstrapper()->IsActive()) return; |
3101 // Just continue if breaks are disabled. | 3065 // Just continue if breaks are disabled. |
3102 if (break_disabled_) return; | 3066 if (break_disabled_) return; |
3103 // Ignore debug break if debugger is not active. | 3067 // Ignore debug break if debugger is not active. |
3104 if (!is_active()) return; | 3068 if (!is_active()) return; |
3105 | 3069 |
3106 StackLimitCheck check(isolate_); | 3070 StackLimitCheck check(isolate_); |
3107 if (check.HasOverflowed()) return; | 3071 if (check.HasOverflowed()) return; |
3108 | 3072 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3154 // Link recursive debugger entry. | 3118 // Link recursive debugger entry. |
3155 debug->thread_local_.debugger_entry_ = this; | 3119 debug->thread_local_.debugger_entry_ = this; |
3156 | 3120 |
3157 // Store the previous break id and frame id. | 3121 // Store the previous break id and frame id. |
3158 break_id_ = debug->break_id(); | 3122 break_id_ = debug->break_id(); |
3159 break_frame_id_ = debug->break_frame_id(); | 3123 break_frame_id_ = debug->break_frame_id(); |
3160 | 3124 |
3161 // Create the new break info. If there is no JavaScript frames there is no | 3125 // Create the new break info. If there is no JavaScript frames there is no |
3162 // break frame id. | 3126 // break frame id. |
3163 JavaScriptFrameIterator it(isolate_); | 3127 JavaScriptFrameIterator it(isolate_); |
3164 has_js_frames_ = !it.done(); | 3128 bool has_js_frames = !it.done(); |
3165 debug->thread_local_.break_frame_id_ = has_js_frames_ ? it.frame()->id() | 3129 debug->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id() |
3166 : StackFrame::NO_ID; | 3130 : StackFrame::NO_ID; |
3167 debug->SetNextBreakId(); | 3131 debug->SetNextBreakId(); |
3168 | 3132 |
3169 debug->UpdateState(); | 3133 debug->UpdateState(); |
3170 // Make sure that debugger is loaded and enter the debugger context. | 3134 // Make sure that debugger is loaded and enter the debugger context. |
3171 // The previous context is kept in save_. | 3135 // The previous context is kept in save_. |
3172 load_failed_ = !debug->is_loaded(); | 3136 load_failed_ = !debug->is_loaded(); |
3173 if (!load_failed_) isolate_->set_context(*debug->debug_context()); | 3137 if (!load_failed_) isolate_->set_context(*debug->debug_context()); |
3174 } | 3138 } |
3175 | 3139 |
3176 | 3140 |
3177 EnterDebugger::~EnterDebugger() { | 3141 EnterDebugger::~EnterDebugger() { |
3178 Debug* debug = isolate_->debug(); | 3142 Debug* debug = isolate_->debug(); |
3179 | 3143 |
3180 // Restore to the previous break state. | 3144 // Restore to the previous break state. |
3181 debug->thread_local_.break_frame_id_ = break_frame_id_; | 3145 debug->thread_local_.break_frame_id_ = break_frame_id_; |
3182 debug->thread_local_.break_id_ = break_id_; | 3146 debug->thread_local_.break_id_ = break_id_; |
3183 | 3147 |
3184 // Check for leaving the debugger. | 3148 // Check for leaving the debugger. |
3185 if (!load_failed_ && prev_ == NULL) { | 3149 if (!load_failed_ && prev_ == NULL) { |
3186 // Clear mirror cache when leaving the debugger. Skip this if there is a | 3150 // Clear mirror cache when leaving the debugger. Skip this if there is a |
3187 // pending exception as clearing the mirror cache calls back into | 3151 // pending exception as clearing the mirror cache calls back into |
3188 // JavaScript. This can happen if the v8::Debug::Call is used in which | 3152 // JavaScript. This can happen if the v8::Debug::Call is used in which |
3189 // case the exception should end up in the calling code. | 3153 // case the exception should end up in the calling code. |
3190 if (!isolate_->has_pending_exception()) { | 3154 if (!isolate_->has_pending_exception()) debug->ClearMirrorCache(); |
3191 debug->ClearMirrorCache(); | |
3192 } | |
3193 | 3155 |
3194 // If there are commands in the queue when leaving the debugger request | 3156 // If there are commands in the queue when leaving the debugger request |
3195 // that these commands are processed. | 3157 // that these commands are processed. |
3196 if (debug->has_commands()) isolate_->stack_guard()->RequestDebugCommand(); | 3158 if (debug->has_commands()) isolate_->stack_guard()->RequestDebugCommand(); |
3197 } | 3159 } |
3198 | 3160 |
3199 // Leaving this debugger entry. | 3161 // Leaving this debugger entry. |
3200 debug->thread_local_.debugger_entry_ = prev_; | 3162 debug->thread_local_.debugger_entry_ = prev_; |
3201 | 3163 |
3202 debug->UpdateState(); | 3164 debug->UpdateState(); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3362 } | 3324 } |
3363 | 3325 |
3364 | 3326 |
3365 CommandMessage::CommandMessage(const Vector<uint16_t>& text, | 3327 CommandMessage::CommandMessage(const Vector<uint16_t>& text, |
3366 v8::Debug::ClientData* data) | 3328 v8::Debug::ClientData* data) |
3367 : text_(text), | 3329 : text_(text), |
3368 client_data_(data) { | 3330 client_data_(data) { |
3369 } | 3331 } |
3370 | 3332 |
3371 | 3333 |
3372 CommandMessage::~CommandMessage() { | |
3373 } | |
3374 | |
3375 | |
3376 void CommandMessage::Dispose() { | 3334 void CommandMessage::Dispose() { |
3377 text_.Dispose(); | 3335 text_.Dispose(); |
3378 delete client_data_; | 3336 delete client_data_; |
3379 client_data_ = NULL; | 3337 client_data_ = NULL; |
3380 } | 3338 } |
3381 | 3339 |
3382 | 3340 |
3383 CommandMessage CommandMessage::New(const Vector<uint16_t>& command, | 3341 CommandMessage CommandMessage::New(const Vector<uint16_t>& command, |
3384 v8::Debug::ClientData* data) { | 3342 v8::Debug::ClientData* data) { |
3385 return CommandMessage(command.Clone(), data); | 3343 return CommandMessage(command.Clone(), data); |
3386 } | 3344 } |
3387 | 3345 |
3388 | 3346 |
3389 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0), | 3347 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0), |
3390 size_(size) { | 3348 size_(size) { |
3391 messages_ = NewArray<CommandMessage>(size); | 3349 messages_ = NewArray<CommandMessage>(size); |
3392 } | 3350 } |
3393 | 3351 |
3394 | 3352 |
3395 CommandMessageQueue::~CommandMessageQueue() { | 3353 CommandMessageQueue::~CommandMessageQueue() { |
3396 while (!IsEmpty()) { | 3354 while (!IsEmpty()) Get().Dispose(); |
3397 CommandMessage m = Get(); | |
3398 m.Dispose(); | |
3399 } | |
3400 DeleteArray(messages_); | 3355 DeleteArray(messages_); |
3401 } | 3356 } |
3402 | 3357 |
3403 | 3358 |
3404 CommandMessage CommandMessageQueue::Get() { | 3359 CommandMessage CommandMessageQueue::Get() { |
3405 ASSERT(!IsEmpty()); | 3360 ASSERT(!IsEmpty()); |
3406 int result = start_; | 3361 int result = start_; |
3407 start_ = (start_ + 1) % size_; | 3362 start_ = (start_ + 1) % size_; |
3408 return messages_[result]; | 3363 return messages_[result]; |
3409 } | 3364 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3456 logger_->DebugEvent("Put", message.text()); | 3411 logger_->DebugEvent("Put", message.text()); |
3457 } | 3412 } |
3458 | 3413 |
3459 | 3414 |
3460 void LockingCommandMessageQueue::Clear() { | 3415 void LockingCommandMessageQueue::Clear() { |
3461 LockGuard<Mutex> lock_guard(&mutex_); | 3416 LockGuard<Mutex> lock_guard(&mutex_); |
3462 queue_.Clear(); | 3417 queue_.Clear(); |
3463 } | 3418 } |
3464 | 3419 |
3465 } } // namespace v8::internal | 3420 } } // namespace v8::internal |
OLD | NEW |