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. The second also sweeps precisely, | |
603 // which saves us doing yet another GC to make the heap iterable. | |
604 heap->CollectAllGarbage(Heap::kNoGCFlags, "Debug::CreateScriptCache"); | |
ulan
2014/05/28 13:24:32
The comment is out of sync: there is only one GC a
Yang
2014/06/02 12:19:31
The comment actually makes sense:
Script wrappers
| |
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 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2595 Handle<Object> exec_state; | 2574 Handle<Object> exec_state; |
2596 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); | 2575 if (!MakeExecutionState().ToHandle(&exec_state)) return MaybeHandle<Object>(); |
2597 // Create the script collected event object. | 2576 // Create the script collected event object. |
2598 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); | 2577 Handle<Object> id_object = Handle<Smi>(Smi::FromInt(id), isolate_); |
2599 Handle<Object> argv[] = { exec_state, id_object }; | 2578 Handle<Object> argv[] = { exec_state, id_object }; |
2600 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); | 2579 return MakeJSObject("MakeScriptCollectedEvent", ARRAY_SIZE(argv), argv); |
2601 } | 2580 } |
2602 | 2581 |
2603 | 2582 |
2604 void Debug::OnException(Handle<Object> exception, bool uncaught) { | 2583 void Debug::OnException(Handle<Object> exception, bool uncaught) { |
2584 if (is_entered() || ignore_events()) return; | |
2585 | |
2605 HandleScope scope(isolate_); | 2586 HandleScope scope(isolate_); |
2606 | |
2607 // Bail out based on state or if there is no listener for this event | |
2608 if (is_entered()) return; | |
2609 if (!EventActive()) return; | |
2610 | |
2611 Handle<Object> promise = GetPromiseForUncaughtException(); | 2587 Handle<Object> promise = GetPromiseForUncaughtException(); |
2612 uncaught |= !promise->IsUndefined(); | 2588 uncaught |= !promise->IsUndefined(); |
2613 | 2589 |
2614 // Bail out if exception breaks are not active | 2590 // Bail out if exception breaks are not active |
2615 if (uncaught) { | 2591 if (uncaught) { |
2616 // Uncaught exceptions are reported by either flags. | 2592 // Uncaught exceptions are reported by either flags. |
2617 if (!(break_on_uncaught_exception() || break_on_exception())) return; | 2593 if (!(break_on_uncaught_exception_ || break_on_exception_)) return; |
2618 } else { | 2594 } else { |
2619 // Caught exceptions are reported is activated. | 2595 // Caught exceptions are reported is activated. |
2620 if (!break_on_exception()) return; | 2596 if (!break_on_exception_) return; |
2621 } | 2597 } |
2622 | 2598 |
2623 // Enter the debugger. | 2599 // Enter the debugger. |
2624 EnterDebugger debugger(isolate_); | 2600 EnterDebugger debugger(isolate_); |
2625 if (debugger.FailedToEnter()) return; | 2601 if (debugger.FailedToEnter()) return; |
2626 | 2602 |
2627 // Clear all current stepping setup. | 2603 // Clear all current stepping setup. |
2628 ClearStepping(); | 2604 ClearStepping(); |
2629 | 2605 |
2630 // Create the event data object. | 2606 // Create the event data object. |
2631 Handle<Object> event_data; | 2607 Handle<Object> event_data; |
2632 // Bail out and don't call debugger if exception. | 2608 // Bail out and don't call debugger if exception. |
2633 if (!MakeExceptionEvent( | 2609 if (!MakeExceptionEvent( |
2634 exception, uncaught, promise).ToHandle(&event_data)) { | 2610 exception, uncaught, promise).ToHandle(&event_data)) { |
2635 return; | 2611 return; |
2636 } | 2612 } |
2637 | 2613 |
2638 // Process debug event. | 2614 // Process debug event. |
2639 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); | 2615 ProcessDebugEvent(v8::Exception, Handle<JSObject>::cast(event_data), false); |
2640 // Return to continue execution from where the exception was thrown. | 2616 // Return to continue execution from where the exception was thrown. |
2641 } | 2617 } |
2642 | 2618 |
2643 | 2619 |
2644 void Debug::OnDebugBreak(Handle<Object> break_points_hit, | 2620 void Debug::OnDebugBreak(Handle<Object> break_points_hit, |
2645 bool auto_continue) { | 2621 bool auto_continue) { |
2646 HandleScope scope(isolate_); | |
2647 | |
2648 // Debugger has already been entered by caller. | 2622 // Debugger has already been entered by caller. |
2649 ASSERT(isolate_->context() == *debug_context()); | 2623 ASSERT(isolate_->context() == *debug_context()); |
2624 // Bail out if there is no listener for this event | |
2625 if (ignore_events()) return; | |
2650 | 2626 |
2651 // Bail out if there is no listener for this event | 2627 HandleScope scope(isolate_); |
2652 if (!EventActive()) return; | |
2653 | |
2654 // Create the event data object. | 2628 // Create the event data object. |
2655 Handle<Object> event_data; | 2629 Handle<Object> event_data; |
2656 // Bail out and don't call debugger if exception. | 2630 // Bail out and don't call debugger if exception. |
2657 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; | 2631 if (!MakeBreakEvent(break_points_hit).ToHandle(&event_data)) return; |
2658 | 2632 |
2659 // Process debug event. | 2633 // Process debug event. |
2660 ProcessDebugEvent(v8::Break, | 2634 ProcessDebugEvent(v8::Break, |
2661 Handle<JSObject>::cast(event_data), | 2635 Handle<JSObject>::cast(event_data), |
2662 auto_continue); | 2636 auto_continue); |
2663 } | 2637 } |
2664 | 2638 |
2665 | 2639 |
2666 void Debug::OnBeforeCompile(Handle<Script> script) { | 2640 void Debug::OnBeforeCompile(Handle<Script> script) { |
2641 if (is_entered() || ignore_events()) return; | |
2642 | |
2667 HandleScope scope(isolate_); | 2643 HandleScope scope(isolate_); |
2668 | |
2669 // Bail out based on state or if there is no listener for this event | |
2670 if (is_entered()) return; | |
2671 if (!EventActive()) return; | |
2672 | |
2673 // Enter the debugger. | 2644 // Enter the debugger. |
2674 EnterDebugger debugger(isolate_); | 2645 EnterDebugger debugger(isolate_); |
2675 if (debugger.FailedToEnter()) return; | 2646 if (debugger.FailedToEnter()) return; |
2676 | 2647 |
2677 // Create the event data object. | 2648 // Create the event data object. |
2678 Handle<Object> event_data; | 2649 Handle<Object> event_data; |
2679 // Bail out and don't call debugger if exception. | 2650 // Bail out and don't call debugger if exception. |
2680 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; | 2651 if (!MakeCompileEvent(script, true).ToHandle(&event_data)) return; |
2681 | 2652 |
2682 // Process debug event. | 2653 // Process debug event. |
2683 ProcessDebugEvent(v8::BeforeCompile, | 2654 ProcessDebugEvent(v8::BeforeCompile, |
2684 Handle<JSObject>::cast(event_data), | 2655 Handle<JSObject>::cast(event_data), |
2685 true); | 2656 true); |
2686 } | 2657 } |
2687 | 2658 |
2688 | 2659 |
2689 // Handle debugger actions when a new script is compiled. | 2660 // Handle debugger actions when a new script is compiled. |
2690 void Debug::OnAfterCompile(Handle<Script> script, | 2661 void Debug::OnAfterCompile(Handle<Script> script, |
2691 AfterCompileFlags after_compile_flags) { | 2662 AfterCompileFlags after_compile_flags) { |
2692 HandleScope scope(isolate_); | |
2693 | |
2694 // Add the newly compiled script to the script cache. | 2663 // Add the newly compiled script to the script cache. |
2695 AddScriptToScriptCache(script); | 2664 if (script_cache_ != NULL) script_cache_->Add(script); |
2696 | 2665 |
2697 // No more to do if not debugging. | 2666 // No more to do if not debugging. |
2698 if (!EventActive()) return; | 2667 if (is_entered() || ignore_events()) return; |
2699 | 2668 |
2669 HandleScope scope(isolate_); | |
2700 // Store whether in debugger before entering debugger. | 2670 // Store whether in debugger before entering debugger. |
2701 bool in_debugger = is_entered(); | 2671 bool in_debugger = is_entered(); |
2702 | 2672 |
2703 // Enter the debugger. | 2673 // Enter the debugger. |
2704 EnterDebugger debugger(isolate_); | 2674 EnterDebugger debugger(isolate_); |
2705 if (debugger.FailedToEnter()) return; | 2675 if (debugger.FailedToEnter()) return; |
2706 | 2676 |
2707 // If debugging there might be script break points registered for this | 2677 // If debugging there might be script break points registered for this |
2708 // script. Make sure that these break points are set. | 2678 // script. Make sure that these break points are set. |
2709 | 2679 |
(...skipping 29 matching lines...) Expand all Loading... | |
2739 Handle<Object> event_data; | 2709 Handle<Object> event_data; |
2740 // Bail out and don't call debugger if exception. | 2710 // Bail out and don't call debugger if exception. |
2741 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return; | 2711 if (!MakeCompileEvent(script, false).ToHandle(&event_data)) return; |
2742 | 2712 |
2743 // Process debug event. | 2713 // Process debug event. |
2744 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); | 2714 ProcessDebugEvent(v8::AfterCompile, Handle<JSObject>::cast(event_data), true); |
2745 } | 2715 } |
2746 | 2716 |
2747 | 2717 |
2748 void Debug::OnScriptCollected(int id) { | 2718 void Debug::OnScriptCollected(int id) { |
2719 if (is_entered() || ignore_events()) return; | |
2720 | |
2749 HandleScope scope(isolate_); | 2721 HandleScope scope(isolate_); |
2750 | |
2751 // No more to do if not debugging. | |
2752 if (is_entered()) return; | |
2753 if (!EventActive()) return; | |
2754 | |
2755 // Enter the debugger. | 2722 // Enter the debugger. |
2756 EnterDebugger debugger(isolate_); | 2723 EnterDebugger debugger(isolate_); |
2757 if (debugger.FailedToEnter()) return; | 2724 if (debugger.FailedToEnter()) return; |
2758 | 2725 |
2759 // Create the script collected state object. | 2726 // Create the script collected state object. |
2760 Handle<Object> event_data; | 2727 Handle<Object> event_data; |
2761 // Bail out and don't call debugger if exception. | 2728 // Bail out and don't call debugger if exception. |
2762 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; | 2729 if (!MakeScriptCollectedEvent(id).ToHandle(&event_data)) return; |
2763 | 2730 |
2764 // Process debug event. | 2731 // Process debug event. |
2765 ProcessDebugEvent(v8::ScriptCollected, | 2732 ProcessDebugEvent(v8::ScriptCollected, |
2766 Handle<JSObject>::cast(event_data), | 2733 Handle<JSObject>::cast(event_data), |
2767 true); | 2734 true); |
2768 } | 2735 } |
2769 | 2736 |
2770 | 2737 |
2771 void Debug::ProcessDebugEvent(v8::DebugEvent event, | 2738 void Debug::ProcessDebugEvent(v8::DebugEvent event, |
2772 Handle<JSObject> event_data, | 2739 Handle<JSObject> event_data, |
2773 bool auto_continue) { | 2740 bool auto_continue) { |
2774 HandleScope scope(isolate_); | 2741 HandleScope scope(isolate_); |
2775 | 2742 |
2776 // Clear any pending debug break if this is a real break. | |
2777 if (!auto_continue) thread_local_.has_pending_interrupt_ = false; | |
2778 | |
2779 // Create the execution state. | 2743 // Create the execution state. |
2780 Handle<Object> exec_state; | 2744 Handle<Object> exec_state; |
2781 // Bail out and don't call debugger if exception. | 2745 // Bail out and don't call debugger if exception. |
2782 if (!MakeExecutionState().ToHandle(&exec_state)) return; | 2746 if (!MakeExecutionState().ToHandle(&exec_state)) return; |
2783 | 2747 |
2784 // First notify the message handler if any. | 2748 // First notify the message handler if any. |
2785 if (message_handler_ != NULL) { | 2749 if (message_handler_ != NULL) { |
2786 NotifyMessageHandler(event, | 2750 NotifyMessageHandler(event, |
2787 Handle<JSObject>::cast(exec_state), | 2751 Handle<JSObject>::cast(exec_state), |
2788 event_data, | 2752 event_data, |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3083 Handle<Object> argv[] = { exec_state, data }; | 3047 Handle<Object> argv[] = { exec_state, data }; |
3084 return Execution::Call( | 3048 return Execution::Call( |
3085 isolate_, | 3049 isolate_, |
3086 fun, | 3050 fun, |
3087 Handle<Object>(debug_context()->global_proxy(), isolate_), | 3051 Handle<Object>(debug_context()->global_proxy(), isolate_), |
3088 ARRAY_SIZE(argv), | 3052 ARRAY_SIZE(argv), |
3089 argv); | 3053 argv); |
3090 } | 3054 } |
3091 | 3055 |
3092 | 3056 |
3093 void Debug::DebugBreakHelper() { | 3057 void Debug::HandleDebugBreak() { |
3094 // Ignore debug break during bootstrapping. | 3058 // Ignore debug break during bootstrapping. |
3095 if (isolate_->bootstrapper()->IsActive()) return; | 3059 if (isolate_->bootstrapper()->IsActive()) return; |
3096 // Just continue if breaks are disabled. | 3060 // Just continue if breaks are disabled. |
3097 if (break_disabled_) return; | 3061 if (break_disabled_) return; |
3098 // Ignore debug break if debugger is not active. | 3062 // Ignore debug break if debugger is not active. |
3099 if (!is_active()) return; | 3063 if (!is_active()) return; |
3100 | 3064 |
3101 StackLimitCheck check(isolate_); | 3065 StackLimitCheck check(isolate_); |
3102 if (check.HasOverflowed()) return; | 3066 if (check.HasOverflowed()) return; |
3103 | 3067 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3149 // Link recursive debugger entry. | 3113 // Link recursive debugger entry. |
3150 debug->thread_local_.debugger_entry_ = this; | 3114 debug->thread_local_.debugger_entry_ = this; |
3151 | 3115 |
3152 // Store the previous break id and frame id. | 3116 // Store the previous break id and frame id. |
3153 break_id_ = debug->break_id(); | 3117 break_id_ = debug->break_id(); |
3154 break_frame_id_ = debug->break_frame_id(); | 3118 break_frame_id_ = debug->break_frame_id(); |
3155 | 3119 |
3156 // Create the new break info. If there is no JavaScript frames there is no | 3120 // Create the new break info. If there is no JavaScript frames there is no |
3157 // break frame id. | 3121 // break frame id. |
3158 JavaScriptFrameIterator it(isolate_); | 3122 JavaScriptFrameIterator it(isolate_); |
3159 has_js_frames_ = !it.done(); | 3123 bool has_js_frames = !it.done(); |
3160 debug->thread_local_.break_frame_id_ = has_js_frames_ ? it.frame()->id() | 3124 debug->thread_local_.break_frame_id_ = has_js_frames ? it.frame()->id() |
3161 : StackFrame::NO_ID; | 3125 : StackFrame::NO_ID; |
3162 debug->SetNextBreakId(); | 3126 debug->SetNextBreakId(); |
3163 | 3127 |
3164 debug->UpdateState(); | 3128 debug->UpdateState(); |
3165 // Make sure that debugger is loaded and enter the debugger context. | 3129 // Make sure that debugger is loaded and enter the debugger context. |
3166 // The previous context is kept in save_. | 3130 // The previous context is kept in save_. |
3167 load_failed_ = !debug->is_loaded(); | 3131 load_failed_ = !debug->is_loaded(); |
3168 if (!load_failed_) isolate_->set_context(*debug->debug_context()); | 3132 if (!load_failed_) isolate_->set_context(*debug->debug_context()); |
3169 } | 3133 } |
3170 | 3134 |
3171 | 3135 |
3172 EnterDebugger::~EnterDebugger() { | 3136 EnterDebugger::~EnterDebugger() { |
3173 Debug* debug = isolate_->debug(); | 3137 Debug* debug = isolate_->debug(); |
3174 | 3138 |
3175 // Restore to the previous break state. | 3139 // Restore to the previous break state. |
3176 debug->thread_local_.break_frame_id_ = break_frame_id_; | 3140 debug->thread_local_.break_frame_id_ = break_frame_id_; |
3177 debug->thread_local_.break_id_ = break_id_; | 3141 debug->thread_local_.break_id_ = break_id_; |
3178 | 3142 |
3179 // Check for leaving the debugger. | 3143 // Check for leaving the debugger. |
3180 if (!load_failed_ && prev_ == NULL) { | 3144 if (!load_failed_ && prev_ == NULL) { |
3181 // Clear mirror cache when leaving the debugger. Skip this if there is a | 3145 // Clear mirror cache when leaving the debugger. Skip this if there is a |
3182 // pending exception as clearing the mirror cache calls back into | 3146 // pending exception as clearing the mirror cache calls back into |
3183 // JavaScript. This can happen if the v8::Debug::Call is used in which | 3147 // JavaScript. This can happen if the v8::Debug::Call is used in which |
3184 // case the exception should end up in the calling code. | 3148 // case the exception should end up in the calling code. |
3185 if (!isolate_->has_pending_exception()) { | 3149 if (!isolate_->has_pending_exception()) debug->ClearMirrorCache(); |
3186 debug->ClearMirrorCache(); | |
3187 } | |
3188 | 3150 |
3189 // If there are commands in the queue when leaving the debugger request | 3151 // If there are commands in the queue when leaving the debugger request |
3190 // that these commands are processed. | 3152 // that these commands are processed. |
3191 if (debug->has_commands()) isolate_->stack_guard()->RequestDebugCommand(); | 3153 if (debug->has_commands()) isolate_->stack_guard()->RequestDebugCommand(); |
3192 } | 3154 } |
3193 | 3155 |
3194 // Leaving this debugger entry. | 3156 // Leaving this debugger entry. |
3195 debug->thread_local_.debugger_entry_ = prev_; | 3157 debug->thread_local_.debugger_entry_ = prev_; |
3196 | 3158 |
3197 debug->UpdateState(); | 3159 debug->UpdateState(); |
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3357 } | 3319 } |
3358 | 3320 |
3359 | 3321 |
3360 CommandMessage::CommandMessage(const Vector<uint16_t>& text, | 3322 CommandMessage::CommandMessage(const Vector<uint16_t>& text, |
3361 v8::Debug::ClientData* data) | 3323 v8::Debug::ClientData* data) |
3362 : text_(text), | 3324 : text_(text), |
3363 client_data_(data) { | 3325 client_data_(data) { |
3364 } | 3326 } |
3365 | 3327 |
3366 | 3328 |
3367 CommandMessage::~CommandMessage() { | |
3368 } | |
3369 | |
3370 | |
3371 void CommandMessage::Dispose() { | 3329 void CommandMessage::Dispose() { |
3372 text_.Dispose(); | 3330 text_.Dispose(); |
3373 delete client_data_; | 3331 delete client_data_; |
3374 client_data_ = NULL; | 3332 client_data_ = NULL; |
3375 } | 3333 } |
3376 | 3334 |
3377 | 3335 |
3378 CommandMessage CommandMessage::New(const Vector<uint16_t>& command, | 3336 CommandMessage CommandMessage::New(const Vector<uint16_t>& command, |
3379 v8::Debug::ClientData* data) { | 3337 v8::Debug::ClientData* data) { |
3380 return CommandMessage(command.Clone(), data); | 3338 return CommandMessage(command.Clone(), data); |
3381 } | 3339 } |
3382 | 3340 |
3383 | 3341 |
3384 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0), | 3342 CommandMessageQueue::CommandMessageQueue(int size) : start_(0), end_(0), |
3385 size_(size) { | 3343 size_(size) { |
3386 messages_ = NewArray<CommandMessage>(size); | 3344 messages_ = NewArray<CommandMessage>(size); |
3387 } | 3345 } |
3388 | 3346 |
3389 | 3347 |
3390 CommandMessageQueue::~CommandMessageQueue() { | 3348 CommandMessageQueue::~CommandMessageQueue() { |
3391 while (!IsEmpty()) { | 3349 while (!IsEmpty()) Get().Dispose(); |
3392 CommandMessage m = Get(); | |
3393 m.Dispose(); | |
3394 } | |
3395 DeleteArray(messages_); | 3350 DeleteArray(messages_); |
3396 } | 3351 } |
3397 | 3352 |
3398 | 3353 |
3399 CommandMessage CommandMessageQueue::Get() { | 3354 CommandMessage CommandMessageQueue::Get() { |
3400 ASSERT(!IsEmpty()); | 3355 ASSERT(!IsEmpty()); |
3401 int result = start_; | 3356 int result = start_; |
3402 start_ = (start_ + 1) % size_; | 3357 start_ = (start_ + 1) % size_; |
3403 return messages_[result]; | 3358 return messages_[result]; |
3404 } | 3359 } |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3451 logger_->DebugEvent("Put", message.text()); | 3406 logger_->DebugEvent("Put", message.text()); |
3452 } | 3407 } |
3453 | 3408 |
3454 | 3409 |
3455 void LockingCommandMessageQueue::Clear() { | 3410 void LockingCommandMessageQueue::Clear() { |
3456 LockGuard<Mutex> lock_guard(&mutex_); | 3411 LockGuard<Mutex> lock_guard(&mutex_); |
3457 queue_.Clear(); | 3412 queue_.Clear(); |
3458 } | 3413 } |
3459 | 3414 |
3460 } } // namespace v8::internal | 3415 } } // namespace v8::internal |
OLD | NEW |