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->
Length() + 1);
80 if (data.start() ==
NULL) {
85 PrintF(
"%s\n", data.start());
89 static Handle<Code> ComputeCallDebugPrepareStepIn(
int argc,
Code::Kind kind) {
90 Isolate* isolate = Isolate::Current();
91 return isolate->stub_cache()->ComputeCallDebugPrepareStepIn(argc, kind);
96 Handle<Context> context = isolate->debug()->debugger_entry()->GetContext();
100 Handle<Context> native_context(context->native_context());
105 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
106 BreakLocatorType type) {
107 debug_info_ = debug_info;
109 reloc_iterator_ =
NULL;
110 reloc_iterator_original_ =
NULL;
115 BreakLocationIterator::~BreakLocationIterator() {
118 delete reloc_iterator_;
119 delete reloc_iterator_original_;
123 void BreakLocationIterator::Next() {
124 AssertNoAllocation nogc;
129 bool first = break_point_ == -1;
130 while (!RinfoDone()) {
131 if (!first) RinfoNext();
133 if (RinfoDone())
return;
137 if (RelocInfo::IsPosition(rmode())) {
138 if (RelocInfo::IsStatementPosition(rmode())) {
139 statement_position_ =
static_cast<int>(
140 rinfo()->data() - debug_info_->shared()->start_position());
144 position_ =
static_cast<int>(
145 rinfo()->data() - debug_info_->shared()->start_position());
147 ASSERT(statement_position_ >= 0);
150 if (IsDebugBreakSlot()) {
154 }
else if (RelocInfo::IsCodeTarget(rmode())) {
158 Address target = original_rinfo()->target_address();
160 if ((code->is_inline_cache_stub() &&
161 !code->is_binary_op_stub() &&
162 !code->is_unary_op_stub() &&
163 !code->is_compare_ic_stub() &&
164 !code->is_to_boolean_ic_stub()) ||
165 RelocInfo::IsConstructCall(rmode())) {
169 if (code->kind() == Code::STUB) {
170 if (IsDebuggerStatement()) {
174 if (type_ == ALL_BREAK_LOCATIONS) {
175 if (Debug::IsBreakStub(code)) {
180 ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
181 if (Debug::IsSourceBreakStub(code)) {
190 if (RelocInfo::IsJSReturn(rmode())) {
192 if (debug_info_->shared()->HasSourceCode()) {
193 position_ = debug_info_->shared()->end_position() -
194 debug_info_->shared()->start_position() - 1;
198 statement_position_ = position_;
206 void BreakLocationIterator::Next(
int count) {
215 void BreakLocationIterator::FindBreakLocationFromAddress(
Address pc) {
217 int closest_break_point = 0;
221 if (this->
pc() < pc && pc - this->
pc() < distance) {
222 closest_break_point = break_point();
223 distance =
static_cast<int>(pc - this->
pc());
225 if (distance == 0)
break;
232 Next(closest_break_point);
237 void BreakLocationIterator::FindBreakLocationFromPosition(
int position) {
240 int closest_break_point = 0;
244 if (position <= statement_position() &&
245 statement_position() - position < distance) {
246 closest_break_point = break_point();
247 distance = statement_position() - position;
249 if (distance == 0)
break;
256 Next(closest_break_point);
260 void BreakLocationIterator::Reset() {
262 if (reloc_iterator_ !=
NULL)
delete reloc_iterator_;
263 if (reloc_iterator_original_ !=
NULL)
delete reloc_iterator_original_;
264 reloc_iterator_ =
new RelocIterator(debug_info_->code());
265 reloc_iterator_original_ =
new RelocIterator(debug_info_->original_code());
270 statement_position_ = 1;
275 bool BreakLocationIterator::Done()
const {
280 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
283 if (!HasBreakPoint()) {
286 ASSERT(IsDebugBreak() || IsDebuggerStatement());
288 DebugInfo::SetBreakPoint(debug_info_, code_position(),
289 position(), statement_position(),
294 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
296 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
298 if (!HasBreakPoint()) {
305 void BreakLocationIterator::SetOneShot() {
307 if (IsDebuggerStatement()) {
312 if (HasBreakPoint()) {
322 void BreakLocationIterator::ClearOneShot() {
324 if (IsDebuggerStatement()) {
329 if (HasBreakPoint()) {
340 void BreakLocationIterator::SetDebugBreak() {
342 if (IsDebuggerStatement()) {
350 if (IsDebugBreak()) {
354 if (RelocInfo::IsJSReturn(rmode())) {
356 SetDebugBreakAtReturn();
357 }
else if (IsDebugBreakSlot()) {
359 SetDebugBreakAtSlot();
368 void BreakLocationIterator::ClearDebugBreak() {
370 if (IsDebuggerStatement()) {
374 if (RelocInfo::IsJSReturn(rmode())) {
376 ClearDebugBreakAtReturn();
377 }
else if (IsDebugBreakSlot()) {
379 ClearDebugBreakAtSlot();
382 ClearDebugBreakAtIC();
388 void BreakLocationIterator::PrepareStepIn() {
393 Address target = rinfo()->target_address();
395 if (target_code->is_call_stub() || target_code->is_keyed_call_stub()) {
401 Handle<Code> stub = ComputeCallDebugPrepareStepIn(
402 target_code->arguments_count(), target_code->kind());
403 if (IsDebugBreak()) {
404 original_rinfo()->set_target_address(stub->entry());
406 rinfo()->set_target_address(stub->entry());
412 Handle<Code> maybe_call_function_stub = target_code;
413 if (IsDebugBreak()) {
414 Address original_target = original_rinfo()->target_address();
415 maybe_call_function_stub =
418 bool is_call_function_stub =
419 (maybe_call_function_stub->kind() == Code::STUB &&
420 maybe_call_function_stub->major_key() == CodeStub::CallFunction);
429 ASSERT(RelocInfo::IsConstructCall(rmode()) ||
430 target_code->is_inline_cache_stub() ||
431 is_call_function_stub);
438 bool BreakLocationIterator::IsExit()
const {
439 return (RelocInfo::IsJSReturn(rmode()));
443 bool BreakLocationIterator::HasBreakPoint() {
444 return debug_info_->HasBreakPoint(code_position());
449 bool BreakLocationIterator::IsDebugBreak() {
450 if (RelocInfo::IsJSReturn(rmode())) {
451 return IsDebugBreakAtReturn();
452 }
else if (IsDebugBreakSlot()) {
453 return IsDebugBreakAtSlot();
455 return Debug::IsDebugBreak(rinfo()->target_address());
460 void BreakLocationIterator::SetDebugBreakAtIC() {
463 original_rinfo()->set_target_address(rinfo()->target_address());
465 RelocInfo::Mode mode = rmode();
466 if (RelocInfo::IsCodeTarget(mode)) {
467 Address target = rinfo()->target_address();
472 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(target_code, mode));
473 rinfo()->set_target_address(dbgbrk_code->entry());
478 void BreakLocationIterator::ClearDebugBreakAtIC() {
480 rinfo()->set_target_address(original_rinfo()->target_address());
484 bool BreakLocationIterator::IsDebuggerStatement() {
489 bool BreakLocationIterator::IsDebugBreakSlot() {
490 return RelocInfo::DEBUG_BREAK_SLOT == rmode();
494 Object* BreakLocationIterator::BreakPointObjects() {
495 return debug_info_->GetBreakPointObjects(code_position());
502 void BreakLocationIterator::ClearAllDebugBreak() {
510 bool BreakLocationIterator::RinfoDone()
const {
511 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
512 return reloc_iterator_->done();
516 void BreakLocationIterator::RinfoNext() {
517 reloc_iterator_->next();
518 reloc_iterator_original_->next();
520 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
521 if (!reloc_iterator_->done()) {
522 ASSERT(rmode() == original_rmode());
529 void Debug::ThreadInit() {
530 thread_local_.break_count_ = 0;
531 thread_local_.break_id_ = 0;
532 thread_local_.break_frame_id_ = StackFrame::NO_ID;
533 thread_local_.last_step_action_ = StepNone;
534 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
535 thread_local_.step_count_ = 0;
536 thread_local_.last_fp_ = 0;
537 thread_local_.queued_step_count_ = 0;
538 thread_local_.step_into_fp_ = 0;
539 thread_local_.step_out_fp_ = 0;
540 thread_local_.after_break_target_ = 0;
542 thread_local_.debugger_entry_ =
NULL;
543 thread_local_.pending_interrupts_ = 0;
544 thread_local_.restarter_frame_function_pointer_ =
NULL;
548 char* Debug::ArchiveDebug(
char* storage) {
550 memcpy(to, reinterpret_cast<char*>(&thread_local_),
sizeof(ThreadLocal));
551 to +=
sizeof(ThreadLocal);
552 memcpy(to, reinterpret_cast<char*>(®isters_),
sizeof(registers_));
554 ASSERT(to <= storage + ArchiveSpacePerThread());
555 return storage + ArchiveSpacePerThread();
559 char* Debug::RestoreDebug(
char* storage) {
560 char* from = storage;
561 memcpy(reinterpret_cast<char*>(&thread_local_), from,
sizeof(ThreadLocal));
562 from +=
sizeof(ThreadLocal);
563 memcpy(reinterpret_cast<char*>(®isters_), from,
sizeof(registers_));
564 ASSERT(from <= storage + ArchiveSpacePerThread());
565 return storage + ArchiveSpacePerThread();
569 int Debug::ArchiveSpacePerThread() {
581 ASSERT(bottom_js_frame->is_java_script());
597 const int Debug::kFrameDropperFrameSize = 4;
600 void ScriptCache::Add(Handle<Script> script) {
601 GlobalHandles* global_handles = Isolate::Current()->global_handles();
603 int id =
Smi::cast(script->id())->value();
604 HashMap::Entry* entry =
606 if (entry->value !=
NULL) {
607 ASSERT(*script == *reinterpret_cast<Script**>(entry->value));
613 Handle<Script> script_ =
615 (global_handles->Create(*script)));
616 global_handles->MakeWeak(
617 reinterpret_cast<Object**>(script_.location()),
619 ScriptCache::HandleWeakScript);
620 entry->value = script_.location();
624 Handle<FixedArray> ScriptCache::GetScripts() {
625 Handle<FixedArray> instances =
FACTORY->NewFixedArray(occupancy());
627 for (HashMap::Entry* entry = Start(); entry !=
NULL; entry = Next(entry)) {
629 if (entry->value !=
NULL) {
630 instances->set(count, *reinterpret_cast<Script**>(entry->value));
638 void ScriptCache::ProcessCollectedScripts() {
639 Debugger* debugger = Isolate::Current()->debugger();
640 for (
int i = 0; i < collected_scripts_.length(); i++) {
641 debugger->OnScriptCollected(collected_scripts_[i]);
643 collected_scripts_.Clear();
647 void ScriptCache::Clear() {
648 GlobalHandles* global_handles = Isolate::Current()->global_handles();
650 for (HashMap::Entry* entry = Start(); entry !=
NULL; entry = Next(entry)) {
652 Object** location =
reinterpret_cast<Object**
>(entry->value);
653 ASSERT((*location)->IsScript());
654 global_handles->ClearWeakness(location);
655 global_handles->Destroy(location);
663 ScriptCache* script_cache =
reinterpret_cast<ScriptCache*
>(data);
666 reinterpret_cast<Script**
>(Utils::OpenHandle(*obj).location());
667 ASSERT((*location)->IsScript());
670 int id =
Smi::cast((*location)->id())->value();
671 script_cache->Remove(reinterpret_cast<void*>(
id), Hash(
id));
672 script_cache->collected_scripts_.Add(
id);
680 void Debug::SetUp(
bool create_heap_objects) {
682 if (create_heap_objects) {
684 debug_break_return_ =
685 isolate_->builtins()->builtin(Builtins::kReturn_DebugBreak);
686 ASSERT(debug_break_return_->IsCode());
689 isolate_->builtins()->builtin(Builtins::kSlot_DebugBreak);
690 ASSERT(debug_break_slot_->IsCode());
696 Debug* debug = Isolate::Current()->debug();
697 DebugInfoListNode* node =
reinterpret_cast<DebugInfoListNode*
>(data);
702 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
703 it.ClearAllDebugBreak();
704 debug->RemoveDebugInfo(node->debug_info());
706 node = debug->debug_info_list_;
707 while (node !=
NULL) {
708 ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
715 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(
NULL) {
716 GlobalHandles* global_handles = Isolate::Current()->global_handles();
719 (global_handles->Create(debug_info)));
720 global_handles->MakeWeak(
721 reinterpret_cast<Object**>(debug_info_.location()),
723 Debug::HandleWeakDebugInfo);
727 DebugInfoListNode::~DebugInfoListNode() {
728 Isolate::Current()->global_handles()->Destroy(
729 reinterpret_cast<Object**>(debug_info_.location()));
733 bool Debug::CompileDebuggerScript(
int index) {
734 Isolate* isolate = Isolate::Current();
735 Factory* factory = isolate->factory();
736 HandleScope scope(isolate);
744 Handle<String> source_code =
745 isolate->bootstrapper()->NativesSourceLookup(index);
747 Handle<String> script_name = factory->NewStringFromAscii(name);
748 Handle<Context> context = isolate->native_context();
751 Handle<SharedFunctionInfo> function_info;
761 if (function_info.is_null()) {
762 ASSERT(isolate->has_pending_exception());
763 isolate->clear_pending_exception();
768 bool caught_exception;
769 Handle<JSFunction>
function =
770 factory->NewFunctionFromSharedFunctionInfo(function_info, context);
772 Handle<Object> exception =
774 0,
NULL, &caught_exception);
777 if (caught_exception) {
778 ASSERT(!isolate->has_pending_exception());
779 MessageLocation computed_location;
780 isolate->ComputeLocation(&computed_location);
782 "error_loading_debugger", &computed_location,
783 Vector<Handle<Object> >::empty(), Handle<String>(), Handle<JSArray>());
784 ASSERT(!isolate->has_pending_exception());
785 isolate->set_pending_exception(*exception);
787 isolate->clear_pending_exception();
792 Handle<Script> script(
Script::cast(function->shared()->script()));
800 if (IsLoaded())
return true;
802 Debugger* debugger = isolate_->debugger();
806 if (debugger->compiling_natives() ||
807 debugger->is_loading_debugger())
809 debugger->set_loading_debugger(
true);
813 DisableBreak disable(
true);
814 PostponeInterruptsScope postpone(isolate_);
817 HandleScope scope(isolate_);
818 Handle<Context> context =
819 isolate_->bootstrapper()->CreateEnvironment(
826 if (context.is_null())
return false;
829 SaveContext save(isolate_);
830 isolate_->set_context(*context);
833 Handle<String> key = isolate_->factory()->LookupAsciiSymbol(
"builtins");
834 Handle<GlobalObject> global = Handle<GlobalObject>(context->global_object());
842 debugger->set_compiling_natives(
true);
843 bool caught_exception =
847 if (FLAG_enable_liveedit) {
848 caught_exception = caught_exception ||
852 debugger->set_compiling_natives(
false);
856 debugger->set_loading_debugger(
false);
859 if (caught_exception)
return false;
862 debug_context_ = context;
868 void Debug::Unload() {
875 DestroyScriptCache();
878 Isolate::Current()->global_handles()->Destroy(
879 reinterpret_cast<Object**>(debug_context_.location()));
880 debug_context_ = Handle<Context>();
885 void Debug::PreemptionWhileInDebugger() {
887 Debug::set_interrupts_pending(
PREEMPT);
891 void Debug::Iterate(ObjectVisitor* v) {
892 v->VisitPointer(BitCast<Object**>(&(debug_break_return_)));
893 v->VisitPointer(BitCast<Object**>(&(debug_break_slot_)));
898 Heap* heap = isolate_->heap();
899 HandleScope scope(isolate_);
900 ASSERT(args.length() == 0);
902 thread_local_.frame_drop_mode_ = FRAMES_UNTOUCHED;
906 JavaScriptFrame* frame = it.frame();
909 if (disable_break() || !
Load()) {
910 SetAfterBreakTarget(frame);
911 return heap->undefined_value();
915 EnterDebugger debugger;
916 if (debugger.FailedToEnter()) {
917 return heap->undefined_value();
921 PostponeInterruptsScope postpone(isolate_);
924 Handle<SharedFunctionInfo> shared =
926 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
929 BreakLocationIterator break_location_iterator(debug_info,
930 ALL_BREAK_LOCATIONS);
931 break_location_iterator.FindBreakLocationFromAddress(frame->pc());
934 if (!StepNextContinue(&break_location_iterator, frame)) {
936 if (thread_local_.step_count_ > 0) {
937 thread_local_.step_count_--;
943 Handle<Object> break_points_hit(heap->undefined_value());
944 if (break_location_iterator.HasBreakPoint()) {
945 Handle<Object> break_point_objects =
946 Handle<Object>(break_location_iterator.BreakPointObjects());
947 break_points_hit = CheckBreakPoints(break_point_objects);
952 if (StepOutActive() && frame->fp() != step_out_fp() &&
953 break_points_hit->IsUndefined() ) {
955 ASSERT(thread_local_.step_count_ == 0);
956 }
else if (!break_points_hit->IsUndefined() ||
957 (thread_local_.last_step_action_ != StepNone &&
958 thread_local_.step_count_ == 0)) {
965 if (thread_local_.queued_step_count_ > 0) {
967 int step_count = thread_local_.queued_step_count_;
970 thread_local_.queued_step_count_ = 0;
972 PrepareStep(StepNext, step_count);
975 isolate_->debugger()->OnDebugBreak(break_points_hit,
false);
977 }
else if (thread_local_.last_step_action_ != StepNone) {
980 StepAction step_action = thread_local_.last_step_action_;
981 int step_count = thread_local_.step_count_;
985 if (step_action == StepNext && frame->fp() < thread_local_.last_fp_) {
989 while (!it.done() && it.frame()->fp() < thread_local_.last_fp_) {
995 CHECK(!it.done() && (it.frame()->fp() == thread_local_.last_fp_));
996 if (step_count > 1) {
998 thread_local_.queued_step_count_ = step_count - 1;
1002 step_action = StepOut;
1010 PrepareStep(step_action, step_count);
1013 if (thread_local_.frame_drop_mode_ == FRAMES_UNTOUCHED) {
1014 SetAfterBreakTarget(frame);
1015 }
else if (thread_local_.frame_drop_mode_ ==
1016 FRAME_DROPPED_IN_IC_CALL) {
1018 Code* plain_return = isolate_->builtins()->builtin(
1019 Builtins::kPlainReturn_LiveEdit);
1020 thread_local_.after_break_target_ = plain_return->entry();
1021 }
else if (thread_local_.frame_drop_mode_ ==
1022 FRAME_DROPPED_IN_DEBUG_SLOT_CALL) {
1025 Code* plain_return = isolate_->builtins()->builtin(
1026 Builtins::kFrameDropper_LiveEdit);
1027 thread_local_.after_break_target_ = plain_return->entry();
1028 }
else if (thread_local_.frame_drop_mode_ ==
1029 FRAME_DROPPED_IN_DIRECT_CALL) {
1031 }
else if (thread_local_.frame_drop_mode_ ==
1032 FRAME_DROPPED_IN_RETURN_CALL) {
1033 Code* plain_return = isolate_->builtins()->builtin(
1034 Builtins::kFrameDropper_LiveEdit);
1035 thread_local_.after_break_target_ = plain_return->entry();
1040 return heap->undefined_value();
1045 return isolate->debug()->Break(args);
1052 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
1053 Factory* factory = isolate_->factory();
1057 Handle<FixedArray> break_points_hit;
1058 int break_points_hit_count = 0;
1059 ASSERT(!break_point_objects->IsUndefined());
1060 if (break_point_objects->IsFixedArray()) {
1062 break_points_hit = factory->NewFixedArray(array->length());
1063 for (
int i = 0; i < array->length(); i++) {
1064 Handle<Object> o(array->get(i));
1065 if (CheckBreakPoint(o)) {
1066 break_points_hit->set(break_points_hit_count++, *o);
1070 break_points_hit = factory->NewFixedArray(1);
1071 if (CheckBreakPoint(break_point_objects)) {
1072 break_points_hit->set(break_points_hit_count++, *break_point_objects);
1077 if (break_points_hit_count == 0) {
1078 return factory->undefined_value();
1081 Handle<JSArray> result = factory->NewJSArrayWithElements(break_points_hit);
1082 result->set_length(
Smi::FromInt(break_points_hit_count));
1088 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
1089 Factory* factory = isolate_->factory();
1090 HandleScope scope(isolate_);
1093 if (!break_point_object->IsJSObject())
return true;
1096 Handle<String> is_break_point_triggered_symbol =
1097 factory->LookupAsciiSymbol(
"IsBreakPointTriggered");
1098 Handle<JSFunction> check_break_point =
1100 debug_context()->global_object()->GetPropertyNoExceptionThrown(
1101 *is_break_point_triggered_symbol)));
1104 Handle<Object> break_id = factory->NewNumberFromInt(Debug::break_id());
1107 bool caught_exception;
1108 Handle<Object> argv[] = { break_id, break_point_object };
1110 isolate_->js_builtins_object(),
1116 if (caught_exception || !result->IsBoolean()) {
1121 ASSERT(!result.is_null());
1122 return (*result)->IsTrue();
1127 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
1128 return !shared->debug_info()->IsUndefined();
1134 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
1135 ASSERT(HasDebugInfo(shared));
1136 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
1140 void Debug::SetBreakPoint(Handle<JSFunction>
function,
1141 Handle<Object> break_point_object,
1142 int* source_position) {
1143 HandleScope scope(isolate_);
1145 PrepareForBreakPoints();
1148 Handle<SharedFunctionInfo> shared(function->shared());
1149 if (!EnsureDebugInfo(shared,
function)) {
1154 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1156 ASSERT(*source_position >= 0);
1159 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1160 it.FindBreakLocationFromPosition(*source_position);
1161 it.SetBreakPoint(break_point_object);
1163 *source_position = it.position();
1166 ASSERT(debug_info->GetBreakPointCount() > 0);
1170 bool Debug::SetBreakPointForScript(Handle<Script> script,
1171 Handle<Object> break_point_object,
1172 int* source_position) {
1173 HandleScope scope(isolate_);
1175 PrepareForBreakPoints();
1178 Object* result = FindSharedFunctionInfoInScript(script, *source_position);
1179 if (result->IsUndefined())
return false;
1183 if (!EnsureDebugInfo(shared, Handle<JSFunction>::null())) {
1191 if (shared->start_position() > *source_position) {
1194 position = *source_position - shared->start_position();
1197 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1202 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1203 it.FindBreakLocationFromPosition(position);
1204 it.SetBreakPoint(break_point_object);
1206 *source_position = it.position() + shared->start_position();
1209 ASSERT(debug_info->GetBreakPointCount() > 0);
1214 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
1215 HandleScope scope(isolate_);
1217 DebugInfoListNode* node = debug_info_list_;
1218 while (node !=
NULL) {
1219 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
1220 break_point_object);
1221 if (!result->IsUndefined()) {
1223 BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
1224 Handle<DebugInfo> debug_info = node->debug_info();
1225 Handle<SharedFunctionInfo> shared(debug_info->shared());
1226 int source_position = break_point_info->statement_position()->value();
1229 ASSERT(source_position >= 0);
1232 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
1233 it.FindBreakLocationFromPosition(source_position);
1234 it.ClearBreakPoint(break_point_object);
1238 if (debug_info->GetBreakPointCount() == 0) {
1239 RemoveDebugInfo(debug_info);
1244 node = node->next();
1249 void Debug::ClearAllBreakPoints() {
1250 DebugInfoListNode* node = debug_info_list_;
1251 while (node !=
NULL) {
1253 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1254 it.ClearAllDebugBreak();
1255 node = node->next();
1259 while (debug_info_list_ !=
NULL) {
1260 RemoveDebugInfo(debug_info_list_->debug_info());
1265 void Debug::FloodWithOneShot(Handle<JSFunction>
function) {
1266 PrepareForBreakPoints();
1269 Handle<SharedFunctionInfo> shared(function->shared());
1270 if (!EnsureDebugInfo(shared,
function)) {
1276 BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
1277 while (!it.Done()) {
1284 void Debug::FloodBoundFunctionWithOneShot(Handle<JSFunction>
function) {
1285 Handle<FixedArray> new_bindings(function->function_bindings());
1288 if (!bindee.is_null() && bindee->IsJSFunction() &&
1291 Debug::FloodWithOneShot(bindee_function);
1296 void Debug::FloodHandlerWithOneShot() {
1298 StackFrame::Id
id = break_frame_id();
1299 if (
id == StackFrame::NO_ID) {
1304 JavaScriptFrame* frame = it.frame();
1305 if (frame->HasHandler()) {
1308 FloodWithOneShot(Handle<JSFunction>(
function));
1315 void Debug::ChangeBreakOnException(ExceptionBreakType type,
bool enable) {
1316 if (type == BreakUncaughtException) {
1317 break_on_uncaught_exception_ = enable;
1319 break_on_exception_ = enable;
1324 bool Debug::IsBreakOnException(ExceptionBreakType type) {
1325 if (type == BreakUncaughtException) {
1326 return break_on_uncaught_exception_;
1328 return break_on_exception_;
1333 void Debug::PrepareStep(StepAction step_action,
int step_count) {
1334 HandleScope scope(isolate_);
1336 PrepareForBreakPoints();
1338 ASSERT(Debug::InDebugger());
1341 thread_local_.last_step_action_ = step_action;
1342 if (step_action == StepOut) {
1345 thread_local_.step_count_ = 0;
1347 thread_local_.step_count_ = step_count;
1354 StackFrame::Id
id = break_frame_id();
1355 if (
id == StackFrame::NO_ID) {
1360 JavaScriptFrame* frame = frames_it.frame();
1364 FloodHandlerWithOneShot();
1369 if (!frame->function()->IsJSFunction()) {
1372 frames_it.Advance();
1375 FloodWithOneShot(Handle<JSFunction>(
function));
1381 Handle<SharedFunctionInfo> shared(function->shared());
1382 if (!EnsureDebugInfo(shared,
function)) {
1386 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1389 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
1390 it.FindBreakLocationFromAddress(frame->pc());
1393 bool is_load_or_store =
false;
1394 bool is_inline_cache_stub =
false;
1395 bool is_at_restarted_function =
false;
1396 Handle<Code> call_function_stub;
1398 if (thread_local_.restarter_frame_function_pointer_ ==
NULL) {
1399 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
1400 bool is_call_target =
false;
1401 Address target = it.rinfo()->target_address();
1403 if (code->is_call_stub() || code->is_keyed_call_stub()) {
1404 is_call_target =
true;
1406 if (code->is_inline_cache_stub()) {
1407 is_inline_cache_stub =
true;
1408 is_load_or_store = !is_call_target;
1412 Code* maybe_call_function_stub =
code;
1415 if (it.IsDebugBreak()) {
1416 Address original_target = it.original_rinfo()->target_address();
1417 maybe_call_function_stub =
1420 if (maybe_call_function_stub->kind() == Code::STUB &&
1421 maybe_call_function_stub->major_key() == CodeStub::CallFunction) {
1424 call_function_stub = Handle<Code>(maybe_call_function_stub);
1428 is_at_restarted_function =
true;
1432 if (it.IsExit() || step_action == StepOut) {
1433 if (step_action == StepOut) {
1435 while (step_count-- > 0 && !frames_it.done()) {
1436 frames_it.Advance();
1440 frames_it.Advance();
1443 while (!frames_it.done() &&
1445 frames_it.Advance();
1449 if (!frames_it.done()) {
1452 FloodWithOneShot(Handle<JSFunction>(
function));
1454 ActivateStepOut(frames_it.frame());
1456 }
else if (!(is_inline_cache_stub || RelocInfo::IsConstructCall(it.rmode()) ||
1457 !call_function_stub.is_null() || is_at_restarted_function)
1458 || step_action == StepNext || step_action == StepMin) {
1462 FloodWithOneShot(
function);
1465 thread_local_.last_statement_position_ =
1466 debug_info->code()->SourceStatementPosition(frame->pc());
1467 thread_local_.last_fp_ = frame->UnpaddedFP();
1471 if (is_at_restarted_function) {
1472 Handle<JSFunction> restarted_function(
1474 FloodWithOneShot(restarted_function);
1475 }
else if (!call_function_stub.is_null()) {
1483 isolate_->heap()->code_stubs()->SlowReverseLookup(
1484 *call_function_stub));
1486 ASSERT(!(*obj)->IsUndefined());
1492 int call_function_arg_count =
1494 CodeStub::MinorKeyFromKey(key));
1495 ASSERT(call_function_stub->major_key() ==
1496 CodeStub::MajorKeyFromKey(key));
1505 int expressions_count = frame->ComputeExpressionsCount();
1506 ASSERT(expressions_count - 2 - call_function_arg_count >= 0);
1507 Object* fun = frame->GetExpression(
1508 expressions_count - 2 - call_function_arg_count);
1509 if (fun->IsJSFunction()) {
1511 if (js_function->shared()->bound()) {
1512 Debug::FloodBoundFunctionWithOneShot(js_function);
1513 }
else if (!js_function->IsBuiltin()) {
1516 FloodWithOneShot(js_function);
1525 FloodWithOneShot(
function);
1527 if (is_load_or_store) {
1532 thread_local_.last_statement_position_ =
1533 debug_info->code()->SourceStatementPosition(frame->pc());
1534 thread_local_.last_fp_ = frame->UnpaddedFP();
1539 ActivateStepIn(frame);
1550 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
1551 JavaScriptFrame* frame) {
1554 if (thread_local_.last_step_action_ == StepNext ||
1555 thread_local_.last_step_action_ == StepOut) {
1556 if (frame->fp() < thread_local_.last_fp_)
return true;
1561 if (thread_local_.last_step_action_ == StepNext ||
1562 thread_local_.last_step_action_ == StepIn) {
1564 if (break_location_iterator->IsExit())
return false;
1567 int current_statement_position =
1568 break_location_iterator->code()->SourceStatementPosition(frame->pc());
1569 return thread_local_.last_fp_ == frame->UnpaddedFP() &&
1570 thread_local_.last_statement_position_ == current_statement_position;
1580 bool Debug::IsDebugBreak(
Address addr) {
1588 bool Debug::IsSourceBreakStub(Code* code) {
1589 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1590 return major_key == CodeStub::CallFunction;
1596 bool Debug::IsBreakStub(Code* code) {
1597 CodeStub::Major major_key = CodeStub::GetMajorKey(code);
1598 return major_key == CodeStub::CallFunction;
1603 Handle<Code> Debug::FindDebugBreak(Handle<Code> code, RelocInfo::Mode mode) {
1604 Isolate* isolate = Isolate::Current();
1608 if (code->is_inline_cache_stub()) {
1609 switch (code->kind()) {
1611 case Code::KEYED_CALL_IC:
1612 return isolate->stub_cache()->ComputeCallDebugBreak(
1613 code->arguments_count(), code->kind());
1616 return isolate->builtins()->LoadIC_DebugBreak();
1618 case Code::STORE_IC:
1619 return isolate->builtins()->StoreIC_DebugBreak();
1621 case Code::KEYED_LOAD_IC:
1622 return isolate->builtins()->KeyedLoadIC_DebugBreak();
1624 case Code::KEYED_STORE_IC:
1625 return isolate->builtins()->KeyedStoreIC_DebugBreak();
1631 if (RelocInfo::IsConstructCall(mode)) {
1632 if (code->has_function_cache()) {
1633 return isolate->builtins()->CallConstructStub_Recording_DebugBreak();
1635 return isolate->builtins()->CallConstructStub_DebugBreak();
1638 if (code->kind() == Code::STUB) {
1639 ASSERT(code->major_key() == CodeStub::CallFunction);
1640 if (code->has_function_cache()) {
1641 return isolate->builtins()->CallFunctionStub_Recording_DebugBreak();
1643 return isolate->builtins()->CallFunctionStub_DebugBreak();
1653 Handle<Object> Debug::GetSourceBreakLocations(
1654 Handle<SharedFunctionInfo> shared) {
1655 Isolate* isolate = Isolate::Current();
1656 Heap* heap = isolate->heap();
1657 if (!HasDebugInfo(shared))
return Handle<Object>(heap->undefined_value());
1658 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
1659 if (debug_info->GetBreakPointCount() == 0) {
1660 return Handle<Object>(heap->undefined_value());
1662 Handle<FixedArray> locations =
1663 isolate->factory()->NewFixedArray(debug_info->GetBreakPointCount());
1665 for (
int i = 0; i < debug_info->break_points()->length(); i++) {
1666 if (!debug_info->break_points()->get(i)->IsUndefined()) {
1667 BreakPointInfo* break_point_info =
1668 BreakPointInfo::cast(debug_info->break_points()->get(i));
1669 if (break_point_info->GetBreakPointCount() > 0) {
1670 locations->set(count++, break_point_info->statement_position());
1678 void Debug::NewBreak(StackFrame::Id break_frame_id) {
1679 thread_local_.break_frame_id_ = break_frame_id;
1680 thread_local_.break_id_ = ++thread_local_.break_count_;
1684 void Debug::SetBreak(StackFrame::Id break_frame_id,
int break_id) {
1685 thread_local_.break_frame_id_ = break_frame_id;
1686 thread_local_.break_id_ = break_id;
1691 void Debug::HandleStepIn(Handle<JSFunction>
function,
1692 Handle<Object> holder,
1694 bool is_constructor) {
1697 StackFrameIterator it;
1700 if (is_constructor) {
1701 ASSERT(it.frame()->is_construct());
1704 fp = it.frame()->fp();
1709 if (fp == step_in_fp()) {
1710 if (function->shared()->bound()) {
1712 Debug::FloodBoundFunctionWithOneShot(
function);
1713 }
else if (!function->IsBuiltin()) {
1715 if (function->shared()->code() ==
1716 Isolate::Current()->builtins()->builtin(Builtins::kFunctionApply) ||
1717 function->shared()->code() ==
1718 Isolate::Current()->builtins()->builtin(Builtins::kFunctionCall)) {
1723 if (!holder.is_null() && holder->IsJSFunction() &&
1726 Debug::FloodWithOneShot(js_function);
1729 Debug::FloodWithOneShot(
function);
1736 void Debug::ClearStepping() {
1744 thread_local_.step_count_ = 0;
1750 void Debug::ClearOneShot() {
1755 DebugInfoListNode* node = debug_info_list_;
1756 while (node !=
NULL) {
1757 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
1758 while (!it.Done()) {
1762 node = node->next();
1767 void Debug::ActivateStepIn(
StackFrame* frame) {
1768 ASSERT(!StepOutActive());
1769 thread_local_.step_into_fp_ = frame->UnpaddedFP();
1773 void Debug::ClearStepIn() {
1774 thread_local_.step_into_fp_ = 0;
1778 void Debug::ActivateStepOut(
StackFrame* frame) {
1780 thread_local_.step_out_fp_ = frame->UnpaddedFP();
1784 void Debug::ClearStepOut() {
1785 thread_local_.step_out_fp_ = 0;
1789 void Debug::ClearStepNext() {
1790 thread_local_.last_step_action_ = StepNone;
1791 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
1792 thread_local_.last_fp_ = 0;
1805 static bool CompileFullCodeForDebugging(Handle<JSFunction>
function,
1806 Handle<Code> current_code) {
1807 ASSERT(!current_code->has_debug_break_slots());
1809 CompilationInfoWithZone info(
function);
1810 info.MarkCompilingForDebugging(current_code);
1811 ASSERT(!info.shared_info()->is_compiled());
1812 ASSERT(!info.isolate()->has_pending_exception());
1817 ASSERT(result != Isolate::Current()->has_pending_exception());
1818 info.isolate()->clear_pending_exception();
1821 Handle<Code> new_code(function->shared()->code());
1822 ASSERT(new_code->has_debug_break_slots());
1823 ASSERT(current_code->is_compiled_optimizable() ==
1824 new_code->is_compiled_optimizable());
1831 static void CollectActiveFunctionsFromThread(
1833 ThreadLocalTop* top,
1834 List<Handle<JSFunction> >* active_functions,
1835 Object* active_code_marker) {
1841 JavaScriptFrame* frame = it.frame();
1842 if (frame->is_optimized()) {
1844 frame->GetFunctions(&functions);
1845 for (
int i = 0; i < functions.length(); i++) {
1846 JSFunction*
function = functions[i];
1847 active_functions->Add(Handle<JSFunction>(
function));
1848 function->shared()->code()->set_gc_metadata(active_code_marker);
1850 }
else if (frame->function()->IsJSFunction()) {
1852 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1853 active_functions->Add(Handle<JSFunction>(
function));
1854 function->shared()->code()->set_gc_metadata(active_code_marker);
1860 static void RedirectActivationsToRecompiledCodeOnThread(
1862 ThreadLocalTop* top) {
1864 JavaScriptFrame* frame = it.frame();
1866 if (frame->is_optimized() || !frame->function()->IsJSFunction())
continue;
1870 ASSERT(frame->LookupCode()->kind() == Code::FUNCTION);
1872 Handle<Code> frame_code(frame->LookupCode());
1873 if (frame_code->has_debug_break_slots())
continue;
1875 Handle<Code> new_code(function->shared()->code());
1876 if (new_code->kind() != Code::FUNCTION ||
1877 !new_code->has_debug_break_slots()) {
1884 int constpool_mask = RelocInfo::ModeMask(RelocInfo::CONST_POOL);
1885 int frame_const_pool_size = 0;
1886 for (RelocIterator it(*frame_code, constpool_mask); !it.done(); it.next()) {
1887 RelocInfo* info = it.rinfo();
1888 if (info->pc() >= frame->pc())
break;
1889 frame_const_pool_size +=
static_cast<int>(info->data());
1891 intptr_t frame_offset =
1892 frame->pc() - frame_code->instruction_start() - frame_const_pool_size;
1896 int debug_break_slot_bytes = 0;
1897 int new_code_const_pool_size = 0;
1898 int mask = RelocInfo::ModeMask(RelocInfo::DEBUG_BREAK_SLOT) |
1899 RelocInfo::ModeMask(RelocInfo::CONST_POOL);
1900 for (RelocIterator it(*new_code, mask); !it.done(); it.next()) {
1903 RelocInfo* info = it.rinfo();
1904 intptr_t new_offset = info->pc() - new_code->instruction_start() -
1905 new_code_const_pool_size - debug_break_slot_bytes;
1906 if (new_offset >= frame_offset) {
1910 if (RelocInfo::IsDebugBreakSlot(info->rmode())) {
1913 ASSERT(RelocInfo::IsConstPool(info->rmode()));
1915 new_code_const_pool_size +=
static_cast<int>(info->data());
1920 byte* new_pc = new_code->instruction_start() + frame_offset +
1921 debug_break_slot_bytes + new_code_const_pool_size;
1923 if (FLAG_trace_deopt) {
1928 reinterpret_cast<intptr_t>(
1929 frame_code->instruction_start()),
1930 reinterpret_cast<intptr_t>(
1931 frame_code->instruction_start()) +
1932 frame_code->instruction_size(),
1933 frame_code->instruction_size(),
1934 reinterpret_cast<intptr_t
>(new_code->instruction_start()),
1935 reinterpret_cast<intptr_t>(new_code->instruction_start()) +
1936 new_code->instruction_size(),
1937 new_code->instruction_size(),
1938 reinterpret_cast<intptr_t
>(frame->pc()),
1939 reinterpret_cast<intptr_t>(new_pc));
1944 frame->set_pc(new_pc);
1949 class ActiveFunctionsCollector :
public ThreadVisitor {
1951 explicit ActiveFunctionsCollector(List<Handle<JSFunction> >* active_functions,
1952 Object* active_code_marker)
1953 : active_functions_(active_functions),
1954 active_code_marker_(active_code_marker) { }
1956 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1957 CollectActiveFunctionsFromThread(isolate,
1960 active_code_marker_);
1964 List<Handle<JSFunction> >* active_functions_;
1965 Object* active_code_marker_;
1969 class ActiveFunctionsRedirector :
public ThreadVisitor {
1971 void VisitThread(Isolate* isolate, ThreadLocalTop* top) {
1972 RedirectActivationsToRecompiledCodeOnThread(isolate, top);
1977 void Debug::PrepareForBreakPoints() {
1980 if (!has_break_points_) {
1983 Handle<Code> lazy_compile =
1984 Handle<Code>(isolate_->builtins()->builtin(Builtins::kLazyCompile));
1987 has_break_points_ =
true;
1991 List<Handle<JSFunction> > active_functions(100);
1997 "preparing for breakpoints");
2001 AssertNoAllocation no_allocation;
2003 Object* active_code_marker = isolate_->heap()->the_hole_value();
2005 CollectActiveFunctionsFromThread(isolate_,
2006 isolate_->thread_local_top(),
2008 active_code_marker);
2009 ActiveFunctionsCollector active_functions_collector(&active_functions,
2010 active_code_marker);
2011 isolate_->thread_manager()->IterateArchivedThreads(
2012 &active_functions_collector);
2017 HeapIterator iterator;
2018 HeapObject* obj =
NULL;
2019 while (((obj = iterator.next()) !=
NULL)) {
2020 if (obj->IsJSFunction()) {
2022 SharedFunctionInfo* shared =
function->shared();
2023 if (shared->allows_lazy_compilation() &&
2024 shared->script()->IsScript() &&
2025 function->code()->kind() == Code::FUNCTION &&
2026 !
function->code()->has_debug_break_slots() &&
2027 shared->code()->gc_metadata() != active_code_marker) {
2028 function->set_code(*lazy_compile);
2029 function->shared()->set_code(*lazy_compile);
2035 for (
int i = 0; i < active_functions.length(); i++) {
2036 Handle<JSFunction>
function = active_functions[i];
2037 function->shared()->code()->set_gc_metadata(
Smi::FromInt(0));
2043 for (
int i = 0; i < active_functions.length(); i++) {
2044 Handle<JSFunction>
function = active_functions[i];
2045 Handle<SharedFunctionInfo> shared(function->shared());
2047 if (function->code()->kind() == Code::FUNCTION &&
2048 function->code()->has_debug_break_slots()) {
2054 if (shared->is_toplevel() ||
2055 !shared->allows_lazy_compilation() ||
2062 if (!shared->code()->has_debug_break_slots()) {
2065 Handle<Code> current_code(function->shared()->code());
2066 shared->set_code(*lazy_compile);
2067 bool prev_force_debugger_active =
2068 isolate_->debugger()->force_debugger_active();
2069 isolate_->debugger()->set_force_debugger_active(
true);
2070 ASSERT(current_code->kind() == Code::FUNCTION);
2071 CompileFullCodeForDebugging(
function, current_code);
2072 isolate_->debugger()->set_force_debugger_active(
2073 prev_force_debugger_active);
2074 if (!shared->is_compiled()) {
2075 shared->set_code(*current_code);
2081 function->set_code(shared->code());
2084 RedirectActivationsToRecompiledCodeOnThread(isolate_,
2085 isolate_->thread_local_top());
2087 ActiveFunctionsRedirector active_functions_redirector;
2088 isolate_->thread_manager()->IterateArchivedThreads(
2089 &active_functions_redirector);
2094 Object* Debug::FindSharedFunctionInfoInScript(Handle<Script> script,
2109 int target_start_position = RelocInfo::kNoPosition;
2110 Handle<JSFunction> target_function;
2111 Handle<SharedFunctionInfo> target;
2114 isolate_->heap()->EnsureHeapIsIterable();
2115 AssertNoAllocation no_alloc_during_heap_iteration;
2116 HeapIterator iterator;
2117 for (HeapObject* obj = iterator.next();
2118 obj !=
NULL; obj = iterator.next()) {
2119 bool found_next_candidate =
false;
2120 Handle<JSFunction>
function;
2121 Handle<SharedFunctionInfo> shared;
2122 if (obj->IsJSFunction()) {
2124 shared = Handle<SharedFunctionInfo>(
function->shared());
2125 ASSERT(shared->allows_lazy_compilation() || shared->is_compiled());
2126 found_next_candidate =
true;
2127 }
else if (obj->IsSharedFunctionInfo()) {
2131 found_next_candidate = shared->is_compiled() ||
2132 shared->allows_lazy_compilation_without_context();
2134 if (!found_next_candidate)
continue;
2135 if (shared->script() == *script) {
2138 int start_position = shared->function_token_position();
2139 if (start_position == RelocInfo::kNoPosition) {
2140 start_position = shared->start_position();
2142 if (start_position <= position &&
2143 position <= shared->end_position()) {
2146 if (target.is_null()) {
2147 target_start_position = start_position;
2148 target_function =
function;
2151 if (target_start_position == start_position &&
2152 shared->end_position() == target->end_position()) {
2156 if (!shared->is_toplevel()) {
2157 target_start_position = start_position;
2158 target_function =
function;
2161 }
else if (target_start_position <= start_position &&
2162 shared->end_position() <= target->end_position()) {
2166 target_start_position = start_position;
2167 target_function =
function;
2176 if (target.is_null()) {
2177 return isolate_->heap()->undefined_value();
2181 has_break_points_ =
true;
2184 done = target->is_compiled();
2191 if (target_function.is_null()) {
2204 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared,
2205 Handle<JSFunction>
function) {
2207 if (HasDebugInfo(shared)) {
2208 ASSERT(shared->is_compiled());
2213 has_break_points_ =
true;
2216 if (!
function.is_null() &&
2222 Handle<DebugInfo> debug_info =
FACTORY->NewDebugInfo(shared);
2225 DebugInfoListNode* node =
new DebugInfoListNode(*debug_info);
2226 node->set_next(debug_info_list_);
2227 debug_info_list_ = node;
2233 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
2236 DebugInfoListNode* prev =
NULL;
2237 DebugInfoListNode* current = debug_info_list_;
2238 while (current !=
NULL) {
2239 if (*current->debug_info() == *debug_info) {
2242 debug_info_list_ = current->next();
2244 prev->set_next(current->next());
2246 current->debug_info()->shared()->set_debug_info(
2247 isolate_->heap()->undefined_value());
2252 has_break_points_ = debug_info_list_ !=
NULL;
2258 current = current->next();
2264 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
2265 HandleScope scope(isolate_);
2267 PrepareForBreakPoints();
2271 Handle<SharedFunctionInfo> shared(function->shared());
2272 if (!EnsureDebugInfo(shared,
function)) {
2276 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2277 Handle<Code>
code(debug_info->code());
2278 Handle<Code> original_code(debug_info->original_code());
2281 Handle<Code> frame_code(frame->LookupCode());
2282 ASSERT(frame_code.is_identical_to(code));
2291 bool at_js_return =
false;
2292 bool break_at_js_return_active =
false;
2293 bool at_debug_break_slot =
false;
2294 RelocIterator it(debug_info->code());
2295 while (!it.done() && !at_js_return && !at_debug_break_slot) {
2296 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2297 at_js_return = (it.rinfo()->pc() ==
2299 break_at_js_return_active = it.rinfo()->IsPatchedReturnSequence();
2301 if (RelocInfo::IsDebugBreakSlot(it.rinfo()->rmode())) {
2302 at_debug_break_slot = (it.rinfo()->pc() ==
2314 if (break_at_js_return_active) {
2315 addr += original_code->instruction_start() - code->instruction_start();
2319 thread_local_.after_break_target_ =
2321 }
else if (at_debug_break_slot) {
2334 addr += original_code->instruction_start() - code->instruction_start();
2349 bool Debug::IsBreakAtReturn(JavaScriptFrame* frame) {
2350 HandleScope scope(isolate_);
2355 if (!has_break_points_) {
2359 PrepareForBreakPoints();
2363 Handle<SharedFunctionInfo> shared(function->shared());
2364 if (!EnsureDebugInfo(shared,
function)) {
2368 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
2369 Handle<Code>
code(debug_info->code());
2372 Handle<Code> frame_code(frame->LookupCode());
2373 ASSERT(frame_code.is_identical_to(code));
2380 RelocIterator it(debug_info->code());
2381 while (!it.done()) {
2382 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
2383 return (it.rinfo()->pc() ==
2392 void Debug::FramesHaveBeenDropped(StackFrame::Id new_break_frame_id,
2394 Object** restarter_frame_function_pointer) {
2395 if (mode != CURRENTLY_SET_MODE) {
2396 thread_local_.frame_drop_mode_ = mode;
2398 thread_local_.break_frame_id_ = new_break_frame_id;
2399 thread_local_.restarter_frame_function_pointer_ =
2400 restarter_frame_function_pointer;
2404 const int Debug::FramePaddingLayout::kInitialSize = 1;
2408 const int Debug::FramePaddingLayout::kPaddingValue = kInitialSize + 1;
2411 bool Debug::IsDebugGlobal(GlobalObject* global) {
2412 return IsLoaded() && global == debug_context()->global_object();
2416 void Debug::ClearMirrorCache() {
2417 PostponeInterruptsScope postpone(isolate_);
2418 HandleScope scope(isolate_);
2419 ASSERT(isolate_->context() == *Debug::debug_context());
2422 Handle<String> function_name =
2423 isolate_->factory()->LookupSymbol(
CStrVector(
"ClearMirrorCache"));
2425 Isolate::Current()->global_object()->GetPropertyNoExceptionThrown(
2427 ASSERT(fun->IsJSFunction());
2428 bool caught_exception;
2430 Handle<JSObject>(Debug::debug_context()->global_object()),
2431 0,
NULL, &caught_exception);
2435 void Debug::CreateScriptCache() {
2436 Heap* heap = isolate_->heap();
2437 HandleScope scope(isolate_);
2445 "Debug::CreateScriptCache");
2448 script_cache_ =
new ScriptCache();
2452 HeapIterator iterator;
2453 AssertNoAllocation no_allocation;
2455 for (HeapObject* obj = iterator.next(); obj !=
NULL; obj = iterator.next()) {
2464 void Debug::DestroyScriptCache() {
2466 if (script_cache_ !=
NULL) {
2467 delete script_cache_;
2468 script_cache_ =
NULL;
2473 void Debug::AddScriptToScriptCache(Handle<Script> script) {
2474 if (script_cache_ !=
NULL) {
2475 script_cache_->Add(script);
2480 Handle<FixedArray> Debug::GetLoadedScripts() {
2483 if (script_cache_ ==
NULL) {
2484 CreateScriptCache();
2489 if (script_cache_ ==
NULL) {
2490 isolate_->factory()->NewFixedArray(0);
2496 "Debug::GetLoadedScripts");
2499 return script_cache_->GetScripts();
2503 void Debug::AfterGarbageCollection() {
2505 if (script_cache_ !=
NULL) {
2506 script_cache_->ProcessCollectedScripts();
2511 Debugger::Debugger(Isolate* isolate)
2512 : debugger_access_(isolate->debugger_access()),
2513 event_listener_(Handle<
Object>()),
2514 event_listener_data_(Handle<
Object>()),
2515 compiling_natives_(
false),
2516 is_loading_debugger_(
false),
2517 live_edit_enabled_(
true),
2518 never_unload_debugger_(
false),
2519 force_debugger_active_(
false),
2520 message_handler_(
NULL),
2521 debugger_unload_pending_(
false),
2522 host_dispatch_handler_(
NULL),
2523 dispatch_handler_access_(OS::CreateMutex()),
2524 debug_message_dispatch_handler_(
NULL),
2525 message_dispatch_helper_thread_(
NULL),
2526 host_dispatch_micros_(100 * 1000),
2528 command_queue_(isolate->logger(), kQueueInitialSize),
2529 command_received_(OS::CreateSemaphore(0)),
2530 event_command_queue_(isolate->logger(), kQueueInitialSize),
2535 Debugger::~Debugger() {
2536 delete dispatch_handler_access_;
2537 dispatch_handler_access_ = 0;
2538 delete command_received_;
2539 command_received_ = 0;
2543 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
2545 Handle<Object> argv[],
2546 bool* caught_exception) {
2547 ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2550 Handle<String> constructor_str =
2551 isolate_->factory()->LookupSymbol(constructor_name);
2552 Handle<Object> constructor(
2553 isolate_->global_object()->GetPropertyNoExceptionThrown(
2555 ASSERT(constructor->IsJSFunction());
2556 if (!constructor->IsJSFunction()) {
2557 *caught_exception =
true;
2558 return isolate_->factory()->undefined_value();
2561 Handle<JSFunction>::cast(constructor),
2562 Handle<JSObject>(isolate_->debug()->debug_context()->global_object()),
2570 Handle<Object> Debugger::MakeExecutionState(
bool* caught_exception) {
2572 Handle<Object> break_id = isolate_->factory()->NewNumberFromInt(
2573 isolate_->debug()->break_id());
2574 Handle<Object> argv[] = { break_id };
2575 return MakeJSObject(
CStrVector(
"MakeExecutionState"),
2582 Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
2583 Handle<Object> break_points_hit,
2584 bool* caught_exception) {
2586 Handle<Object> argv[] = { exec_state, break_points_hit };
2587 return MakeJSObject(
CStrVector(
"MakeBreakEvent"),
2594 Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
2595 Handle<Object> exception,
2597 bool* caught_exception) {
2598 Factory* factory = isolate_->factory();
2600 Handle<Object> argv[] = { exec_state,
2602 factory->ToBoolean(uncaught) };
2603 return MakeJSObject(
CStrVector(
"MakeExceptionEvent"),
2610 Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object>
function,
2611 bool* caught_exception) {
2613 Handle<Object> argv[] = {
function };
2614 return MakeJSObject(
CStrVector(
"MakeNewFunctionEvent"),
2621 Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
2623 bool* caught_exception) {
2624 Factory* factory = isolate_->factory();
2626 Handle<Object> exec_state = MakeExecutionState(caught_exception);
2628 Handle<Object> argv[] = { exec_state,
2630 factory->ToBoolean(before) };
2631 return MakeJSObject(
CStrVector(
"MakeCompileEvent"),
2638 Handle<Object> Debugger::MakeScriptCollectedEvent(
int id,
2639 bool* caught_exception) {
2641 Handle<Object> exec_state = MakeExecutionState(caught_exception);
2642 Handle<Object> id_object = Handle<Smi>(
Smi::FromInt(
id));
2643 Handle<Object> argv[] = { exec_state, id_object };
2645 return MakeJSObject(
CStrVector(
"MakeScriptCollectedEvent"),
2652 void Debugger::OnException(Handle<Object> exception,
bool uncaught) {
2653 HandleScope scope(isolate_);
2654 Debug* debug = isolate_->debug();
2657 if (debug->InDebugger())
return;
2663 if (!(debug->break_on_uncaught_exception() ||
2664 debug->break_on_exception()))
return;
2667 if (!debug->break_on_exception())
return;
2671 EnterDebugger debugger;
2672 if (debugger.FailedToEnter())
return;
2675 debug->ClearStepping();
2677 bool caught_exception =
false;
2678 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2679 Handle<Object> event_data;
2680 if (!caught_exception) {
2681 event_data = MakeExceptionEvent(exec_state, exception, uncaught,
2685 if (caught_exception) {
2690 ProcessDebugEvent(
v8::Exception, Handle<JSObject>::cast(event_data),
false);
2695 void Debugger::OnDebugBreak(Handle<Object> break_points_hit,
2696 bool auto_continue) {
2697 HandleScope scope(isolate_);
2700 ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2703 if (!Debugger::EventActive(
v8::Break))
return;
2706 ASSERT(isolate_->context() == *isolate_->debug()->debug_context());
2709 bool caught_exception =
false;
2710 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2711 Handle<Object> event_data;
2712 if (!caught_exception) {
2713 event_data = MakeBreakEvent(exec_state, break_points_hit,
2717 if (caught_exception) {
2723 Handle<JSObject>::cast(event_data),
2728 void Debugger::OnBeforeCompile(Handle<Script> script) {
2729 HandleScope scope(isolate_);
2732 if (isolate_->debug()->InDebugger())
return;
2733 if (compiling_natives())
return;
2737 EnterDebugger debugger;
2738 if (debugger.FailedToEnter())
return;
2741 bool caught_exception =
false;
2742 Handle<Object> event_data = MakeCompileEvent(script,
true, &caught_exception);
2744 if (caught_exception) {
2750 Handle<JSObject>::cast(event_data),
2756 void Debugger::OnAfterCompile(Handle<Script> script,
2757 AfterCompileFlags after_compile_flags) {
2758 HandleScope scope(isolate_);
2759 Debug* debug = isolate_->debug();
2762 debug->AddScriptToScriptCache(script);
2765 if (!IsDebuggerActive())
return;
2768 if (compiling_natives())
return;
2771 bool in_debugger = debug->InDebugger();
2774 EnterDebugger debugger;
2775 if (debugger.FailedToEnter())
return;
2781 Handle<String> update_script_break_points_symbol =
2782 isolate_->factory()->LookupAsciiSymbol(
"UpdateScriptBreakPoints");
2783 Handle<Object> update_script_break_points =
2784 Handle<Object>(debug->debug_context()->global_object()->
2785 GetPropertyNoExceptionThrown(*update_script_break_points_symbol));
2786 if (!update_script_break_points->IsJSFunction()) {
2789 ASSERT(update_script_break_points->IsJSFunction());
2796 bool caught_exception;
2797 Handle<Object> argv[] = { wrapper };
2799 Isolate::Current()->js_builtins_object(),
2803 if (caught_exception) {
2807 if (in_debugger && (after_compile_flags & SEND_WHEN_DEBUGGING) == 0)
return;
2811 Handle<Object> event_data = MakeCompileEvent(script,
2815 if (caught_exception) {
2820 Handle<JSObject>::cast(event_data),
2825 void Debugger::OnScriptCollected(
int id) {
2826 HandleScope scope(isolate_);
2829 if (isolate_->debug()->InDebugger())
return;
2830 if (!IsDebuggerActive())
return;
2834 EnterDebugger debugger;
2835 if (debugger.FailedToEnter())
return;
2838 bool caught_exception =
false;
2839 Handle<Object> event_data = MakeScriptCollectedEvent(
id,
2842 if (caught_exception) {
2848 Handle<JSObject>::cast(event_data),
2854 Handle<JSObject> event_data,
2855 bool auto_continue) {
2856 HandleScope scope(isolate_);
2859 if (!auto_continue) {
2860 isolate_->debug()->clear_interrupt_pending(
DEBUGBREAK);
2864 bool caught_exception =
false;
2865 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
2866 if (caught_exception) {
2870 if (message_handler_ !=
NULL) {
2871 NotifyMessageHandler(event,
2872 Handle<JSObject>::cast(exec_state),
2879 if ((event !=
v8::Break || !auto_continue) && !event_listener_.is_null()) {
2880 CallEventCallback(event, exec_state, event_data,
NULL);
2884 while (!event_command_queue_.IsEmpty()) {
2885 CommandMessage command = event_command_queue_.Get();
2886 if (!event_listener_.is_null()) {
2890 command.client_data());
2899 Handle<Object> exec_state,
2900 Handle<Object> event_data,
2902 if (event_listener_->IsForeign()) {
2903 CallCEventCallback(event, exec_state, event_data, client_data);
2905 CallJSEventCallback(event, exec_state, event_data);
2911 Handle<Object> exec_state,
2912 Handle<Object> event_data,
2914 Handle<Foreign> callback_obj(Handle<Foreign>::cast(event_listener_));
2916 FUNCTION_CAST<v8::Debug::EventCallback2>(
2917 callback_obj->foreign_address());
2918 EventDetailsImpl event_details(
2920 Handle<JSObject>::cast(exec_state),
2921 Handle<JSObject>::cast(event_data),
2922 event_listener_data_,
2924 callback(event_details);
2929 Handle<Object> exec_state,
2930 Handle<Object> event_data) {
2931 ASSERT(event_listener_->IsJSFunction());
2932 Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
2935 Handle<Object> argv[] = { Handle<Object>(
Smi::FromInt(event)),
2938 event_listener_data_ };
2939 bool caught_exception;
2941 isolate_->global_object(),
2949 Handle<Context> Debugger::GetDebugContext() {
2950 never_unload_debugger_ =
true;
2951 EnterDebugger debugger;
2952 return isolate_->debug()->debug_context();
2956 void Debugger::UnloadDebugger() {
2957 Debug* debug = isolate_->debug();
2960 debug->ClearAllBreakPoints();
2963 if (!never_unload_debugger_) {
2968 debugger_unload_pending_ =
false;
2973 Handle<JSObject> exec_state,
2974 Handle<JSObject> event_data,
2975 bool auto_continue) {
2976 HandleScope scope(isolate_);
2978 if (!isolate_->debug()->Load())
return;
2981 bool sendEventMessage =
false;
2985 sendEventMessage = !auto_continue;
2988 sendEventMessage =
true;
2993 sendEventMessage =
true;
2996 sendEventMessage =
true;
3007 ASSERT(isolate_->debug()->InDebugger());
3012 if (sendEventMessage) {
3013 MessageImpl message = MessageImpl::NewEvent(
3016 Handle<JSObject>::cast(exec_state),
3017 Handle<JSObject>::cast(event_data));
3018 InvokeMessageHandler(message);
3043 static const int kArgc = 1;
3052 bool running = auto_continue;
3057 if (Debugger::host_dispatch_handler_) {
3059 if (!command_received_->Wait(host_dispatch_micros_)) {
3061 Debugger::host_dispatch_handler_();
3066 command_received_->Wait();
3070 CommandMessage command = command_queue_.Get();
3071 isolate_->logger()->DebugTag(
3072 "Got request from command queue, in interactive loop.");
3073 if (!Debugger::IsDebuggerActive()) {
3088 command.text().length());
3089 static const int kArgc = 1;
3104 if (FLAG_trace_debug_json) {
3112 static const int kArgc = 1;
3116 running = running_val->
ToBoolean()->Value();
3120 response = try_catch.
Exception()->ToString();
3124 MessageImpl message = MessageImpl::NewResponse(
3127 Handle<JSObject>::cast(exec_state),
3128 Handle<JSObject>::cast(event_data),
3129 Handle<String>(Utils::OpenHandle(*response)),
3130 command.client_data());
3131 InvokeMessageHandler(message);
3137 if (running && !HasCommands()) {
3144 void Debugger::SetEventListener(Handle<Object> callback,
3145 Handle<Object> data) {
3146 HandleScope scope(isolate_);
3147 GlobalHandles* global_handles = isolate_->global_handles();
3151 if (!event_listener_.is_null()) {
3152 global_handles->Destroy(
3153 reinterpret_cast<Object**>(event_listener_.location()));
3154 event_listener_ = Handle<Object>();
3156 if (!event_listener_data_.is_null()) {
3157 global_handles->Destroy(
3158 reinterpret_cast<Object**>(event_listener_data_.location()));
3159 event_listener_data_ = Handle<Object>();
3164 if (!callback->IsUndefined() && !callback->IsNull()) {
3166 global_handles->Create(*callback));
3167 if (data.is_null()) {
3168 data = isolate_->factory()->undefined_value();
3171 global_handles->Create(*data));
3179 ScopedLock with(debugger_access_);
3181 message_handler_ = handler;
3183 if (handler ==
NULL) {
3186 if (isolate_->debug()->InDebugger()) {
3187 ProcessCommand(Vector<const uint16_t>::empty());
3193 void Debugger::ListenersChanged() {
3194 if (IsDebuggerActive()) {
3196 isolate_->compilation_cache()->Disable();
3197 debugger_unload_pending_ =
false;
3199 isolate_->compilation_cache()->Enable();
3202 debugger_unload_pending_ =
true;
3209 host_dispatch_handler_ = handler;
3210 host_dispatch_micros_ = period * 1000;
3214 void Debugger::SetDebugMessageDispatchHandler(
3216 ScopedLock with(dispatch_handler_access_);
3217 debug_message_dispatch_handler_ = handler;
3219 if (provide_locker && message_dispatch_helper_thread_ ==
NULL) {
3220 message_dispatch_helper_thread_ =
new MessageDispatchHelperThread(isolate_);
3221 message_dispatch_helper_thread_->Start();
3228 void Debugger::InvokeMessageHandler(MessageImpl message) {
3229 ScopedLock with(debugger_access_);
3231 if (message_handler_ !=
NULL) {
3232 message_handler_(message);
3241 void Debugger::ProcessCommand(Vector<const uint16_t> command,
3244 CommandMessage message = CommandMessage::New(
3245 Vector<uint16_t>(const_cast<uint16_t*>(command.start()),
3248 isolate_->logger()->DebugTag(
"Put command on command_queue.");
3249 command_queue_.Put(message);
3250 command_received_->Signal();
3253 if (!isolate_->debug()->InDebugger()) {
3254 isolate_->stack_guard()->DebugCommand();
3257 MessageDispatchHelperThread* dispatch_thread;
3259 ScopedLock with(dispatch_handler_access_);
3260 dispatch_thread = message_dispatch_helper_thread_;
3263 if (dispatch_thread ==
NULL) {
3264 CallMessageDispatchHandler();
3266 dispatch_thread->Schedule();
3271 bool Debugger::HasCommands() {
3272 return !command_queue_.IsEmpty();
3277 CommandMessage message = CommandMessage::New(Vector<uint16_t>(), client_data);
3278 event_command_queue_.Put(message);
3281 if (!isolate_->debug()->InDebugger()) {
3282 isolate_->stack_guard()->DebugCommand();
3287 bool Debugger::IsDebuggerActive() {
3288 ScopedLock with(debugger_access_);
3290 return message_handler_ !=
NULL ||
3291 !event_listener_.is_null() ||
3292 force_debugger_active_;
3296 Handle<Object> Debugger::Call(Handle<JSFunction> fun,
3297 Handle<Object> data,
3298 bool* pending_exception) {
3300 Debugger::never_unload_debugger_ =
true;
3303 EnterDebugger debugger;
3304 if (debugger.FailedToEnter()) {
3305 return isolate_->factory()->undefined_value();
3309 bool caught_exception =
false;
3310 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
3311 if (caught_exception) {
3312 return isolate_->factory()->undefined_value();
3315 Handle<Object> argv[] = { exec_state, data };
3318 Handle<Object>(isolate_->debug()->debug_context_->global_proxy()),
3331 bool Debugger::StartAgent(
const char* name,
int port,
3332 bool wait_for_connection) {
3333 ASSERT(Isolate::Current() == isolate_);
3334 if (wait_for_connection) {
3341 Debugger::message_handler_ = StubMessageHandler2;
3346 if (agent_ ==
NULL) {
3347 agent_ =
new DebuggerAgent(name, port);
3357 void Debugger::StopAgent() {
3358 ASSERT(Isolate::Current() == isolate_);
3359 if (agent_ !=
NULL) {
3368 void Debugger::WaitForAgent() {
3369 ASSERT(Isolate::Current() == isolate_);
3371 agent_->WaitUntilListening();
3375 void Debugger::CallMessageDispatchHandler() {
3378 ScopedLock with(dispatch_handler_access_);
3379 handler = Debugger::debug_message_dispatch_handler_;
3381 if (handler !=
NULL) {
3387 EnterDebugger::EnterDebugger()
3388 : isolate_(Isolate::Current()),
3389 prev_(isolate_->debug()->debugger_entry()),
3391 has_js_frames_(!it_.done()),
3393 Debug* debug = isolate_->debug();
3398 debug->set_debugger_entry(
this);
3401 break_id_ = debug->break_id();
3402 break_frame_id_ = debug->break_frame_id();
3406 if (has_js_frames_) {
3407 debug->NewBreak(it_.frame()->id());
3409 debug->NewBreak(StackFrame::NO_ID);
3413 load_failed_ = !debug->Load();
3414 if (!load_failed_) {
3417 isolate_->set_context(*debug->debug_context());
3422 EnterDebugger::~EnterDebugger() {
3423 ASSERT(Isolate::Current() == isolate_);
3424 Debug* debug = isolate_->debug();
3427 debug->SetBreak(break_frame_id_, break_id_);
3430 if (!load_failed_ && prev_ ==
NULL) {
3435 if (!isolate_->has_pending_exception()) {
3438 if (isolate_->stack_guard()->IsDebugBreak()) {
3440 isolate_->stack_guard()->Continue(
DEBUGBREAK);
3442 debug->ClearMirrorCache();
3447 if (debug->is_interrupt_pending(
PREEMPT)) {
3450 debug->clear_interrupt_pending(
PREEMPT);
3451 isolate_->stack_guard()->Preempt();
3453 if (debug->is_interrupt_pending(
DEBUGBREAK)) {
3455 isolate_->stack_guard()->DebugBreak();
3460 if (isolate_->debugger()->HasCommands()) {
3461 isolate_->stack_guard()->DebugCommand();
3465 if (!isolate_->debugger()->IsDebuggerActive()) {
3466 isolate_->debugger()->UnloadDebugger();
3471 debug->set_debugger_entry(prev_);
3475 MessageImpl MessageImpl::NewEvent(
DebugEvent event,
3477 Handle<JSObject> exec_state,
3478 Handle<JSObject> event_data) {
3479 MessageImpl
message(
true, event, running,
3480 exec_state, event_data, Handle<String>(),
NULL);
3485 MessageImpl MessageImpl::NewResponse(
DebugEvent event,
3487 Handle<JSObject> exec_state,
3488 Handle<JSObject> event_data,
3489 Handle<String> response_json,
3491 MessageImpl
message(
false, event, running,
3492 exec_state, event_data, response_json, client_data);
3497 MessageImpl::MessageImpl(
bool is_event,
3500 Handle<JSObject> exec_state,
3501 Handle<JSObject> event_data,
3502 Handle<String> response_json,
3504 : is_event_(is_event),
3507 exec_state_(exec_state),
3508 event_data_(event_data),
3509 response_json_(response_json),
3510 client_data_(client_data) {}
3513 bool MessageImpl::IsEvent()
const {
3518 bool MessageImpl::IsResponse()
const {
3528 bool MessageImpl::WillStartRunning()
const {
3548 Handle<Object> fun =
GetProperty(event_data_,
"toJSONProtocol");
3549 if (!fun->IsJSFunction()) {
3552 bool caught_exception;
3555 0,
NULL, &caught_exception);
3556 if (caught_exception || !json->IsString()) {
3567 Isolate* isolate = Isolate::Current();
3576 return client_data_;
3580 EventDetailsImpl::EventDetailsImpl(
DebugEvent event,
3581 Handle<JSObject> exec_state,
3582 Handle<JSObject> event_data,
3583 Handle<Object> callback_data,
3586 exec_state_(exec_state),
3587 event_data_(event_data),
3588 callback_data_(callback_data),
3589 client_data_(client_data) {}
3592 DebugEvent EventDetailsImpl::GetEvent()
const {
3608 return GetDebugEventContext(Isolate::Current());
3618 return client_data_;
3622 CommandMessage::CommandMessage() : text_(Vector<
uint16_t>::empty()),
3623 client_data_(
NULL) {
3627 CommandMessage::CommandMessage(
const Vector<uint16_t>& text,
3630 client_data_(data) {
3634 CommandMessage::~CommandMessage() {
3638 void CommandMessage::Dispose() {
3640 delete client_data_;
3641 client_data_ =
NULL;
3645 CommandMessage CommandMessage::New(
const Vector<uint16_t>& command,
3647 return CommandMessage(command.Clone(), data);
3651 CommandMessageQueue::CommandMessageQueue(
int size) : start_(0),
end_(0),
3653 messages_ = NewArray<CommandMessage>(size);
3657 CommandMessageQueue::~CommandMessageQueue() {
3658 while (!IsEmpty()) {
3659 CommandMessage m = Get();
3666 CommandMessage CommandMessageQueue::Get() {
3668 int result = start_;
3669 start_ = (start_ + 1) % size_;
3670 return messages_[result];
3674 void CommandMessageQueue::Put(
const CommandMessage& message) {
3675 if ((
end_ + 1) % size_ == start_) {
3683 void CommandMessageQueue::Expand() {
3684 CommandMessageQueue new_queue(size_ * 2);
3685 while (!IsEmpty()) {
3686 new_queue.Put(Get());
3688 CommandMessage* array_to_free = messages_;
3690 new_queue.messages_ = array_to_free;
3692 new_queue.start_ = new_queue.end_;
3697 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger,
int size)
3698 : logger_(logger), queue_(size) {
3703 LockingCommandMessageQueue::~LockingCommandMessageQueue() {
3708 bool LockingCommandMessageQueue::IsEmpty()
const {
3709 ScopedLock sl(lock_);
3710 return queue_.IsEmpty();
3714 CommandMessage LockingCommandMessageQueue::Get() {
3715 ScopedLock sl(lock_);
3716 CommandMessage result = queue_.Get();
3717 logger_->DebugEvent(
"Get", result.text());
3722 void LockingCommandMessageQueue::Put(
const CommandMessage& message) {
3723 ScopedLock sl(lock_);
3724 queue_.Put(message);
3725 logger_->DebugEvent(
"Put", message.text());
3729 void LockingCommandMessageQueue::Clear() {
3730 ScopedLock sl(lock_);
3735 MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
3736 : Thread(
"v8:MsgDispHelpr"),
3737 sem_(OS::CreateSemaphore(0)), mutex_(OS::CreateMutex()),
3738 already_signalled_(
false) {
3742 MessageDispatchHelperThread::~MessageDispatchHelperThread() {
3748 void MessageDispatchHelperThread::Schedule() {
3750 ScopedLock lock(mutex_);
3751 if (already_signalled_) {
3754 already_signalled_ =
true;
3760 void MessageDispatchHelperThread::Run() {
3764 ScopedLock lock(mutex_);
3765 already_signalled_ =
false;
3769 Isolate::Current()->debugger()->CallMessageDispatchHandler();
3774 #endif // ENABLE_DEBUGGER_SUPPORT
V8EXPORT int Length() const
static Handle< Object > SetProperty(Handle< JSReceiver > object, Handle< String > key, Handle< Object > value, PropertyAttributes attributes, StrictModeFlag strict_mode)
static Object * Cast(Value *obj)
static bool CompileLazy(Handle< JSFunction > function, ClearExceptionFlag flag)
static Object *& Object_at(Address addr)
static Handle< Object > TryCall(Handle< JSFunction > func, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *caught_exception)
Handle< Boolean > V8EXPORT True()
void PrintF(const char *format,...)
Local< Value > Exception() const
static Handle< JSMessageObject > MakeMessageObject(const char *type, MessageLocation *loc, Vector< Handle< Object > > args, Handle< String > stack_trace, Handle< JSArray > stack_frames)
V8EXPORT Local< Value > Get(Handle< Value > key)
static Smi * FromInt(int value)
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)
static V8EXPORT Local< String > New(const char *data, int length=-1)
void(* DebugMessageDispatchHandler)()
V8EXPORT Local< Value > Call(Handle< Object > recv, int argc, Handle< Value > argv[])
#define ASSERT(condition)
static const int kPatchReturnSequenceAddressOffset
static Script * cast(Object *obj)
void(* MessageHandler2)(const Message &message)
static void DeoptimizeAll()
static SharedFunctionInfo * cast(Object *obj)
V8EXPORT Local< String > ToString() const
Handle< Object > GetProperty(Handle< JSReceiver > obj, const char *name)
static Function * Cast(Value *obj)
#define RETURN_IF_EMPTY_HANDLE_VALUE(isolate, call, value)
static Smi * cast(Object *object)
HANDLE HANDLE LPSTACKFRAME64 StackFrame
static const int kNoGCFlags
Handle< JSValue > GetScriptWrapper(Handle< Script > script)
Entry * Lookup(void *key, uint32_t hash, bool insert, FreeStoreAllocationPolicyallocator=FreeStoreAllocationPolicy())
static Mutex * CreateMutex()
static Code * GetCodeFromTargetAddress(Address address)
static const int kMakeHeapIterableMask
static String * Cast(v8::Value *obj)
Handle< Boolean > V8EXPORT False()
activate correct semantics for inheriting readonliness false
static Handle< Object > Call(Handle< Object > callable, Handle< Object > receiver, int argc, Handle< Object > argv[], bool *pending_exception, bool convert_receiver=false)
Vector< const char > CStrVector(const char *data)
static const int kDebugBreakSlotLength
static Local< Context > ToLocal(v8::internal::Handle< v8::internal::Context > obj)
void(* EventCallback2)(const EventDetails &event_details)
static Address target_address_at(Address pc)
void(* HostDispatchHandler)()
static Handle< SharedFunctionInfo > Compile(Handle< String > source, Handle< Object > script_name, int line_offset, int column_offset, Handle< Context > context, v8::Extension *extension, ScriptDataImpl *pre_data, Handle< Object > script_data, NativesFlag is_natives_code)
JavaScriptFrameIteratorTemp< StackFrameIterator > JavaScriptFrameIterator
static const int kContextOffset
static const int kFunctionOffset
static bool EnsureCompiled(Handle< JSFunction > function, ClearExceptionFlag flag)
Object * JSCallerSavedBuffer[kNumJSCallerSaved]
v8::Handle< v8::Value > Load(const v8::Arguments &args)
static Handle< String > null()
static bool CompileLazy(Handle< SharedFunctionInfo > shared, ClearExceptionFlag flag)
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if expose natives in global object expose gc extension number of stack frames to capture disable builtin natives files print a stack trace if an assertion failure occurs use random jit cookie to mask large constants trace lazy optimization use adaptive optimizations prepare for turning on always opt minimum length for automatic enable preparsing maximum number of optimization attempts before giving up cache prototype transitions automatically set the debug break flag when debugger commands are in the queue always cause a debug break before aborting 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 more details following each garbage collection print amount of external allocated memory after each time it is adjusted flush code that we expect not to use again before full gc do incremental marking steps track object counts and memory usage use caching Perform compaction on every full GC Never perform compaction on full GC testing only Compact code space on full incremental collections Default seed for initializing random allows verbose printing trace parsing and preparsing Check icache flushes in ARM and MIPS simulator Stack alingment in bytes in print stack trace when throwing exceptions randomize hashes to avoid predictable hash Fixed seed to use to hash property activate a timer that switches between V8 threads testing_bool_flag float flag Seed used for threading test randomness A filename with extra code to be included in the Print usage message
Local< T > Close(Handle< T > value)
static FixedArray * cast(Object *obj)
V8EXPORT int WriteAscii(char *buffer, int start=0, int length=-1, int options=NO_OPTIONS) const
static bool CompileLazy(CompilationInfo *info)
static const int kBoundFunctionIndex
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit 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 SAHF instruction if enable use of VFP3 instructions if available this implies enabling ARMv7 and VFP2 enable use of VFP2 instructions if available 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 MIPS FPU instructions if NULL
static const int kMaxInliningLevels
activate correct semantics for inheriting readonliness enable harmony semantics for typeof enable harmony enable harmony proxies enable all harmony harmony_scoping harmony_proxies harmony_scoping tracks arrays with only smi values automatically unbox arrays of doubles use crankshaft use hydrogen range analysis use hydrogen global value numbering use function inlining maximum number of AST nodes considered for a single inlining loop invariant code motion print statistics for hydrogen trace generated IR for specified phases trace register allocator trace range analysis trace representation types environment for every instruction put a break point before deoptimizing polymorphic inlining perform array bounds checks elimination use dead code elimination trace on stack replacement optimize closures cache optimized code for closures functions with arguments object loop weight for representation inference allow uint32 values on optimize frames if they are used only in safe operations track parallel recompilation enable all profiler experiments number of stack frames inspected by the profiler call recompile stub directly when self optimizing trigger profiler ticks based on counting instead of timing weight back edges by jump distance for interrupt triggering percentage of ICs that must have type info to allow optimization watch_ic_patching retry_self_opt interrupt_at_exit extra verbose compilation tracing generate extra code(assertions) for debugging") DEFINE_bool(code_comments
V8EXPORT Local< Boolean > ToBoolean() const
static const int kCodeOffset
static void DebugBreak(Isolate *isolate=NULL)
static void ReportMessage(Isolate *isolate, MessageLocation *loc, Handle< Object > message)
static const int kMarkerOffset
void DeleteArray(T *array)
static const int kPatchDebugBreakSlotAddressOffset
static void FatalProcessOutOfMemory(const char *location, bool take_snapshot=false)
static JSFunction * cast(Object *obj)