51 #include "../include/v8-debug.h"
56 #ifdef ENABLE_DEBUGGER_SUPPORT
59 Debug::Debug(Isolate* isolate)
60 : has_break_points_(
false),
62 debug_info_list_(
NULL),
63 disable_break_(
false),
64 break_on_exception_(
false),
65 break_on_uncaught_exception_(
false),
66 debug_break_return_(
NULL),
67 debug_break_slot_(
NULL),
79 ScopedVector<char> data(s->Utf8Length() + 1);
80 if (data.start() ==
NULL) {
84 s->WriteUtf8(data.start());
85 PrintF(
"%s\n", data.start());
90 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
94 Handle<Context> native_context(context->native_context());
99 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
100 BreakLocatorType type) {
101 debug_info_ = debug_info;
103 reloc_iterator_ =
NULL;
104 reloc_iterator_original_ =
NULL;
109 BreakLocationIterator::~BreakLocationIterator() {
112 delete reloc_iterator_;
113 delete reloc_iterator_original_;
117 void BreakLocationIterator::Next() {
123 bool first = break_point_ == -1;
124 while (!RinfoDone()) {
125 if (!first) RinfoNext();
127 if (RinfoDone())
return;
131 if (RelocInfo::IsPosition(rmode())) {
132 if (RelocInfo::IsStatementPosition(rmode())) {
133 statement_position_ =
static_cast<int>(
134 rinfo()->data() - debug_info_->shared()->start_position());
138 position_ =
static_cast<int>(
139 rinfo()->data() - debug_info_->shared()->start_position());
141 ASSERT(statement_position_ >= 0);
144 if (IsDebugBreakSlot()) {
148 }
else if (RelocInfo::IsCodeTarget(rmode())) {
152 Address target = original_rinfo()->target_address();
154 if ((code->is_inline_cache_stub() &&
155 !code->is_binary_op_stub() &&
156 !code->is_compare_ic_stub() &&
157 !code->is_to_boolean_ic_stub()) ||
158 RelocInfo::IsConstructCall(rmode())) {
163 if (IsDebuggerStatement()) {
167 if (type_ == ALL_BREAK_LOCATIONS) {
168 if (Debug::IsBreakStub(code)) {
173 ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
174 if (Debug::IsSourceBreakStub(code)) {
183 if (RelocInfo::IsJSReturn(rmode())) {
185 if (debug_info_->shared()->HasSourceCode()) {
186 position_ = debug_info_->shared()->end_position() -
187 debug_info_->shared()->start_position() - 1;
191 statement_position_ = position_;
199 void BreakLocationIterator::Next(
int count) {
209 void BreakLocationIterator::FindBreakLocationFromAddress(
Address pc) {
211 int closest_break_point = 0;
215 if (this->
pc() <= pc && pc - this->
pc() < distance) {
216 closest_break_point = break_point();
217 distance =
static_cast<int>(pc - this->
pc());
219 if (distance == 0)
break;
226 Next(closest_break_point);
231 void BreakLocationIterator::FindBreakLocationFromPosition(
int position,
232 BreakPositionAlignment alignment) {
235 int closest_break_point = 0;
241 case STATEMENT_ALIGNED:
242 next_position = this->statement_position();
244 case BREAK_POSITION_ALIGNED:
245 next_position = this->position();
249 next_position = this->statement_position();
252 if (position <= next_position && next_position - position < distance) {
253 closest_break_point = break_point();
254 distance = next_position - position;
256 if (distance == 0)
break;
263 Next(closest_break_point);
267 void BreakLocationIterator::Reset() {
269 if (reloc_iterator_ !=
NULL)
delete reloc_iterator_;
270 if (reloc_iterator_original_ !=
NULL)
delete reloc_iterator_original_;
271 reloc_iterator_ =
new RelocIterator(
273 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
274 reloc_iterator_original_ =
new RelocIterator(
275 debug_info_->original_code(),
276 ~RelocInfo::ModeMask(RelocInfo::CODE_AGE_SEQUENCE));
281 statement_position_ = 1;
286 bool BreakLocationIterator::Done()
const {
291 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
294 if (!HasBreakPoint()) {
297 ASSERT(IsDebugBreak() || IsDebuggerStatement());
299 DebugInfo::SetBreakPoint(debug_info_, code_position(),
300 position(), statement_position(),
305 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
307 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
309 if (!HasBreakPoint()) {
316 void BreakLocationIterator::SetOneShot() {
318 if (IsDebuggerStatement()) {
323 if (HasBreakPoint()) {
333 void BreakLocationIterator::ClearOneShot() {
335 if (IsDebuggerStatement()) {
340 if (HasBreakPoint()) {
351 void BreakLocationIterator::SetDebugBreak() {
353 if (IsDebuggerStatement()) {
361 if (IsDebugBreak()) {
365 if (RelocInfo::IsJSReturn(rmode())) {
367 SetDebugBreakAtReturn();
368 }
else if (IsDebugBreakSlot()) {
370 SetDebugBreakAtSlot();
379 void BreakLocationIterator::ClearDebugBreak() {
381 if (IsDebuggerStatement()) {
385 if (RelocInfo::IsJSReturn(rmode())) {
387 ClearDebugBreakAtReturn();
388 }
else if (IsDebugBreakSlot()) {
390 ClearDebugBreakAtSlot();
393 ClearDebugBreakAtIC();
399 bool BreakLocationIterator::IsStepInLocation(Isolate* isolate) {
400 if (RelocInfo::IsConstructCall(original_rmode())) {
402 }
else if (RelocInfo::IsCodeTarget(rmode())) {
403 HandleScope scope(debug_info_->GetIsolate());
404 Address target = original_rinfo()->target_address();
407 return target_code->major_key() == CodeStub::CallFunction;
414 void BreakLocationIterator::PrepareStepIn(Isolate* isolate) {
416 HandleScope scope(isolate);
419 Address target = rinfo()->target_address();
423 Handle<Code> maybe_call_function_stub = target_code;
424 if (IsDebugBreak()) {
425 Address original_target = original_rinfo()->target_address();
426 maybe_call_function_stub =
429 bool is_call_function_stub =
430 (maybe_call_function_stub->kind() ==
Code::STUB &&
431 maybe_call_function_stub->major_key() == CodeStub::CallFunction);
440 ASSERT(RelocInfo::IsConstructCall(rmode()) ||
441 target_code->is_inline_cache_stub() ||
442 is_call_function_stub);
448 bool BreakLocationIterator::IsExit()
const {
449 return (RelocInfo::IsJSReturn(rmode()));
453 bool BreakLocationIterator::HasBreakPoint() {
454 return debug_info_->HasBreakPoint(code_position());
459 bool BreakLocationIterator::IsDebugBreak() {
460 if (RelocInfo::IsJSReturn(rmode())) {
461 return IsDebugBreakAtReturn();
462 }
else if (IsDebugBreakSlot()) {
463 return IsDebugBreakAtSlot();
465 return Debug::IsDebugBreak(rinfo()->target_address());
470 void BreakLocationIterator::SetDebugBreakAtIC() {
473 original_rinfo()->set_target_address(rinfo()->target_address());
475 RelocInfo::Mode
mode = rmode();
476 if (RelocInfo::IsCodeTarget(mode)) {
477 Address target = rinfo()->target_address();
482 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode));
483 rinfo()->set_target_address(dbgbrk_code->entry());
488 void BreakLocationIterator::ClearDebugBreakAtIC() {
490 rinfo()->set_target_address(original_rinfo()->target_address());
494 bool BreakLocationIterator::IsDebuggerStatement() {
499 bool BreakLocationIterator::IsDebugBreakSlot() {
500 return RelocInfo::DEBUG_BREAK_SLOT == rmode();
504 Object* BreakLocationIterator::BreakPointObjects() {
505 return debug_info_->GetBreakPointObjects(code_position());
512 void BreakLocationIterator::ClearAllDebugBreak() {
520 bool BreakLocationIterator::RinfoDone()
const {
521 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
522 return reloc_iterator_->done();
526 void BreakLocationIterator::RinfoNext() {
527 reloc_iterator_->next();
528 reloc_iterator_original_->next();
530 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
531 if (!reloc_iterator_->done()) {
532 ASSERT(rmode() == original_rmode());
539 void Debug::ThreadInit() {
540 thread_local_.break_count_ = 0;
541 thread_local_.break_id_ = 0;
542 thread_local_.break_frame_id_ = StackFrame::NO_ID;
543 thread_local_.last_step_action_ = StepNone;
544 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
545 thread_local_.step_count_ = 0;
546 thread_local_.last_fp_ = 0;
547 thread_local_.queued_step_count_ = 0;
548 thread_local_.step_into_fp_ = 0;
549 thread_local_.step_out_fp_ = 0;
550 thread_local_.after_break_target_ = 0;
552 thread_local_.debugger_entry_ =
NULL;
553 thread_local_.pending_interrupts_ = 0;
554 thread_local_.restarter_frame_function_pointer_ =
NULL;
558 char* Debug::ArchiveDebug(
char* storage) {
560 OS::MemCopy(to, reinterpret_cast<char*>(&thread_local_),
sizeof(ThreadLocal));
561 to +=
sizeof(ThreadLocal);
562 OS::MemCopy(to, reinterpret_cast<char*>(®isters_),
sizeof(registers_));
564 ASSERT(to <= storage + ArchiveSpacePerThread());
565 return storage + ArchiveSpacePerThread();
569 char* Debug::RestoreDebug(
char* storage) {
570 char* from = storage;
572 reinterpret_cast<char*>(&thread_local_), from,
sizeof(ThreadLocal));
573 from +=
sizeof(ThreadLocal);
574 OS::MemCopy(reinterpret_cast<char*>(®isters_), from,
sizeof(registers_));
575 ASSERT(from <= storage + ArchiveSpacePerThread());
576 return storage + ArchiveSpacePerThread();
580 int Debug::ArchiveSpacePerThread() {
592 ASSERT(bottom_js_frame->is_java_script());
608 const int Debug::kFrameDropperFrameSize = 4;
611 void ScriptCache::Add(Handle<Script> script) {
612 GlobalHandles* global_handles = isolate_->global_handles();
614 int id = script->id()->value();
615 HashMap::Entry* entry =
617 if (entry->value !=
NULL) {
618 ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
623 Handle<Script> script_ =
627 ScriptCache::HandleWeakScript);
628 entry->value = script_.location();
632 Handle<FixedArray> ScriptCache::GetScripts() {
633 Factory* factory = isolate_->factory();
634 Handle<FixedArray> instances = factory->NewFixedArray(occupancy());
636 for (HashMap::Entry* entry = Start(); entry !=
NULL; entry = Next(entry)) {
638 if (entry->value !=
NULL) {
639 instances->set(count, *reinterpret_cast<Script**>(entry->value));
647 void ScriptCache::ProcessCollectedScripts() {
648 Debugger* debugger = isolate_->debugger();
649 for (
int i = 0; i < collected_scripts_.length(); i++) {
650 debugger->OnScriptCollected(collected_scripts_[i]);
652 collected_scripts_.Clear();
656 void ScriptCache::Clear() {
658 for (HashMap::Entry* entry = Start(); entry !=
NULL; entry = Next(entry)) {
660 Object** location =
reinterpret_cast<Object**
>(entry->value);
661 ASSERT((*location)->IsScript());
670 void ScriptCache::HandleWeakScript(
675 void* key =
reinterpret_cast<void*
>(id);
676 uint32_t hash = Hash(
id);
679 ScriptCache* script_cache =
681 HashMap::Entry* entry = script_cache->Lookup(key, hash,
false);
682 Object** location =
reinterpret_cast<Object**
>(entry->value);
683 script_cache->Remove(key, hash);
684 script_cache->collected_scripts_.Add(
id);
691 void Debug::SetUp(
bool create_heap_objects) {
693 if (create_heap_objects) {
695 debug_break_return_ =
696 isolate_->builtins()->builtin(Builtins::kReturn_DebugBreak);
697 ASSERT(debug_break_return_->IsCode());
700 isolate_->builtins()->builtin(Builtins::kSlot_DebugBreak);
701 ASSERT(debug_break_slot_->IsCode());
706 void Debug::HandleWeakDebugInfo(
708 Debug* debug =
reinterpret_cast<Isolate*
>(data.
GetIsolate())->debug();
709 DebugInfoListNode* node =
710 reinterpret_cast<DebugInfoListNode*
>(data.
GetParameter());
715 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
716 it.ClearAllDebugBreak();
717 debug->RemoveDebugInfo(node->debug_info());
719 for (DebugInfoListNode* n = debug->debug_info_list_;
728 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(
NULL) {
730 GlobalHandles* global_handles = debug_info->GetIsolate()->global_handles();
734 Debug::HandleWeakDebugInfo);
738 DebugInfoListNode::~DebugInfoListNode() {
743 bool Debug::CompileDebuggerScript(Isolate* isolate,
int index) {
744 Factory* factory = isolate->factory();
745 HandleScope scope(isolate);
753 Handle<String> source_code =
754 isolate->bootstrapper()->NativesSourceLookup(index);
756 Handle<String> script_name = factory->NewStringFromAscii(name);
757 ASSERT(!script_name.is_null());
758 Handle<Context> context = isolate->native_context();
761 Handle<SharedFunctionInfo> function_info;
770 if (function_info.is_null()) {
771 ASSERT(isolate->has_pending_exception());
772 isolate->clear_pending_exception();
777 bool caught_exception;
778 Handle<JSFunction>
function =
779 factory->NewFunctionFromSharedFunctionInfo(function_info, context);
781 Handle<Object> exception =
783 Handle<Object>(context->global_object(), isolate),
789 if (caught_exception) {
790 ASSERT(!isolate->has_pending_exception());
791 MessageLocation computed_location;
792 isolate->ComputeLocation(&computed_location);
794 isolate,
"error_loading_debugger", &computed_location,
795 Vector<Handle<Object> >::empty(), Handle<JSArray>());
796 ASSERT(!isolate->has_pending_exception());
797 if (!exception.is_null()) {
798 isolate->set_pending_exception(*exception);
800 isolate->clear_pending_exception();
806 Handle<Script> script(
Script::cast(function->shared()->script()));
814 if (IsLoaded())
return true;
816 Debugger* debugger = isolate_->debugger();
820 if (debugger->compiling_natives() ||
821 debugger->is_loading_debugger())
823 debugger->set_loading_debugger(
true);
827 DisableBreak disable(isolate_,
true);
828 PostponeInterruptsScope postpone(isolate_);
831 HandleScope scope(isolate_);
832 ExtensionConfiguration no_extensions;
833 Handle<Context> context =
834 isolate_->bootstrapper()->CreateEnvironment(
835 Handle<Object>::null(),
840 if (context.is_null())
return false;
843 SaveContext save(isolate_);
844 isolate_->set_context(*context);
847 Handle<String> key = isolate_->factory()->InternalizeOneByteString(
849 Handle<GlobalObject> global = Handle<GlobalObject>(context->global_object());
854 Handle<Object>(global->builtins(), isolate_),
860 debugger->set_compiling_natives(
true);
861 bool caught_exception =
865 if (FLAG_enable_liveedit) {
866 caught_exception = caught_exception ||
870 debugger->set_compiling_natives(
false);
874 debugger->set_loading_debugger(
false);
877 if (caught_exception)
return false;
881 isolate_->global_handles()->Create(*context));
887 void Debug::Unload() {
894 DestroyScriptCache();
898 debug_context_ = Handle<Context>();
903 void Debug::PreemptionWhileInDebugger() {
905 Debug::set_interrupts_pending(
PREEMPT);
909 void Debug::Iterate(ObjectVisitor* v) {
910 v->VisitPointer(BitCast<Object**>(&(debug_break_return_)));
911 v->VisitPointer(BitCast<Object**>(&(debug_break_slot_)));
916 Heap* heap = isolate_->heap();
917 HandleScope scope(isolate_);
918 ASSERT(args.length() == 0);
920 thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED;
923 JavaScriptFrameIterator it(isolate_);
924 JavaScriptFrame* frame = it.frame();
927 if (disable_break() || !
Load()) {
928 SetAfterBreakTarget(frame);
929 return heap->undefined_value();
933 EnterDebugger debugger(isolate_);
934 if (debugger.FailedToEnter()) {
935 return heap->undefined_value();
939 PostponeInterruptsScope postpone(isolate_);
942 Handle<SharedFunctionInfo> shared =
943 Handle<SharedFunctionInfo>(frame->function()->shared());
944 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
947 BreakLocationIterator break_location_iterator(debug_info,
948 ALL_BREAK_LOCATIONS);
951 break_location_iterator.FindBreakLocationFromAddress(frame->pc() - 1);
954 if (!StepNextContinue(&break_location_iterator, frame)) {
956 if (thread_local_.step_count_ > 0) {
957 thread_local_.step_count_--;
963 Handle<Object> break_points_hit(heap->undefined_value(), isolate_);
964 if (break_location_iterator.HasBreakPoint()) {
965 Handle<Object> break_point_objects =
966 Handle<Object>(break_location_iterator.BreakPointObjects(), isolate_);
967 break_points_hit = CheckBreakPoints(break_point_objects);
972 if (StepOutActive() && frame->fp() != step_out_fp() &&
973 break_points_hit->IsUndefined() ) {
975 ASSERT(thread_local_.step_count_ == 0);
976 }
else if (!break_points_hit->IsUndefined() ||
977 (thread_local_.last_step_action_ != StepNone &&
978 thread_local_.step_count_ == 0)) {
985 if (thread_local_.queued_step_count_ > 0) {
987 int step_count = thread_local_.queued_step_count_;
990 thread_local_.queued_step_count_ = 0;
992 PrepareStep(StepNext, step_count, StackFrame::NO_ID);
995 isolate_->debugger()->OnDebugBreak(break_points_hit,
false);
997 }
else if (thread_local_.last_step_action_ != StepNone) {
1000 StepAction step_action = thread_local_.last_step_action_;
1001 int step_count = thread_local_.step_count_;
1005 if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
1008 JavaScriptFrameIterator it(isolate_);
1009 while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
1015 CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
1016 if (step_count > 1) {
1018 thread_local_.queued_step_count_ = step_count - 1;
1022 step_action = StepOut;
1030 PrepareStep(step_action, step_count, StackFrame::NO_ID);
1033 if (thread_local_.frame_drop_mode_ == FRAMES_UNTOUCHED) {
1034 SetAfterBreakTarget(frame);
1035 }
else if (thread_local_.frame_drop_mode_ ==
1036 FRAME_DROPPED_IN_IC_CALL) {
1038 Code* plain_return = isolate_->builtins()->builtin(
1039 Builtins::kPlainReturn_LiveEdit);
1040 thread_local_.after_break_target_ = plain_return->entry();
1041 }
else if (thread_local_.frame_drop_mode_ ==
1042 FRAME_DROPPED_IN_DEBUG_SLOT_CALL) {
1045 Code* plain_return = isolate_->builtins()->builtin(
1046 Builtins::kFrameDropper_LiveEdit);
1047 thread_local_.after_break_target_ = plain_return->entry();
1048 }
else if (thread_local_.frame_drop_mode_ ==
1049 FRAME_DROPPED_IN_DIRECT_CALL) {
1051 }
else if (thread_local_.frame_drop_mode_ ==
1052 FRAME_DROPPED_IN_RETURN_CALL) {
1053 Code* plain_return = isolate_->builtins()->builtin(
1054 Builtins::kFrameDropper_LiveEdit);
1055 thread_local_.after_break_target_ = plain_return->entry();
1060 return heap->undefined_value();
1065 return isolate->debug()->Break(args);
1072 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
1073 Factory* factory = isolate_->factory();
1077 Handle<FixedArray> break_points_hit;
1078 int break_points_hit_count = 0;
1079 ASSERT(!break_point_objects->IsUndefined());
1080 if (break_point_objects->IsFixedArray()) {
1082 break_points_hit = factory->NewFixedArray(array->length());
1083 for (
int i = 0; i < array->length(); i++) {
1084 Handle<Object> o(array->get(i), isolate_);
1085 if (CheckBreakPoint(o)) {
1086 break_points_hit->set(break_points_hit_count++, *o);
1090 break_points_hit = factory->NewFixedArray(1);
1091 if (CheckBreakPoint(break_point_objects)) {
1092 break_points_hit->set(break_points_hit_count++, *break_point_objects);
1097 if (break_points_hit_count == 0) {
1098 return factory->undefined_value();
1101 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
1102 result->set_length(
Smi::FromInt(break_points_hit_count));
1108 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
1109 Factory* factory = isolate_->factory();
1110 HandleScope scope(isolate_);
1113 if (!break_point_object->IsJSObject())
return true;
1116 Handle<String> is_break_point_triggered_string =
1117 factory->InternalizeOneByteString(
1119 Handle<JSFunction> check_break_point =
1121 debug_context()->global_object()->GetPropertyNoExceptionThrown(
1122 *is_break_point_triggered_string)));
1125 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
1128 bool caught_exception;
1129 Handle<Object> argv[] = { break_id, break_point_object };
1131 isolate_->js_builtins_object(),
1137 if (caught_exception || !result->IsBoolean()) {
1142 ASSERT(!result.is_null());
1143 return (*result)->IsTrue();
1148 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
1149 return !shared->debug_info()->IsUndefined();
1155 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
1156 ASSERT(HasDebugInfo(shared));
1157 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
1161 void Debug::SetBreakPoint(Handle<JSFunction>
function,
1162 Handle<Object> break_point_object,
1163 int* source_position) {
1164 HandleScope scope(isolate_);
1166 PrepareForBreakPoints();
1169 Handle<SharedFunctionInfo> shared(function->shared());
1170 if (!EnsureDebugInfo(shared,
function)) {
1175 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1177 ASSERT(*source_position >= 0);
1180 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1181 it.FindBreakLocationFromPosition(*source_position, STATEMENT_ALIGNED);
1182 it.SetBreakPoint(break_point_object);
1184 *source_position = it.position();
1187 ASSERT(debug_info->GetBreakPointCount() > 0);
1191 bool Debug::SetBreakPointForScript(Handle<Script> script,
1192 Handle<Object> break_point_object,
1193 int* source_position,
1194 BreakPositionAlignment alignment) {
1195 HandleScope scope(isolate_);
1197 PrepareForBreakPoints();
1200 Object* result = FindSharedFunctionInfoInScript(script, *source_position);
1201 if (result->IsUndefined())
return false;
1205 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1213 if (shared->start_position() > *source_position) {
1216 position = *source_position - shared->start_position();
1219 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1224 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1225 it.FindBreakLocationFromPosition(position, alignment);
1226 it.SetBreakPoint(break_point_object);
1228 *source_position = it.position() + shared->start_position();
1231 ASSERT(debug_info->GetBreakPointCount() > 0);
1236 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1237 HandleScope scope(isolate_);
1239 DebugInfoListNode* node = debug_info_list_;
1240 while (node !=
NULL) {
1241 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
1242 break_point_object);
1243 if (!result->IsUndefined()) {
1245 BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
1246 Handle<DebugInfo> debug_info = node->debug_info();
1249 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1250 it.FindBreakLocationFromAddress(debug_info->code()->entry() +
1251 break_point_info->code_position()->value());
1252 it.ClearBreakPoint(break_point_object);
1256 if (debug_info->GetBreakPointCount() == 0) {
1257 RemoveDebugInfo(debug_info);
1262 node = node->next();
1267 void Debug::ClearAllBreakPoints() {
1268 DebugInfoListNode* node = debug_info_list_;
1269 while (node !=
NULL) {
1271 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1272 it.ClearAllDebugBreak();
1273 node = node->next();
1277 while (debug_info_list_ !=
NULL) {
1278 RemoveDebugInfo(debug_info_list_->debug_info());
1283 void Debug::FloodWithOneShot(Handle<JSFunction>
function) {
1284 PrepareForBreakPoints();
1287 Handle<SharedFunctionInfo> shared(function->shared());
1288 if (!EnsureDebugInfo(shared,
function)) {
1294 BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
1295 while (!it.Done()) {
1302 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction>
function) {
1303 Handle<FixedArray> new_bindings(function->function_bindings());
1307 if (!bindee.is_null() && bindee->IsJSFunction() &&
1310 Debug::FloodWithOneShot(bindee_function);
1315 void Debug::FloodHandlerWithOneShot() {
1317 StackFrame::Id
id = break_frame_id();
1318 if (
id == StackFrame::NO_ID) {
1322 for (JavaScriptFrameIterator it(isolate_,
id); !it.done(); it.Advance()) {
1323 JavaScriptFrame* frame = it.frame();
1324 if (frame->HasHandler()) {
1326 FloodWithOneShot(Handle<JSFunction>(frame->function()));
1333 void Debug::ChangeBreakOnException(ExceptionBreakType type,
bool enable) {
1334 if (type == BreakUncaughtException) {
1335 break_on_uncaught_exception_ = enable;
1337 break_on_exception_ = enable;
1342 bool Debug::IsBreakOnException(ExceptionBreakType type) {
1343 if (type == BreakUncaughtException) {
1344 return break_on_uncaught_exception_;
1346 return break_on_exception_;
1351 void Debug::PrepareStep(StepAction step_action,
1353 StackFrame::Id frame_id) {
1354 HandleScope scope(isolate_);
1356 PrepareForBreakPoints();
1358 ASSERT(Debug::InDebugger());
1361 thread_local_.last_step_action_ = step_action;
1362 if (step_action == StepOut) {
1365 thread_local_.step_count_ = 0;
1367 thread_local_.step_count_ = step_count;
1374 StackFrame::Id
id = break_frame_id();
1375 if (
id == StackFrame::NO_ID) {
1379 if (frame_id != StackFrame::NO_ID) {
1382 JavaScriptFrameIterator frames_it(isolate_,
id);
1383 JavaScriptFrame* frame = frames_it.frame();
1387 FloodHandlerWithOneShot();
1392 if (!frame->function()->IsJSFunction()) {
1395 frames_it.Advance();
1397 JSFunction*
function = frames_it.frame()->function();
1398 FloodWithOneShot(Handle<JSFunction>(
function));
1403 Handle<JSFunction>
function(frame->function());
1404 Handle<SharedFunctionInfo> shared(function->shared());
1405 if (!EnsureDebugInfo(shared,
function)) {
1409 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1412 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1415 it.FindBreakLocationFromAddress(frame->pc() - 1);
1418 bool is_load_or_store =
false;
1419 bool is_inline_cache_stub =
false;
1420 bool is_at_restarted_function =
false;
1421 Handle<Code> call_function_stub;
1423 if (thread_local_.restarter_frame_function_pointer_ ==
NULL) {
1424 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1425 bool is_call_target =
false;
1426 Address target = it.rinfo()->target_address();
1428 if (code->is_inline_cache_stub()) {
1429 is_inline_cache_stub =
true;
1430 is_load_or_store = !is_call_target;
1434 Code* maybe_call_function_stub =
code;
1437 if (it.IsDebugBreak()) {
1438 Address original_target = it.original_rinfo()->target_address();
1439 maybe_call_function_stub =
1442 if (maybe_call_function_stub->kind() ==
Code::STUB &&
1443 maybe_call_function_stub->major_key() == CodeStub::CallFunction) {
1446 call_function_stub = Handle<Code>(maybe_call_function_stub);
1450 is_at_restarted_function =
true;
1454 if (it.IsExit() || step_action == StepOut) {
1455 if (step_action == StepOut) {
1457 while (step_count-- > 0 && !frames_it.done()) {
1458 frames_it.Advance();
1462 frames_it.Advance();
1465 while (!frames_it.done() && frames_it.frame()->function()->IsBuiltin()) {
1466 frames_it.Advance();
1470 if (!frames_it.done()) {
1472 JSFunction*
function = frames_it.frame()->function();
1473 FloodWithOneShot(Handle<JSFunction>(
function));
1475 ActivateStepOut(frames_it.frame());
1477 }
else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
1478 !call_function_stub.is_null() || is_at_restarted_function)
1479 || step_action == StepNext || step_action == StepMin) {
1483 FloodWithOneShot(
function);
1486 thread_local_.last_statement_position_ =
1487 debug_info->code()->SourceStatementPosition(frame->pc());
1488 thread_local_.last_fp_ = frame->UnpaddedFP();
1492 if (is_at_restarted_function) {
1493 Handle<JSFunction> restarted_function(
1495 FloodWithOneShot(restarted_function);
1496 }
else if (!call_function_stub.is_null()) {
1504 isolate_->heap()->code_stubs()->SlowReverseLookup(
1505 *call_function_stub),
1508 ASSERT(!(*obj)->IsUndefined());
1514 int call_function_arg_count =
1516 CodeStub::MinorKeyFromKey(key));
1517 ASSERT(call_function_stub->major_key() ==
1518 CodeStub::MajorKeyFromKey(key));
1527 int expressions_count = frame->ComputeExpressionsCount();
1528 ASSERT(expressions_count - 2 - call_function_arg_count >= 0);
1529 Object* fun = frame->GetExpression(
1530 expressions_count - 2 - call_function_arg_count);
1533 if (fun->IsJSFunction()) {
1536 Code* call = isolate->builtins()->builtin(Builtins::kFunctionCall);
1537 while (fun->IsJSFunction()) {
1539 if (code != apply && code != call)
break;
1540 fun = frame->GetExpression(
1541 expressions_count - 1 - call_function_arg_count);
1545 if (fun->IsJSFunction()) {
1547 if (js_function->shared()->bound()) {
1548 Debug::FloodBoundFunctionWithOneShot(js_function);
1549 }
else if (!js_function->IsBuiltin()) {
1552 FloodWithOneShot(js_function);
1561 FloodWithOneShot(
function);
1563 if (is_load_or_store) {
1568 thread_local_.last_statement_position_ =
1569 debug_info->code()->SourceStatementPosition(frame->pc());
1570 thread_local_.last_fp_ = frame->UnpaddedFP();
1574 it.PrepareStepIn(isolate_);
1575 ActivateStepIn(frame);
1586 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1587 JavaScriptFrame* frame) {
1590 if (thread_local_.last_step_action_ == StepNext ||
1591 thread_local_.last_step_action_ == StepOut) {
1592 if (frame->fp() < thread_local_.last_fp_)
return true;
1597 if (thread_local_.last_step_action_ == StepNext ||
1598 thread_local_.last_step_action_ == StepIn) {
1600 if (break_location_iterator->IsExit())
return false;
1603 int current_statement_position =
1604 break_location_iterator->code()->SourceStatementPosition(frame->pc());
1605 return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1606 thread_local_.last_statement_position_ == current_statement_position;
1616 bool Debug::IsDebugBreak(
Address addr) {
1618 return code->is_debug_stub() && code->extra_ic_state() ==
DEBUG_BREAK;
1624 bool Debug::IsSourceBreakStub(Code* code) {
1625 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1626 return major_key == CodeStub::CallFunction;
1632 bool Debug::IsBreakStub(Code* code) {
1633 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1634 return major_key == CodeStub::CallFunction;
1639 Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
1640 Isolate* isolate = code->GetIsolate();
1644 if (code->is_inline_cache_stub()) {
1645 switch (code->kind()) {
1647 return isolate->builtins()->LoadIC_DebugBreak();
1649 case Code::STORE_IC:
1650 return isolate->builtins()->StoreIC_DebugBreak();
1652 case Code::KEYED_LOAD_IC:
1653 return isolate->builtins()->KeyedLoadIC_DebugBreak();
1655 case Code::KEYED_STORE_IC:
1656 return isolate->builtins()->KeyedStoreIC_DebugBreak();
1658 case Code::COMPARE_NIL_IC:
1659 return isolate->builtins()->CompareNilIC_DebugBreak();
1665 if (RelocInfo::IsConstructCall(mode)) {
1666 if (code->has_function_cache()) {
1667 return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
1669 return isolate->builtins()->CallConstructStub_DebugBreak();
1673 ASSERT(code->major_key() == CodeStub::CallFunction);
1674 if (code->has_function_cache()) {
1675 return isolate->builtins()->CallFunctionStub_Recording_DebugBreak();
1677 return isolate->builtins()->CallFunctionStub_DebugBreak();
1687 Handle<Object> Debug::GetSourceBreakLocations(
1688 Handle<SharedFunctionInfo> shared,
1689 BreakPositionAlignment position_alignment) {
1690 Isolate* isolate = shared->GetIsolate();
1691 Heap* heap = isolate->heap();
1692 if (!HasDebugInfo(shared)) {
1693 return Handle<Object>(heap->undefined_value(), isolate);
1695 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1696 if (debug_info->GetBreakPointCount() == 0) {
1697 return Handle<Object>(heap->undefined_value(), isolate);
1699 Handle<FixedArray> locations =
1700 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1702 for (
int i = 0; i < debug_info->break_points()->length(); i++) {
1703 if (!debug_info->break_points()->get(i)->IsUndefined()) {
1704 BreakPointInfo* break_point_info =
1705 BreakPointInfo::cast(debug_info->break_points()->get(i));
1706 if (break_point_info->GetBreakPointCount() > 0) {
1708 switch (position_alignment) {
1709 case STATEMENT_ALIGNED:
1710 position = break_point_info->statement_position();
1712 case BREAK_POSITION_ALIGNED:
1713 position = break_point_info->source_position();
1717 position = break_point_info->statement_position();
1720 locations->set(count++, position);
1728 void Debug::NewBreak(StackFrame::Id break_frame_id) {
1729 thread_local_.break_frame_id_ = break_frame_id;
1730 thread_local_.break_id_ = ++thread_local_.break_count_;
1734 void Debug::SetBreak(StackFrame::Id break_frame_id,
int break_id) {
1735 thread_local_.break_frame_id_ = break_frame_id;
1736 thread_local_.break_id_ = break_id;
1741 void Debug::HandleStepIn(Handle<JSFunction>
function,
1742 Handle<Object> holder,
1744 bool is_constructor) {
1745 Isolate* isolate =
function->GetIsolate();
1748 StackFrameIterator it(isolate);
1751 if (is_constructor) {
1752 ASSERT(it.frame()->is_construct());
1755 fp = it.frame()->fp();
1760 if (fp == step_in_fp()) {
1761 if (function->shared()->bound()) {
1763 Debug::FloodBoundFunctionWithOneShot(
function);
1764 }
else if (!function->IsBuiltin()) {
1766 if (function->shared()->code() ==
1767 isolate->builtins()->builtin(Builtins::kFunctionApply) ||
1768 function->shared()->code() ==
1769 isolate->builtins()->builtin(Builtins::kFunctionCall)) {
1774 if (!holder.is_null() && holder->IsJSFunction()) {
1776 if (!js_function->IsBuiltin()) {
1777 Debug::FloodWithOneShot(js_function);
1778 }
else if (js_function->shared()->bound()) {
1780 Debug::FloodBoundFunctionWithOneShot(js_function);
1784 Debug::FloodWithOneShot(
function);
1791 void Debug::ClearStepping() {
1799 thread_local_.step_count_ = 0;
1806 void Debug::ClearOneShot() {
1811 DebugInfoListNode* node = debug_info_list_;
1812 while (node !=
NULL) {
1813 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1814 while (!it.Done()) {
1818 node = node->next();
1823 void Debug::ActivateStepIn(
StackFrame* frame) {
1824 ASSERT(!StepOutActive());
1825 thread_local_.step_into_fp_ = frame->UnpaddedFP();
1829 void Debug::ClearStepIn() {
1830 thread_local_.step_into_fp_ = 0;
1834 void Debug::ActivateStepOut(
StackFrame* frame) {
1836 thread_local_.step_out_fp_ = frame->UnpaddedFP();
1840 void Debug::ClearStepOut() {
1841 thread_local_.step_out_fp_ = 0;
1845 void Debug::ClearStepNext() {
1846 thread_local_.last_step_action_ = StepNone;
1847 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1848 thread_local_.last_fp_ = 0;
1852 static void CollectActiveFunctionsFromThread(
1854 ThreadLocalTop* top,
1855 List<Handle<JSFunction> >* active_functions,
1856 Object* active_code_marker) {
1861 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1862 JavaScriptFrame* frame = it.frame();
1863 if (frame->is_optimized()) {
1864 List<JSFunction*> functions(FLAG_max_inlining_levels + 1);
1865 frame->GetFunctions(&functions);
1866 for (
int i = 0; i < functions.length(); i++) {
1867 JSFunction*
function = functions[i];
1868 active_functions->Add(Handle<JSFunction>(
function));
1869 function->shared()->code()->set_gc_metadata(active_code_marker);
1871 }
else if (frame->function()->IsJSFunction()) {
1872 JSFunction*
function = frame->function();
1873 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1874 active_functions->Add(Handle<JSFunction>(
function));
1875 function->shared()->code()->set_gc_metadata(active_code_marker);
1881 static void RedirectActivationsToRecompiledCodeOnThread(
1883 ThreadLocalTop* top) {
1884 for (JavaScriptFrameIterator it(isolate, top); !it.done(); it.Advance()) {
1885 JavaScriptFrame* frame = it.frame();
1887 if (frame->is_optimized() || !frame->function()->IsJSFunction())
continue;
1889 JSFunction*
function = frame->function();
1891 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1893 Handle<Code> frame_code(frame->LookupCode());
1894 if (frame_code->has_debug_break_slots())
continue;
1896 Handle<Code> new_code(function->shared()->code());
1897 if (new_code->kind() != Code::FUNCTION ||
1898 !new_code->has_debug_break_slots()) {
1907 int pool_mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1908 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1909 int frame_pool_size = 0;
1910 for (RelocIterator it(*frame_code, pool_mask); !it.done(); it.next()) {
1911 RelocInfo*
info = it.rinfo();
1912 if (info->pc() >= frame->pc())
break;
1913 frame_pool_size +=
static_cast<int>(info->data());
1915 intptr_t frame_offset =
1916 frame->pc() - frame_code->instruction_start() - frame_pool_size;
1920 int debug_break_slot_bytes = 0;
1921 int new_code_pool_size = 0;
1922 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
1923 RelocInfo::ModeMask(RelocInfo::CONST_POOL) |
1924 RelocInfo::ModeMask(RelocInfo::VENEER_POOL);
1925 for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
1928 RelocInfo* info = it.rinfo();
1929 intptr_t new_offset = info->pc() - new_code->instruction_start() -
1930 new_code_pool_size - debug_break_slot_bytes;
1931 if (new_offset >= frame_offset) {
1935 if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
1938 ASSERT(RelocInfo::IsConstPool(info->rmode()));
1940 new_code_pool_size +=
static_cast<int>(info->data());
1945 byte* new_pc = new_code->instruction_start() + frame_offset +
1946 debug_break_slot_bytes + new_code_pool_size;
1948 if (FLAG_trace_deopt) {
1953 reinterpret_cast<intptr_t>(
1954 frame_code->instruction_start()),
1955 reinterpret_cast<intptr_t>(
1956 frame_code->instruction_start()) +
1957 frame_code->instruction_size(),
1958 frame_code->instruction_size(),
1959 reinterpret_cast<intptr_t
>(new_code->instruction_start()),
1960 reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1961 new_code->instruction_size(),
1962 new_code->instruction_size(),
1963 reinterpret_cast<intptr_t
>(frame->pc()),
1964 reinterpret_cast<intptr_t>(new_pc));
1969 frame->set_pc(new_pc);
1974 class ActiveFunctionsCollector :
public ThreadVisitor {
1976 explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
1977 Object* active_code_marker)
1978 : active_functions_(active_functions),
1979 active_code_marker_(active_code_marker) { }
1981 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1982 CollectActiveFunctionsFromThread(isolate,
1985 active_code_marker_);
1989 List<Handle<JSFunction> >* active_functions_;
1990 Object* active_code_marker_;
1994 class ActiveFunctionsRedirector :
public ThreadVisitor {
1996 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1997 RedirectActivationsToRecompiledCodeOnThread(isolate, top);
2002 void Debug::PrepareForBreakPoints() {
2005 if (!has_break_points_) {
2006 if (isolate_->concurrent_recompilation_enabled()) {
2007 isolate_->optimizing_compiler_thread()->Flush();
2012 Handle<Code> lazy_compile = isolate_->builtins()->CompileUnoptimized();
2015 has_break_points_ =
true;
2019 List<Handle<JSFunction> > active_functions(100);
2024 Heap* heap = isolate_->heap();
2026 "preparing for breakpoints");
2032 Object* active_code_marker = heap->the_hole_value();
2034 CollectActiveFunctionsFromThread(isolate_,
2035 isolate_->thread_local_top(),
2037 active_code_marker);
2038 ActiveFunctionsCollector active_functions_collector(&active_functions,
2039 active_code_marker);
2040 isolate_->thread_manager()->IterateArchivedThreads(
2041 &active_functions_collector);
2046 HeapIterator iterator(heap);
2048 while (((obj = iterator.next()) !=
NULL)) {
2049 if (obj->IsJSFunction()) {
2051 SharedFunctionInfo* shared =
function->shared();
2053 if (!shared->allows_lazy_compilation())
continue;
2054 if (!shared->script()->IsScript())
continue;
2055 if (function->IsBuiltin())
continue;
2056 if (shared->code()->gc_metadata() == active_code_marker)
continue;
2059 if (kind == Code::FUNCTION &&
2060 !function->code()->has_debug_break_slots()) {
2061 function->set_code(*lazy_compile);
2062 function->shared()->set_code(*lazy_compile);
2064 (function->IsInOptimizationQueue() ||
2065 function->IsMarkedForOptimization() ||
2066 function->IsMarkedForConcurrentOptimization())) {
2068 Code* shared_code =
function->shared()->code();
2069 if (shared_code->kind() == Code::FUNCTION &&
2070 shared_code->has_debug_break_slots()) {
2071 function->set_code(shared_code);
2073 function->set_code(*lazy_compile);
2074 function->shared()->set_code(*lazy_compile);
2081 for (
int i = 0; i < active_functions.length(); i++) {
2082 Handle<JSFunction>
function = active_functions[i];
2083 function->shared()->code()->set_gc_metadata(
Smi::FromInt(0));
2089 for (
int i = 0; i < active_functions.length(); i++) {
2090 Handle<JSFunction>
function = active_functions[i];
2091 Handle<SharedFunctionInfo> shared(function->shared());
2093 if (function->code()->kind() == Code::FUNCTION &&
2094 function->code()->has_debug_break_slots()) {
2100 if (shared->is_toplevel() ||
2101 !shared->allows_lazy_compilation() ||
2108 if (!shared->code()->has_debug_break_slots()) {
2111 bool prev_force_debugger_active =
2112 isolate_->debugger()->force_debugger_active();
2113 isolate_->debugger()->set_force_debugger_active(
true);
2115 function->ReplaceCode(*code);
2116 isolate_->debugger()->set_force_debugger_active(
2117 prev_force_debugger_active);
2121 function->set_code(shared->code());
2124 RedirectActivationsToRecompiledCodeOnThread(isolate_,
2125 isolate_->thread_local_top());
2127 ActiveFunctionsRedirector active_functions_redirector;
2128 isolate_->thread_manager()->IterateArchivedThreads(
2129 &active_functions_redirector);
2134 Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2149 int target_start_position = RelocInfo::kNoPosition;
2150 Handle<JSFunction> target_function;
2151 Handle<SharedFunctionInfo> target;
2152 Heap* heap = isolate_->heap();
2155 heap->EnsureHeapIsIterable();
2157 HeapIterator iterator(heap);
2158 for (HeapObject* obj = iterator.next();
2159 obj !=
NULL; obj = iterator.next()) {
2160 bool found_next_candidate =
false;
2161 Handle<JSFunction>
function;
2162 Handle<SharedFunctionInfo> shared;
2163 if (obj->IsJSFunction()) {
2165 shared = Handle<SharedFunctionInfo>(
function->shared());
2166 ASSERT(shared->allows_lazy_compilation() || shared->is_compiled());
2167 found_next_candidate =
true;
2168 }
else if (obj->IsSharedFunctionInfo()) {
2172 found_next_candidate = shared->is_compiled() ||
2173 shared->allows_lazy_compilation_without_context();
2175 if (!found_next_candidate)
continue;
2176 if (shared->script() == *script) {
2179 int start_position = shared->function_token_position();
2180 if (start_position == RelocInfo::kNoPosition) {
2181 start_position = shared->start_position();
2183 if (start_position <= position &&
2184 position <= shared->end_position()) {
2187 if (target.is_null()) {
2188 target_start_position = start_position;
2189 target_function =
function;
2192 if (target_start_position == start_position &&
2193 shared->end_position() == target->end_position()) {
2197 if (!shared->is_toplevel()) {
2198 target_start_position = start_position;
2199 target_function =
function;
2202 }
else if (target_start_position <= start_position &&
2203 shared->end_position() <= target->end_position()) {
2207 target_start_position = start_position;
2208 target_function =
function;
2217 if (target.is_null())
return heap->undefined_value();
2220 has_break_points_ =
true;
2223 done = target->is_compiled();
2230 Handle<Code> result = target_function.is_null()
2232 : Compiler::GetUnoptimizedCode(target_function);
2233 if (result.is_null())
return isolate_->heap()->undefined_value();
2242 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2243 Handle<JSFunction>
function) {
2244 Isolate* isolate = shared->GetIsolate();
2247 if (HasDebugInfo(shared)) {
2248 ASSERT(shared->is_compiled());
2253 has_break_points_ =
true;
2256 if (!
function.is_null() &&
2262 Handle<DebugInfo> debug_info = isolate->factory()->NewDebugInfo(shared);
2265 DebugInfoListNode* node =
new DebugInfoListNode(*debug_info);
2266 node->set_next(debug_info_list_);
2267 debug_info_list_ = node;
2273 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
2276 DebugInfoListNode* prev =
NULL;
2277 DebugInfoListNode* current = debug_info_list_;
2278 while (current !=
NULL) {
2279 if (*current->debug_info() == *debug_info) {
2282 debug_info_list_ = current->next();
2284 prev->set_next(current->next());
2286 current->debug_info()->shared()->set_debug_info(
2287 isolate_->heap()->undefined_value());
2292 has_break_points_ = debug_info_list_ !=
NULL;
2298 current = current->next();
2304 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
2305 HandleScope scope(isolate_);
2307 PrepareForBreakPoints();
2311 Handle<SharedFunctionInfo> shared(function->shared());
2312 if (!EnsureDebugInfo(shared,
function)) {
2316 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2317 Handle<Code>
code(debug_info->code());
2318 Handle<Code> original_code(debug_info->original_code());
2321 Handle<Code> frame_code(frame->LookupCode());
2322 ASSERT(frame_code.is_identical_to(code));
2331 bool at_js_return =
false;
2332 bool break_at_js_return_active =
false;
2333 bool at_debug_break_slot =
false;
2334 RelocIterator it(debug_info->code());
2335 while (!it.done() && !at_js_return && !at_debug_break_slot) {
2336 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2337 at_js_return = (it.rinfo()->pc() ==
2339 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
2341 if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2342 at_debug_break_slot = (it.rinfo()->pc() ==
2354 if (break_at_js_return_active) {
2355 addr += original_code->instruction_start() - code->instruction_start();
2359 thread_local_.after_break_target_ =
2361 }
else if (at_debug_break_slot) {
2374 addr += original_code->instruction_start() - code->instruction_start();
2378 thread_local_.after_break_target_ =
2385 thread_local_.after_break_target_ =
2391 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
2392 HandleScope scope(isolate_);
2397 if (!has_break_points_) {
2401 PrepareForBreakPoints();
2405 Handle<SharedFunctionInfo> shared(function->shared());
2406 if (!EnsureDebugInfo(shared,
function)) {
2410 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2411 Handle<Code>
code(debug_info->code());
2414 Handle<Code> frame_code(frame->LookupCode());
2415 ASSERT(frame_code.is_identical_to(code));
2422 RelocIterator it(debug_info->code());
2423 while (!it.done()) {
2424 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2425 return (it.rinfo()->pc() ==
2434 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
2436 Object** restarter_frame_function_pointer) {
2437 if (mode != CURRENTLY_SET_MODE) {
2438 thread_local_.frame_drop_mode_ =
mode;
2440 thread_local_.break_frame_id_ = new_break_frame_id;
2441 thread_local_.restarter_frame_function_pointer_ =
2442 restarter_frame_function_pointer;
2446 const int Debug::FramePaddingLayout::kInitialSize = 1;
2450 const int Debug::FramePaddingLayout::kPaddingValue = kInitialSize + 1;
2453 bool Debug::IsDebugGlobal(GlobalObject* global) {
2454 return IsLoaded() && global == debug_context()->global_object();
2458 void Debug::ClearMirrorCache() {
2459 PostponeInterruptsScope postpone(isolate_);
2460 HandleScope scope(isolate_);
2461 ASSERT(isolate_->context() == *Debug::debug_context());
2464 Handle<String> function_name = isolate_->factory()->InternalizeOneByteString(
2467 isolate_->global_object()->GetPropertyNoExceptionThrown(*function_name),
2469 ASSERT(fun->IsJSFunction());
2470 bool caught_exception;
2472 Handle<JSObject>(Debug::debug_context()->global_object()),
2473 0,
NULL, &caught_exception);
2477 void Debug::CreateScriptCache() {
2478 Heap* heap = isolate_->heap();
2479 HandleScope scope(isolate_);
2487 "Debug::CreateScriptCache");
2490 script_cache_ =
new ScriptCache(isolate_);
2494 HeapIterator iterator(heap);
2497 for (HeapObject* obj = iterator.next(); obj !=
NULL; obj = iterator.next()) {
2506 void Debug::DestroyScriptCache() {
2508 if (script_cache_ !=
NULL) {
2509 delete script_cache_;
2510 script_cache_ =
NULL;
2515 void Debug::AddScriptToScriptCache(Handle<Script> script) {
2516 if (script_cache_ !=
NULL) {
2517 script_cache_->Add(script);
2522 Handle<FixedArray> Debug::GetLoadedScripts() {
2525 if (script_cache_ ==
NULL) {
2526 CreateScriptCache();
2531 if (script_cache_ ==
NULL) {
2532 isolate_->factory()->NewFixedArray(0);
2538 "Debug::GetLoadedScripts");
2541 return script_cache_->GetScripts();
2545 void Debug::RecordEvalCaller(Handle<Script> script) {
2549 StackTraceFrameIterator it(script->GetIsolate());
2551 script->set_eval_from_shared(it.frame()->function()->shared());
2552 Code* code = it.frame()->LookupCode();
2553 int offset =
static_cast<int>(
2554 it.frame()->pc() - code->instruction_start());
2555 script->set_eval_from_instructions_offset(
Smi::FromInt(offset));
2560 void Debug::AfterGarbageCollection() {
2562 if (script_cache_ !=
NULL) {
2563 script_cache_->ProcessCollectedScripts();
2568 Debugger::Debugger(Isolate* isolate)
2569 : debugger_access_(isolate->debugger_access()),
2570 event_listener_(Handle<
Object>()),
2571 event_listener_data_(Handle<
Object>()),
2572 compiling_natives_(
false),
2573 is_loading_debugger_(
false),
2574 live_edit_enabled_(
true),
2575 never_unload_debugger_(
false),
2576 force_debugger_active_(
false),
2577 message_handler_(
NULL),
2578 debugger_unload_pending_(
false),
2579 host_dispatch_handler_(
NULL),
2580 debug_message_dispatch_handler_(
NULL),
2581 message_dispatch_helper_thread_(
NULL),
2582 host_dispatch_period_(TimeDelta::FromMilliseconds(100)),
2584 command_queue_(isolate->logger(), kQueueInitialSize),
2585 command_received_(0),
2586 event_command_queue_(isolate->logger(), kQueueInitialSize),
2591 Debugger::~Debugger() {}
2594 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
2596 Handle<Object> argv[],
2597 bool* caught_exception) {
2598 ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2601 Handle<String> constructor_str =
2602 isolate_->factory()->InternalizeUtf8String(constructor_name);
2603 ASSERT(!constructor_str.is_null());
2604 Handle<Object> constructor(
2605 isolate_->global_object()->GetPropertyNoExceptionThrown(*constructor_str),
2607 ASSERT(constructor->IsJSFunction());
2608 if (!constructor->IsJSFunction()) {
2609 *caught_exception =
true;
2610 return isolate_->factory()->undefined_value();
2613 Handle<JSFunction>::cast(constructor),
2614 Handle<JSObject>(isolate_->debug()->debug_context()->global_object()),
2622 Handle<Object> Debugger::MakeExecutionState(
bool* caught_exception) {
2624 Handle<Object> break_id = isolate_->factory()->NewNumberFromInt(
2625 isolate_->debug()->break_id());
2626 Handle<Object> argv[] = { break_id };
2627 return MakeJSObject(
CStrVector(
"MakeExecutionState"),
2634 Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
2635 Handle<Object> break_points_hit,
2636 bool* caught_exception) {
2638 Handle<Object> argv[] = { exec_state, break_points_hit };
2639 return MakeJSObject(
CStrVector(
"MakeBreakEvent"),
2646 Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
2647 Handle<Object> exception,
2649 bool* caught_exception) {
2650 Factory* factory = isolate_->factory();
2652 Handle<Object> argv[] = { exec_state,
2654 factory->ToBoolean(uncaught) };
2655 return MakeJSObject(
CStrVector(
"MakeExceptionEvent"),
2662 Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object>
function,
2663 bool* caught_exception) {
2665 Handle<Object> argv[] = {
function };
2666 return MakeJSObject(
CStrVector(
"MakeNewFunctionEvent"),
2673 Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
2675 bool* caught_exception) {
2676 Factory* factory = isolate_->factory();
2678 Handle<Object> exec_state = MakeExecutionState(caught_exception);
2680 Handle<Object> argv[] = { exec_state,
2682 factory->ToBoolean(before) };
2683 return MakeJSObject(
CStrVector(
"MakeCompileEvent"),
2690 Handle<Object> Debugger::MakeScriptCollectedEvent(
int id,
2691 bool* caught_exception) {
2693 Handle<Object> exec_state = MakeExecutionState(caught_exception);
2694 Handle<Object> id_object = Handle<Smi>(
Smi::FromInt(
id), isolate_);
2695 Handle<Object> argv[] = { exec_state, id_object };
2697 return MakeJSObject(
CStrVector(
"MakeScriptCollectedEvent"),
2704 void Debugger::OnException(Handle<Object> exception,
bool uncaught) {
2705 HandleScope scope(isolate_);
2706 Debug* debug = isolate_->debug();
2709 if (debug->InDebugger())
return;
2715 if (!(debug->break_on_uncaught_exception() ||
2716 debug->break_on_exception()))
return;
2719 if (!debug->break_on_exception())
return;
2723 EnterDebugger debugger(isolate_);
2724 if (debugger.FailedToEnter())
return;
2727 debug->ClearStepping();
2729 bool caught_exception =
false;
2730 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2731 Handle<Object> event_data;
2732 if (!caught_exception) {
2733 event_data = MakeExceptionEvent(exec_state, exception, uncaught,
2737 if (caught_exception) {
2742 ProcessDebugEvent(
v8::Exception, Handle<JSObject>::cast(event_data),
false);
2747 void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
2748 bool auto_continue) {
2749 HandleScope scope(isolate_);
2752 ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2755 if (!Debugger::EventActive(
v8::Break))
return;
2758 ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2761 bool caught_exception =
false;
2762 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2763 Handle<Object> event_data;
2764 if (!caught_exception) {
2765 event_data = MakeBreakEvent(exec_state, break_points_hit,
2769 if (caught_exception) {
2775 Handle<JSObject>::cast(event_data),
2780 void Debugger::OnBeforeCompile(Handle<Script> script) {
2781 HandleScope scope(isolate_);
2784 if (isolate_->debug()->InDebugger())
return;
2785 if (compiling_natives())
return;
2789 EnterDebugger debugger(isolate_);
2790 if (debugger.FailedToEnter())
return;
2793 bool caught_exception =
false;
2794 Handle<Object> event_data = MakeCompileEvent(script,
true, &caught_exception);
2796 if (caught_exception) {
2802 Handle<JSObject>::cast(event_data),
2808 void Debugger::OnAfterCompile(Handle<Script> script,
2809 AfterCompileFlags after_compile_flags) {
2810 HandleScope scope(isolate_);
2811 Debug* debug = isolate_->debug();
2814 debug->AddScriptToScriptCache(script);
2817 if (!IsDebuggerActive())
return;
2820 if (compiling_natives())
return;
2823 bool in_debugger = debug->InDebugger();
2826 EnterDebugger debugger(isolate_);
2827 if (debugger.FailedToEnter())
return;
2833 Handle<String> update_script_break_points_string =
2834 isolate_->factory()->InternalizeOneByteString(
2836 Handle<Object> update_script_break_points =
2838 debug->debug_context()->global_object()->GetPropertyNoExceptionThrown(
2839 *update_script_break_points_string),
2841 if (!update_script_break_points->IsJSFunction()) {
2844 ASSERT(update_script_break_points->IsJSFunction());
2851 bool caught_exception;
2852 Handle<Object> argv[] = { wrapper };
2854 isolate_->js_builtins_object(),
2858 if (caught_exception) {
2862 if (in_debugger && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0)
return;
2866 Handle<Object> event_data = MakeCompileEvent(script,
2870 if (caught_exception) {
2875 Handle<JSObject>::cast(event_data),
2880 void Debugger::OnScriptCollected(
int id) {
2881 HandleScope scope(isolate_);
2884 if (isolate_->debug()->InDebugger())
return;
2885 if (!IsDebuggerActive())
return;
2889 EnterDebugger debugger(isolate_);
2890 if (debugger.FailedToEnter())
return;
2893 bool caught_exception =
false;
2894 Handle<Object> event_data = MakeScriptCollectedEvent(
id,
2897 if (caught_exception) {
2903 Handle<JSObject>::cast(event_data),
2909 Handle<JSObject> event_data,
2910 bool auto_continue) {
2911 HandleScope scope(isolate_);
2914 if (!auto_continue) {
2915 isolate_->debug()->clear_interrupt_pending(
DEBUGBREAK);
2919 bool caught_exception =
false;
2920 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2921 if (caught_exception) {
2925 if (message_handler_ !=
NULL) {
2926 NotifyMessageHandler(event,
2927 Handle<JSObject>::cast(exec_state),
2934 if ((event !=
v8::Break || !auto_continue) && !event_listener_.is_null()) {
2935 CallEventCallback(event, exec_state, event_data,
NULL);
2939 while (!event_command_queue_.IsEmpty()) {
2940 CommandMessage command = event_command_queue_.Get();
2941 if (!event_listener_.is_null()) {
2945 command.client_data());
2954 Handle<Object> exec_state,
2955 Handle<Object> event_data,
2957 if (event_listener_->IsForeign()) {
2958 CallCEventCallback(event, exec_state, event_data, client_data);
2960 CallJSEventCallback(event, exec_state, event_data);
2966 Handle<Object> exec_state,
2967 Handle<Object> event_data,
2969 Handle<Foreign> callback_obj(Handle<Foreign>::cast(event_listener_));
2971 FUNCTION_CAST<v8::Debug::EventCallback2>(
2972 callback_obj->foreign_address());
2973 EventDetailsImpl event_details(
2975 Handle<JSObject>::cast(exec_state),
2976 Handle<JSObject>::cast(event_data),
2977 event_listener_data_,
2979 callback(event_details);
2984 Handle<Object> exec_state,
2985 Handle<Object> event_data) {
2986 ASSERT(event_listener_->IsJSFunction());
2987 Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
2990 Handle<Object> argv[] = { Handle<Object>(
Smi::FromInt(event), isolate_),
2993 event_listener_data_ };
2994 bool caught_exception;
2996 isolate_->global_object(),
3004 Handle<Context> Debugger::GetDebugContext() {
3005 never_unload_debugger_ =
true;
3006 EnterDebugger debugger(isolate_);
3007 return isolate_->debug()->debug_context();
3011 void Debugger::UnloadDebugger() {
3012 Debug* debug = isolate_->debug();
3015 debug->ClearAllBreakPoints();
3018 if (!never_unload_debugger_) {
3023 debugger_unload_pending_ =
false;
3028 Handle<JSObject> exec_state,
3029 Handle<JSObject> event_data,
3030 bool auto_continue) {
3032 HandleScope scope(isolate_);
3034 if (!isolate_->debug()->Load())
return;
3037 bool sendEventMessage =
false;
3041 sendEventMessage = !auto_continue;
3044 sendEventMessage =
true;
3049 sendEventMessage =
true;
3052 sendEventMessage =
true;
3063 ASSERT(isolate_->debug()->InDebugger());
3068 if (sendEventMessage) {
3069 MessageImpl message = MessageImpl::NewEvent(
3072 Handle<JSObject>::cast(exec_state),
3073 Handle<JSObject>::cast(event_data));
3074 InvokeMessageHandler(message);
3093 isolate,
"debugCommandProcessor");
3098 static const int kArgc = 1;
3101 fun->
Call(api_exec_state, kArgc, argv));
3108 bool running = auto_continue;
3113 if (Debugger::host_dispatch_handler_) {
3115 if (!command_received_.WaitFor(host_dispatch_period_)) {
3117 Debugger::host_dispatch_handler_();
3122 command_received_.Wait();
3126 CommandMessage command = command_queue_.Get();
3127 isolate_->logger()->DebugTag(
3128 "Got request from command queue, in interactive loop.");
3129 if (!Debugger::IsDebuggerActive()) {
3145 command.text().length());
3146 static const int kArgc = 1;
3154 if (!response_val->IsUndefined()) {
3161 if (FLAG_trace_debug_json) {
3169 static const int kArgc = 1;
3173 running = running_val->ToBoolean()->Value();
3177 response = try_catch.
Exception()->ToString();
3181 MessageImpl message = MessageImpl::NewResponse(
3184 Handle<JSObject>::cast(exec_state),
3185 Handle<JSObject>::cast(event_data),
3187 command.client_data());
3188 InvokeMessageHandler(message);
3194 if (running && !HasCommands()) {
3201 void Debugger::SetEventListener(Handle<Object> callback,
3202 Handle<Object> data) {
3203 HandleScope scope(isolate_);
3204 GlobalHandles* global_handles = isolate_->global_handles();
3208 if (!event_listener_.is_null()) {
3210 reinterpret_cast<Object**>(event_listener_.location()));
3211 event_listener_ = Handle<Object>();
3213 if (!event_listener_data_.is_null()) {
3215 reinterpret_cast<Object**>(event_listener_data_.location()));
3216 event_listener_data_ = Handle<Object>();
3221 if (!callback->IsUndefined() && !callback->IsNull()) {
3223 global_handles->Create(*callback));
3224 if (data.is_null()) {
3225 data = isolate_->factory()->undefined_value();
3228 global_handles->Create(*data));
3236 LockGuard<RecursiveMutex> with(debugger_access_);
3238 message_handler_ = handler;
3240 if (handler ==
NULL) {
3243 if (isolate_->debug()->InDebugger()) {
3244 ProcessCommand(Vector<const uint16_t>::empty());
3250 void Debugger::ListenersChanged() {
3251 if (IsDebuggerActive()) {
3253 isolate_->compilation_cache()->Disable();
3254 debugger_unload_pending_ =
false;
3256 isolate_->compilation_cache()->Enable();
3259 debugger_unload_pending_ =
true;
3266 host_dispatch_handler_ = handler;
3267 host_dispatch_period_ = period;
3271 void Debugger::SetDebugMessageDispatchHandler(
3273 LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3274 debug_message_dispatch_handler_ = handler;
3276 if (provide_locker && message_dispatch_helper_thread_ ==
NULL) {
3277 message_dispatch_helper_thread_ =
new MessageDispatchHelperThread(isolate_);
3278 message_dispatch_helper_thread_->Start();
3285 void Debugger::InvokeMessageHandler(MessageImpl message) {
3286 LockGuard<RecursiveMutex> with(debugger_access_);
3288 if (message_handler_ !=
NULL) {
3289 message_handler_(message);
3298 void Debugger::ProcessCommand(Vector<const uint16_t> command,
3301 CommandMessage message = CommandMessage::New(
3302 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
3305 isolate_->logger()->DebugTag(
"Put command on command_queue.");
3306 command_queue_.Put(message);
3307 command_received_.Signal();
3310 if (!isolate_->debug()->InDebugger()) {
3311 isolate_->stack_guard()->DebugCommand();
3314 MessageDispatchHelperThread* dispatch_thread;
3316 LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3317 dispatch_thread = message_dispatch_helper_thread_;
3320 if (dispatch_thread ==
NULL) {
3321 CallMessageDispatchHandler();
3323 dispatch_thread->Schedule();
3328 bool Debugger::HasCommands() {
3329 return !command_queue_.IsEmpty();
3334 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
3335 event_command_queue_.Put(message);
3338 if (!isolate_->debug()->InDebugger()) {
3339 isolate_->stack_guard()->DebugCommand();
3344 bool Debugger::IsDebuggerActive() {
3345 LockGuard<RecursiveMutex> with(debugger_access_);
3347 return message_handler_ !=
NULL ||
3348 !event_listener_.is_null() ||
3349 force_debugger_active_;
3353 Handle<Object> Debugger::Call(Handle<JSFunction> fun,
3354 Handle<Object> data,
3355 bool* pending_exception) {
3357 Debugger::never_unload_debugger_ =
true;
3360 EnterDebugger debugger(isolate_);
3361 if (debugger.FailedToEnter()) {
3362 return isolate_->factory()->undefined_value();
3366 bool caught_exception =
false;
3367 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
3368 if (caught_exception) {
3369 return isolate_->factory()->undefined_value();
3372 Handle<Object> argv[] = { exec_state, data };
3376 Handle<Object>(isolate_->debug()->debug_context_->global_proxy(),
3390 bool Debugger::StartAgent(
const char* name,
int port,
3391 bool wait_for_connection) {
3392 if (wait_for_connection) {
3399 Debugger::message_handler_ = StubMessageHandler2;
3403 if (agent_ ==
NULL) {
3404 agent_ =
new DebuggerAgent(isolate_, name, port);
3411 void Debugger::StopAgent() {
3412 if (agent_ !=
NULL) {
3421 void Debugger::WaitForAgent() {
3423 agent_->WaitUntilListening();
3427 void Debugger::CallMessageDispatchHandler() {
3430 LockGuard<Mutex> lock_guard(&dispatch_handler_access_);
3431 handler = Debugger::debug_message_dispatch_handler_;
3433 if (handler !=
NULL) {
3439 EnterDebugger::EnterDebugger(Isolate* isolate)
3440 : isolate_(isolate),
3441 prev_(isolate_->debug()->debugger_entry()),
3443 has_js_frames_(!it_.done()),
3445 Debug* debug = isolate_->debug();
3450 debug->set_debugger_entry(
this);
3453 break_id_ = debug->break_id();
3454 break_frame_id_ = debug->break_frame_id();
3458 if (has_js_frames_) {
3459 debug->NewBreak(it_.frame()->id());
3461 debug->NewBreak(StackFrame::NO_ID);
3465 load_failed_ = !debug->Load();
3466 if (!load_failed_) {
3469 isolate_->set_context(*debug->debug_context());
3474 EnterDebugger::~EnterDebugger() {
3475 Debug* debug = isolate_->debug();
3478 debug->SetBreak(break_frame_id_, break_id_);
3481 if (!load_failed_ && prev_ ==
NULL) {
3486 if (!isolate_->has_pending_exception()) {
3489 if (isolate_->stack_guard()->IsDebugBreak()) {
3491 isolate_->stack_guard()->Continue(
DEBUGBREAK);
3493 debug->ClearMirrorCache();
3498 if (debug->is_interrupt_pending(
PREEMPT)) {
3501 debug->clear_interrupt_pending(
PREEMPT);
3502 isolate_->stack_guard()->Preempt();
3504 if (debug->is_interrupt_pending(
DEBUGBREAK)) {
3506 isolate_->stack_guard()->DebugBreak();
3511 if (isolate_->debugger()->HasCommands()) {
3512 isolate_->stack_guard()->DebugCommand();
3516 if (!isolate_->debugger()->IsDebuggerActive()) {
3517 isolate_->debugger()->UnloadDebugger();
3522 debug->set_debugger_entry(prev_);
3526 MessageImpl MessageImpl::NewEvent(
DebugEvent event,
3528 Handle<JSObject> exec_state,
3529 Handle<JSObject> event_data) {
3530 MessageImpl
message(
true, event, running,
3531 exec_state, event_data, Handle<String>(),
NULL);
3536 MessageImpl MessageImpl::NewResponse(
DebugEvent event,
3538 Handle<JSObject> exec_state,
3539 Handle<JSObject> event_data,
3540 Handle<String> response_json,
3542 MessageImpl
message(
false, event, running,
3543 exec_state, event_data, response_json, client_data);
3548 MessageImpl::MessageImpl(
bool is_event,
3551 Handle<JSObject> exec_state,
3552 Handle<JSObject> event_data,
3553 Handle<String> response_json,
3555 : is_event_(is_event),
3558 exec_state_(exec_state),
3559 event_data_(event_data),
3560 response_json_(response_json),
3561 client_data_(client_data) {}
3564 bool MessageImpl::IsEvent()
const {
3569 bool MessageImpl::IsResponse()
const {
3579 bool MessageImpl::WillStartRunning()
const {
3590 return reinterpret_cast<v8::Isolate*
>(exec_state_->GetIsolate());
3601 reinterpret_cast<v8::Isolate*>(event_data_->GetIsolate()));
3605 Handle<Object> fun =
GetProperty(event_data_,
"toJSONProtocol");
3606 if (!fun->IsJSFunction()) {
3609 bool caught_exception;
3612 0,
NULL, &caught_exception);
3613 if (caught_exception || !json->IsString()) {
3624 Isolate* isolate = event_data_->
GetIsolate();
3633 return client_data_;
3637 EventDetailsImpl::EventDetailsImpl(
DebugEvent event,
3638 Handle<JSObject> exec_state,
3639 Handle<JSObject> event_data,
3640 Handle<Object> callback_data,
3643 exec_state_(exec_state),
3644 event_data_(event_data),
3645 callback_data_(callback_data),
3646 client_data_(client_data) {}
3649 DebugEvent EventDetailsImpl::GetEvent()
const {
3665 return GetDebugEventContext(exec_state_->GetIsolate());
3675 return client_data_;
3679 CommandMessage::CommandMessage() : text_(Vector<
uint16_t>::empty()),
3680 client_data_(
NULL) {
3684 CommandMessage::CommandMessage(
const Vector<uint16_t>& text,
3687 client_data_(data) {
3691 CommandMessage::~CommandMessage() {
3695 void CommandMessage::Dispose() {
3697 delete client_data_;
3698 client_data_ =
NULL;
3702 CommandMessage CommandMessage::New(
const Vector<uint16_t>& command,
3704 return CommandMessage(command.Clone(), data);
3708 CommandMessageQueue::CommandMessageQueue(
int size) : start_(0),
end_(0),
3710 messages_ = NewArray<CommandMessage>(
size);
3714 CommandMessageQueue::~CommandMessageQueue() {
3715 while (!IsEmpty()) {
3716 CommandMessage m = Get();
3723 CommandMessage CommandMessageQueue::Get() {
3725 int result = start_;
3726 start_ = (start_ + 1) % size_;
3727 return messages_[result];
3731 void CommandMessageQueue::Put(
const CommandMessage& message) {
3732 if ((
end_ + 1) % size_ == start_) {
3740 void CommandMessageQueue::Expand() {
3741 CommandMessageQueue new_queue(size_ * 2);
3742 while (!IsEmpty()) {
3743 new_queue.Put(Get());
3745 CommandMessage* array_to_free = messages_;
3747 new_queue.messages_ = array_to_free;
3749 new_queue.start_ = new_queue.end_;
3754 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger,
int size)
3755 : logger_(logger), queue_(size) {}
3758 bool LockingCommandMessageQueue::IsEmpty()
const {
3759 LockGuard<Mutex> lock_guard(&mutex_);
3760 return queue_.IsEmpty();
3764 CommandMessage LockingCommandMessageQueue::Get() {
3765 LockGuard<Mutex> lock_guard(&mutex_);
3766 CommandMessage result = queue_.Get();
3767 logger_->DebugEvent(
"Get", result.text());
3772 void LockingCommandMessageQueue::Put(
const CommandMessage& message) {
3773 LockGuard<Mutex> lock_guard(&mutex_);
3774 queue_.Put(message);
3775 logger_->DebugEvent(
"Put", message.text());
3779 void LockingCommandMessageQueue::Clear() {
3780 LockGuard<Mutex> lock_guard(&mutex_);
3785 MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
3786 : Thread(
"v8:MsgDispHelpr"),
3787 isolate_(isolate), sem_(0),
3788 already_signalled_(
false) {
3792 void MessageDispatchHelperThread::Schedule() {
3794 LockGuard<Mutex> lock_guard(&mutex_);
3795 if (already_signalled_) {
3798 already_signalled_ =
true;
3804 void MessageDispatchHelperThread::Run() {
3808 LockGuard<Mutex> lock_guard(&mutex_);
3809 already_signalled_ =
false;
3812 Locker locker(reinterpret_cast<v8::Isolate*>(isolate_));
3813 isolate_->debugger()->CallMessageDispatchHandler();
3818 #endif // ENABLE_DEBUGGER_SUPPORT
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter NULL
static void Destroy(Object **location)
Code * builtin(Name name)
static Object *& Object_at(Address addr)
Local< Value > Call(Handle< Value > recv, int argc, Handle< Value > argv[])
static Handle< Object > TryCall(Handle< JSFunction > func, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *caught_exception)
static Handle< SharedFunctionInfo > CompileScript(Handle< String > source, Handle< Object > script_name, int line_offset, int column_offset, bool is_shared_cross_origin, Handle< Context > context, v8::Extension *extension, ScriptDataImpl **cached_data, CachedDataMode cached_data_mode, NativesFlag is_natives_code)
static Handle< Code > GetCodeForDebugging(Handle< JSFunction > function)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths true
void PrintF(const char *format,...)
Local< Value > Exception() const
Local< Value > Get(Handle< Value > key)
static Smi * FromInt(int value)
static Handle< Code > GetUnoptimizedCode(Handle< JSFunction > function)
static int GetIndex(const char *name)
static int ExtractArgcFromMinorKey(int minor_key)
static Handle< T > cast(Handle< S > that)
static const int kPatchDebugBreakSlotReturnOffset
static Vector< const char > GetScriptName(int index)
kSerializedDataOffset Object
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in only print modified registers Don t break for ASM_UNIMPLEMENTED_BREAK macros print stack trace when an illegal exception is thrown randomize hashes to avoid predictable hash Fixed seed to use to hash property Print the time it takes to deserialize the snapshot testing_bool_flag testing_int_flag string flag tmp file in which to serialize heap Print the time it takes to lazily compile hydrogen code stubs concurrent_recompilation concurrent_sweeping Print usage message
static Address target_address_at(Address pc, ConstantPoolArray *constant_pool)
V8_INLINE Local< T > GetValue() const
void(* DebugMessageDispatchHandler)()
static bool EnsureCompiled(Handle< JSFunction > function, ClearExceptionFlag flag)
#define ASSERT(condition)
static const int kPatchReturnSequenceAddressOffset
static const int kContextOffset
static Script * cast(Object *obj)
void(* MessageHandler2)(const Message &message)
static SharedFunctionInfo * cast(Object *obj)
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value)
static Smi * cast(Object *object)
v8::Isolate * GetIsolate()
static Handle< JSMessageObject > MakeMessageObject(Isolate *isolate, const char *type, MessageLocation *loc, Vector< Handle< Object > > args, Handle< JSArray > stack_frames)
HANDLE HANDLE LPSTACKFRAME64 StackFrame
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long mode(MIPS only)") DEFINE_string(expose_natives_as
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object size
V8_INLINE Isolate * GetIsolate() const
static void MemCopy(void *dest, const void *src, size_t size)
static const int kNoGCFlags
Handle< JSValue > GetScriptWrapper(Handle< Script > script)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
Entry * Lookup(void *key, uint32_t hash, bool insert, FreeStoreAllocationPolicyallocator=FreeStoreAllocationPolicy())
static void * ClearWeakness(Object **location)
static void DeoptimizeAll(Isolate *isolate)
static Code * GetCodeFromTargetAddress(Address address)
static const int kMarkerOffset
static const int kMakeHeapIterableMask
static Local< String > NewFromTwoByte(Isolate *isolate, const uint16_t *data, NewStringType type=kNormalString, int length=-1)
#define STATIC_ASCII_VECTOR(x)
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
static V8_INLINE Local< T > Cast(Local< S > that)
Vector< const char > CStrVector(const char *data)
static const int kDebugBreakSlotLength
V8_INLINE P * GetParameter() const
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
void(* EventCallback2)(const EventDetails &event_details)
void Load(const v8::FunctionCallbackInfo< v8::Value > &args)
void(* HostDispatchHandler)()
static Handle< Object > Call(Isolate *isolate, Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< Name > key, Handle< Object > value, PropertyAttributes attributes, StrictMode strict_mode, StoreFromKeyed store_mode=MAY_BE_STORE_FROM_KEYED)
V8_INLINE bool IsEmpty() const
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function info
static const int kFunctionOffset
Object * JSCallerSavedBuffer[kNumJSCallerSaved]
static void MakeWeak(Object **location, void *parameter, WeakCallback weak_callback)
static Handle< T > null()
PerThreadAssertScopeDebugOnly< HEAP_ALLOCATION_ASSERT, false > DisallowHeapAllocation
static FixedArray * cast(Object *obj)
static const int kBoundFunctionIndex
static const int kCodeOffset
static void DebugBreak(Isolate *isolate=NULL)
static void ReportMessage(Isolate *isolate, MessageLocation *loc, Handle< Object > message)
void DeleteArray(T *array)
enable upcoming ES6 features enable harmony block scoping enable harmony enable harmony proxies enable harmony generators enable harmony numeric enable harmony string enable harmony math functions harmony_scoping harmony_symbols harmony_collections harmony_iteration harmony_strings harmony_scoping harmony_maths tracks arrays with only smi values Optimize object Array DOM strings and string pretenure call new trace pretenuring decisions of HAllocate instructions track fields with only smi values track fields with heap values track_fields track_fields Enables optimizations which favor memory size over execution speed use string slices optimization filter maximum number of GVN fix point iterations use function inlining use allocation folding eliminate write barriers targeting allocations in optimized code maximum source size in bytes considered for a single inlining maximum cumulative number of AST nodes considered for inlining crankshaft harvests type feedback from stub cache trace check elimination phase hydrogen tracing filter trace hydrogen to given file name trace inlining decisions trace store elimination trace all use positions trace global value numbering trace hydrogen escape analysis trace the tracking of allocation sites trace map generalization environment for every instruction deoptimize every n garbage collections put a break point before deoptimizing deoptimize uncommon cases use on stack replacement trace array bounds check elimination perform array index dehoisting use load elimination use store elimination use constant folding eliminate unreachable code number of stress runs when picking a function to watch for shared function not JSFunction itself flushes the cache of optimized code for closures on every GC functions with arguments object maximum number of escape analysis fix point iterations allow uint32 values on optimize frames if they are used only in safe operations track concurrent recompilation artificial compilation delay in ms concurrent on stack replacement do not emit check maps for constant values that have a leaf deoptimize the optimized code if the layout of the maps changes number of stack frames inspected by the profiler percentage of ICs that must have type info to allow optimization extra verbose compilation tracing generate extra emit comments in code disassembly enable use of SSE3 instructions if available enable use of CMOV instruction if available enable use of VFP3 instructions if available enable use of NEON instructions if enable use of SDIV and UDIV instructions if enable loading bit constant by means of movw movt instruction enable unaligned accesses for enable use of d16 d31 registers on ARM this requires VFP3 force all emitted branches to be in long expose natives in global object expose freeBuffer extension expose gc extension under the specified name expose externalize string extension number of stack frames to capture disable builtin natives files print name of functions for which code is generated use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations always try to OSR functions trace optimize function deoptimization minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions trace debugging JSON request response trace out of bounds accesses to external arrays trace_js_array_abuse automatically set the debug break flag when debugger commands are in the queue abort by crashing maximum length of function source code printed in a stack trace max size of the new max size of the old max size of executable always perform global GCs print one trace line following each garbage collection do not print trace line after scavenger collection print statistics of the maximum memory committed for the heap in name
static const int kPatchDebugBreakSlotAddressOffset
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
static V8_INLINE Handle< Boolean > New(Isolate *isolate, bool value)
static Local< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=kNormalString, int length=-1)
static JSFunction * cast(Object *obj)