00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "v8.h"
00029
00030 #include "api.h"
00031 #include "arguments.h"
00032 #include "bootstrapper.h"
00033 #include "code-stubs.h"
00034 #include "compiler.h"
00035 #include "debug.h"
00036 #include "execution.h"
00037 #include "global-handles.h"
00038 #include "natives.h"
00039 #include "stub-cache.h"
00040 #include "log.h"
00041
00042 namespace v8 { namespace internal {
00043
00044 static void PrintLn(v8::Local<v8::Value> value) {
00045 v8::Local<v8::String> s = value->ToString();
00046 char* data = NewArray<char>(s->Length() + 1);
00047 if (data == NULL) {
00048 V8::FatalProcessOutOfMemory("PrintLn");
00049 return;
00050 }
00051 s->WriteAscii(data);
00052 PrintF("%s\n", data);
00053 DeleteArray(data);
00054 }
00055
00056
00057 static Handle<Code> ComputeCallDebugBreak(int argc) {
00058 CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugBreak(argc), Code);
00059 }
00060
00061
00062 static Handle<Code> ComputeCallDebugPrepareStepIn(int argc) {
00063 CALL_HEAP_FUNCTION(StubCache::ComputeCallDebugPrepareStepIn(argc), Code);
00064 }
00065
00066
00067 BreakLocationIterator::BreakLocationIterator(Handle<DebugInfo> debug_info,
00068 BreakLocatorType type) {
00069 debug_info_ = debug_info;
00070 type_ = type;
00071 reloc_iterator_ = NULL;
00072 reloc_iterator_original_ = NULL;
00073 Reset();
00074 }
00075
00076
00077 BreakLocationIterator::~BreakLocationIterator() {
00078 ASSERT(reloc_iterator_ != NULL);
00079 ASSERT(reloc_iterator_original_ != NULL);
00080 delete reloc_iterator_;
00081 delete reloc_iterator_original_;
00082 }
00083
00084
00085 void BreakLocationIterator::Next() {
00086 AssertNoAllocation nogc;
00087 ASSERT(!RinfoDone());
00088
00089
00090
00091 bool first = break_point_ == -1;
00092 while (!RinfoDone()) {
00093 if (!first) RinfoNext();
00094 first = false;
00095 if (RinfoDone()) return;
00096
00097
00098
00099 if (RelocInfo::IsPosition(rmode())) {
00100 if (RelocInfo::IsStatementPosition(rmode())) {
00101 statement_position_ =
00102 rinfo()->data() - debug_info_->shared()->start_position();
00103 }
00104
00105
00106 position_ = rinfo()->data() - debug_info_->shared()->start_position();
00107 ASSERT(position_ >= 0);
00108 ASSERT(statement_position_ >= 0);
00109 }
00110
00111
00112
00113
00114 if (RelocInfo::IsCodeTarget(rmode())) {
00115 Address target = original_rinfo()->target_address();
00116 Code* code = Debug::GetCodeTarget(target);
00117 if (code->is_inline_cache_stub() || RelocInfo::IsConstructCall(rmode())) {
00118 break_point_++;
00119 return;
00120 }
00121 if (code->kind() == Code::STUB) {
00122 if (type_ == ALL_BREAK_LOCATIONS) {
00123 if (Debug::IsBreakStub(code)) {
00124 break_point_++;
00125 return;
00126 }
00127 } else {
00128 ASSERT(type_ == SOURCE_BREAK_LOCATIONS);
00129 if (Debug::IsSourceBreakStub(code)) {
00130 break_point_++;
00131 return;
00132 }
00133 }
00134 }
00135 }
00136
00137
00138 if (RelocInfo::IsJSReturn(rmode())) {
00139
00140 if (debug_info_->shared()->HasSourceCode()) {
00141 position_ = debug_info_->shared()->end_position() -
00142 debug_info_->shared()->start_position();
00143 } else {
00144 position_ = 0;
00145 }
00146 statement_position_ = position_;
00147 break_point_++;
00148 return;
00149 }
00150 }
00151 }
00152
00153
00154 void BreakLocationIterator::Next(int count) {
00155 while (count > 0) {
00156 Next();
00157 count--;
00158 }
00159 }
00160
00161
00162
00163 void BreakLocationIterator::FindBreakLocationFromAddress(Address pc) {
00164
00165 int closest_break_point = 0;
00166 int distance = kMaxInt;
00167 while (!Done()) {
00168
00169 if (this->pc() < pc && pc - this->pc() < distance) {
00170 closest_break_point = break_point();
00171 distance = pc - this->pc();
00172
00173 if (distance == 0) break;
00174 }
00175 Next();
00176 }
00177
00178
00179 Reset();
00180 Next(closest_break_point);
00181 }
00182
00183
00184
00185 void BreakLocationIterator::FindBreakLocationFromPosition(int position) {
00186
00187
00188 int closest_break_point = 0;
00189 int distance = kMaxInt;
00190 while (!Done()) {
00191
00192 if (position <= statement_position() &&
00193 statement_position() - position < distance) {
00194 closest_break_point = break_point();
00195 distance = statement_position() - position;
00196
00197 if (distance == 0) break;
00198 }
00199 Next();
00200 }
00201
00202
00203 Reset();
00204 Next(closest_break_point);
00205 }
00206
00207
00208 void BreakLocationIterator::Reset() {
00209
00210 if (reloc_iterator_ != NULL) delete reloc_iterator_;
00211 if (reloc_iterator_original_ != NULL) delete reloc_iterator_original_;
00212 reloc_iterator_ = new RelocIterator(debug_info_->code());
00213 reloc_iterator_original_ = new RelocIterator(debug_info_->original_code());
00214
00215
00216 break_point_ = -1;
00217 position_ = 1;
00218 statement_position_ = 1;
00219 Next();
00220 }
00221
00222
00223 bool BreakLocationIterator::Done() const {
00224 return RinfoDone();
00225 }
00226
00227
00228 void BreakLocationIterator::SetBreakPoint(Handle<Object> break_point_object) {
00229
00230
00231 if (!HasBreakPoint()) {
00232 SetDebugBreak();
00233 }
00234 ASSERT(IsDebugBreak());
00235
00236 DebugInfo::SetBreakPoint(debug_info_, code_position(),
00237 position(), statement_position(),
00238 break_point_object);
00239 }
00240
00241
00242 void BreakLocationIterator::ClearBreakPoint(Handle<Object> break_point_object) {
00243
00244 DebugInfo::ClearBreakPoint(debug_info_, code_position(), break_point_object);
00245
00246 if (!HasBreakPoint()) {
00247 ClearDebugBreak();
00248 ASSERT(!IsDebugBreak());
00249 }
00250 }
00251
00252
00253 void BreakLocationIterator::SetOneShot() {
00254
00255 if (HasBreakPoint()) {
00256 ASSERT(IsDebugBreak());
00257 return;
00258 }
00259
00260
00261 SetDebugBreak();
00262 }
00263
00264
00265 void BreakLocationIterator::ClearOneShot() {
00266
00267 if (HasBreakPoint()) {
00268 ASSERT(IsDebugBreak());
00269 return;
00270 }
00271
00272
00273 ClearDebugBreak();
00274 ASSERT(!IsDebugBreak());
00275 }
00276
00277
00278 void BreakLocationIterator::SetDebugBreak() {
00279
00280
00281
00282
00283 if (IsDebugBreak()) {
00284 return;
00285 }
00286
00287 if (RelocInfo::IsJSReturn(rmode())) {
00288
00289
00290
00291
00292
00293 ASSERT(Debug::kIa32JSReturnSequenceLength >=
00294 Debug::kIa32CallInstructionLength);
00295 rinfo()->patch_code_with_call(Debug::debug_break_return_entry()->entry(),
00296 Debug::kIa32JSReturnSequenceLength - Debug::kIa32CallInstructionLength);
00297 } else {
00298
00299
00300 original_rinfo()->set_target_address(rinfo()->target_address());
00301
00302
00303
00304 Handle<Code> dbgbrk_code(Debug::FindDebugBreak(rinfo()));
00305 rinfo()->set_target_address(dbgbrk_code->entry());
00306 }
00307 ASSERT(IsDebugBreak());
00308 }
00309
00310
00311 void BreakLocationIterator::ClearDebugBreak() {
00312 if (RelocInfo::IsJSReturn(rmode())) {
00313
00314 rinfo()->patch_code(original_rinfo()->pc(),
00315 Debug::kIa32JSReturnSequenceLength);
00316 } else {
00317
00318 rinfo()->set_target_address(original_rinfo()->target_address());
00319 }
00320 ASSERT(!IsDebugBreak());
00321 }
00322
00323
00324 void BreakLocationIterator::PrepareStepIn() {
00325
00326
00327 Address target = rinfo()->target_address();
00328 Code* code = Debug::GetCodeTarget(target);
00329 if (code->is_call_stub()) {
00330
00331
00332
00333
00334
00335 Handle<Code> stub = ComputeCallDebugPrepareStepIn(code->arguments_count());
00336 if (IsDebugBreak()) {
00337 original_rinfo()->set_target_address(stub->entry());
00338 } else {
00339 rinfo()->set_target_address(stub->entry());
00340 }
00341 } else {
00342
00343 ASSERT(RelocInfo::IsConstructCall(rmode()));
00344 }
00345 }
00346
00347
00348
00349 bool BreakLocationIterator::IsExit() const {
00350 return (RelocInfo::IsJSReturn(rmode()));
00351 }
00352
00353
00354 bool BreakLocationIterator::HasBreakPoint() {
00355 return debug_info_->HasBreakPoint(code_position());
00356 }
00357
00358
00359
00360 bool BreakLocationIterator::IsDebugBreak() {
00361 if (RelocInfo::IsJSReturn(rmode())) {
00362
00363
00364
00365
00366
00367 return (*(rinfo()->pc()) == 0xE8);
00368 } else {
00369 return Debug::IsDebugBreak(rinfo()->target_address());
00370 }
00371 }
00372
00373
00374 Object* BreakLocationIterator::BreakPointObjects() {
00375 return debug_info_->GetBreakPointObjects(code_position());
00376 }
00377
00378
00379 bool BreakLocationIterator::RinfoDone() const {
00380 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
00381 return reloc_iterator_->done();
00382 }
00383
00384
00385 void BreakLocationIterator::RinfoNext() {
00386 reloc_iterator_->next();
00387 reloc_iterator_original_->next();
00388 #ifdef DEBUG
00389 ASSERT(reloc_iterator_->done() == reloc_iterator_original_->done());
00390 if (!reloc_iterator_->done()) {
00391 ASSERT(rmode() == original_rmode());
00392 }
00393 #endif
00394 }
00395
00396
00397 bool Debug::has_break_points_ = false;
00398 DebugInfoListNode* Debug::debug_info_list_ = NULL;
00399
00400
00401
00402 void Debug::ThreadInit() {
00403 thread_local_.last_step_action_ = StepNone;
00404 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
00405 thread_local_.step_count_ = 0;
00406 thread_local_.last_fp_ = 0;
00407 thread_local_.step_into_fp_ = 0;
00408 thread_local_.after_break_target_ = 0;
00409 }
00410
00411
00412 JSCallerSavedBuffer Debug::registers_;
00413 Debug::ThreadLocal Debug::thread_local_;
00414
00415
00416 char* Debug::ArchiveDebug(char* storage) {
00417 char* to = storage;
00418 memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
00419 to += sizeof(ThreadLocal);
00420 memcpy(to, reinterpret_cast<char*>(®isters_), sizeof(registers_));
00421 ThreadInit();
00422 ASSERT(to <= storage + ArchiveSpacePerThread());
00423 return storage + ArchiveSpacePerThread();
00424 }
00425
00426
00427 char* Debug::RestoreDebug(char* storage) {
00428 char* from = storage;
00429 memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
00430 from += sizeof(ThreadLocal);
00431 memcpy(reinterpret_cast<char*>(®isters_), from, sizeof(registers_));
00432 ASSERT(from <= storage + ArchiveSpacePerThread());
00433 return storage + ArchiveSpacePerThread();
00434 }
00435
00436
00437 int Debug::ArchiveSpacePerThread() {
00438 return sizeof(ThreadLocal) + sizeof(registers_);
00439 }
00440
00441
00442
00443 bool Debug::disable_break_ = false;
00444
00445
00446 bool Debug::break_on_exception_ = false;
00447 bool Debug::break_on_uncaught_exception_ = true;
00448
00449 Handle<Context> Debug::debug_context_ = Handle<Context>();
00450 Code* Debug::debug_break_return_entry_ = NULL;
00451 Code* Debug::debug_break_return_ = NULL;
00452
00453
00454 void Debug::HandleWeakDebugInfo(v8::Persistent<v8::Value> obj, void* data) {
00455 DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
00456 RemoveDebugInfo(node->debug_info());
00457 #ifdef DEBUG
00458 node = Debug::debug_info_list_;
00459 while (node != NULL) {
00460 ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
00461 node = node->next();
00462 }
00463 #endif
00464 }
00465
00466
00467 DebugInfoListNode::DebugInfoListNode(DebugInfo* debug_info): next_(NULL) {
00468
00469 debug_info_ = Handle<DebugInfo>::cast((GlobalHandles::Create(debug_info)));
00470 GlobalHandles::MakeWeak(reinterpret_cast<Object**>(debug_info_.location()),
00471 this, Debug::HandleWeakDebugInfo);
00472 }
00473
00474
00475 DebugInfoListNode::~DebugInfoListNode() {
00476 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_info_.location()));
00477 }
00478
00479
00480 void Debug::Setup(bool create_heap_objects) {
00481 ThreadInit();
00482 if (create_heap_objects) {
00483
00484 debug_break_return_entry_ =
00485 Builtins::builtin(Builtins::Return_DebugBreakEntry);
00486 ASSERT(debug_break_return_entry_->IsCode());
00487
00488
00489 debug_break_return_ =
00490 Builtins::builtin(Builtins::Return_DebugBreak);
00491 ASSERT(debug_break_return_->IsCode());
00492 }
00493 }
00494
00495
00496 bool Debug::CompileDebuggerScript(int index) {
00497 HandleScope scope;
00498
00499
00500 if (index == -1) {
00501 return false;
00502 }
00503
00504
00505 Handle<String> source_code = Bootstrapper::NativesSourceLookup(index);
00506 Vector<const char> name = Natives::GetScriptName(index);
00507 Handle<String> script_name = Factory::NewStringFromAscii(name);
00508
00509
00510 bool allow_natives_syntax = FLAG_allow_natives_syntax;
00511 FLAG_allow_natives_syntax = true;
00512 Handle<JSFunction> boilerplate;
00513 boilerplate = Compiler::Compile(source_code, script_name, 0, 0, NULL, NULL);
00514 FLAG_allow_natives_syntax = allow_natives_syntax;
00515
00516
00517 if (boilerplate.is_null()) {
00518 ASSERT(Top::has_pending_exception());
00519 Top::clear_pending_exception();
00520 return false;
00521 }
00522
00523
00524 Handle<Context> context = Top::global_context();
00525 bool caught_exception = false;
00526 Handle<JSFunction> function =
00527 Factory::NewFunctionFromBoilerplate(boilerplate, context);
00528 Handle<Object> result =
00529 Execution::TryCall(function, Handle<Object>(context->global()),
00530 0, NULL, &caught_exception);
00531
00532
00533 if (caught_exception) {
00534 Handle<Object> message = MessageHandler::MakeMessageObject(
00535 "error_loading_debugger", NULL, HandleVector<Object>(&result, 1),
00536 Handle<String>());
00537 MessageHandler::ReportMessage(NULL, message);
00538 return false;
00539 }
00540
00541
00542 Handle<Script> script(Script::cast(function->shared()->script()));
00543 script->set_type(Smi::FromInt(SCRIPT_TYPE_NATIVE));
00544 return true;
00545 }
00546
00547
00548 bool Debug::Load() {
00549
00550 if (IsLoaded()) return true;
00551
00552
00553
00554 if (Debugger::compiling_natives() || Debugger::is_loading_debugger())
00555 return false;
00556 Debugger::set_loading_debugger(true);
00557
00558
00559
00560 DisableBreak disable(true);
00561 PostponeInterruptsScope postpone;
00562
00563
00564 HandleScope scope;
00565 Handle<Context> context =
00566 Bootstrapper::CreateEnvironment(Handle<Object>::null(),
00567 v8::Handle<ObjectTemplate>(),
00568 NULL);
00569
00570
00571 SaveContext save;
00572 Top::set_context(*context);
00573
00574
00575 Handle<String> key = Factory::LookupAsciiSymbol("builtins");
00576 Handle<GlobalObject> global = Handle<GlobalObject>(context->global());
00577 SetProperty(global, key, Handle<Object>(global->builtins()), NONE);
00578
00579
00580 Debugger::set_compiling_natives(true);
00581 bool caught_exception =
00582 !CompileDebuggerScript(Natives::GetIndex("mirror")) ||
00583 !CompileDebuggerScript(Natives::GetIndex("debug"));
00584 Debugger::set_compiling_natives(false);
00585
00586
00587
00588 Debugger::set_loading_debugger(false);
00589
00590
00591 if (caught_exception) return false;
00592
00593
00594 debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
00595 return true;
00596 }
00597
00598
00599 void Debug::Unload() {
00600
00601 if (!IsLoaded()) {
00602 return;
00603 }
00604
00605
00606 GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
00607 debug_context_ = Handle<Context>();
00608 }
00609
00610
00611 void Debug::Iterate(ObjectVisitor* v) {
00612 #define VISIT(field) v->VisitPointer(bit_cast<Object**, Code**>(&(field)));
00613 VISIT(debug_break_return_entry_);
00614 VISIT(debug_break_return_);
00615 #undef VISIT
00616 }
00617
00618
00619 Object* Debug::Break(Arguments args) {
00620 HandleScope scope;
00621 ASSERT(args.length() == 0);
00622
00623
00624 JavaScriptFrameIterator it;
00625 JavaScriptFrame* frame = it.frame();
00626
00627
00628 if (disable_break() || !Load()) {
00629 SetAfterBreakTarget(frame);
00630 return Heap::undefined_value();
00631 }
00632
00633
00634 EnterDebugger debugger;
00635 if (debugger.FailedToEnter()) {
00636 return Heap::undefined_value();
00637 }
00638
00639
00640 PostponeInterruptsScope postpone;
00641
00642
00643 Handle<SharedFunctionInfo> shared =
00644 Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
00645 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
00646
00647
00648 BreakLocationIterator break_location_iterator(debug_info,
00649 ALL_BREAK_LOCATIONS);
00650 break_location_iterator.FindBreakLocationFromAddress(frame->pc());
00651
00652
00653 if (!StepNextContinue(&break_location_iterator, frame)) {
00654
00655 if (thread_local_.step_count_ > 0) {
00656 thread_local_.step_count_--;
00657 }
00658 }
00659
00660
00661
00662 Handle<Object> break_points_hit(Heap::undefined_value());
00663 if (break_location_iterator.HasBreakPoint()) {
00664 Handle<Object> break_point_objects =
00665 Handle<Object>(break_location_iterator.BreakPointObjects());
00666 break_points_hit = CheckBreakPoints(break_point_objects);
00667 }
00668
00669
00670
00671 if (!break_points_hit->IsUndefined() ||
00672 (thread_local_.last_step_action_ != StepNone &&
00673 thread_local_.step_count_ == 0)) {
00674
00675 ClearStepping();
00676
00677
00678 Debugger::OnDebugBreak(break_points_hit);
00679 } else if (thread_local_.last_step_action_ != StepNone) {
00680
00681
00682 StepAction step_action = thread_local_.last_step_action_;
00683 int step_count = thread_local_.step_count_;
00684
00685
00686 ClearStepping();
00687
00688
00689 PrepareStep(step_action, step_count);
00690 }
00691
00692
00693 SetAfterBreakTarget(frame);
00694
00695 return Heap::undefined_value();
00696 }
00697
00698
00699
00700
00701
00702 Handle<Object> Debug::CheckBreakPoints(Handle<Object> break_point_objects) {
00703 int break_points_hit_count = 0;
00704 Handle<JSArray> break_points_hit = Factory::NewJSArray(1);
00705
00706
00707 ASSERT(!break_point_objects->IsUndefined());
00708 if (break_point_objects->IsFixedArray()) {
00709 Handle<FixedArray> array(FixedArray::cast(*break_point_objects));
00710 for (int i = 0; i < array->length(); i++) {
00711 Handle<Object> o(array->get(i));
00712 if (CheckBreakPoint(o)) {
00713 break_points_hit->SetElement(break_points_hit_count++, *o);
00714 }
00715 }
00716 } else {
00717 if (CheckBreakPoint(break_point_objects)) {
00718 break_points_hit->SetElement(break_points_hit_count++,
00719 *break_point_objects);
00720 }
00721 }
00722
00723
00724 if (break_points_hit_count == 0) {
00725 return Factory::undefined_value();
00726 }
00727 return break_points_hit;
00728 }
00729
00730
00731
00732 bool Debug::CheckBreakPoint(Handle<Object> break_point_object) {
00733
00734 if (!break_point_object->IsJSObject()) return true;
00735
00736
00737 Handle<JSFunction> check_break_point =
00738 Handle<JSFunction>(JSFunction::cast(
00739 debug_context()->global()->GetProperty(
00740 *Factory::LookupAsciiSymbol("IsBreakPointTriggered"))));
00741
00742
00743 Handle<Object> break_id = Factory::NewNumberFromInt(Top::break_id());
00744
00745
00746 bool caught_exception = false;
00747 const int argc = 2;
00748 Object** argv[argc] = {
00749 break_id.location(),
00750 reinterpret_cast<Object**>(break_point_object.location())
00751 };
00752 Handle<Object> result = Execution::TryCall(check_break_point,
00753 Top::builtins(), argc, argv,
00754 &caught_exception);
00755
00756
00757 if (caught_exception || !result->IsBoolean()) {
00758 return false;
00759 }
00760
00761
00762 return *result == Heap::true_value();
00763 }
00764
00765
00766
00767 bool Debug::HasDebugInfo(Handle<SharedFunctionInfo> shared) {
00768 return !shared->debug_info()->IsUndefined();
00769 }
00770
00771
00772
00773
00774 Handle<DebugInfo> Debug::GetDebugInfo(Handle<SharedFunctionInfo> shared) {
00775 ASSERT(HasDebugInfo(shared));
00776 return Handle<DebugInfo>(DebugInfo::cast(shared->debug_info()));
00777 }
00778
00779
00780 void Debug::SetBreakPoint(Handle<SharedFunctionInfo> shared,
00781 int source_position,
00782 Handle<Object> break_point_object) {
00783 if (!EnsureDebugInfo(shared)) {
00784
00785 return;
00786 }
00787
00788 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
00789
00790 ASSERT(source_position >= 0);
00791
00792
00793 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
00794 it.FindBreakLocationFromPosition(source_position);
00795 it.SetBreakPoint(break_point_object);
00796
00797
00798 ASSERT(debug_info->GetBreakPointCount() > 0);
00799 }
00800
00801
00802 void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
00803 DebugInfoListNode* node = debug_info_list_;
00804 while (node != NULL) {
00805 Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
00806 break_point_object);
00807 if (!result->IsUndefined()) {
00808
00809 BreakPointInfo* break_point_info = BreakPointInfo::cast(result);
00810 Handle<DebugInfo> debug_info = node->debug_info();
00811 Handle<SharedFunctionInfo> shared(debug_info->shared());
00812 int source_position = break_point_info->statement_position()->value();
00813
00814
00815 ASSERT(source_position >= 0);
00816
00817
00818 BreakLocationIterator it(debug_info, SOURCE_BREAK_LOCATIONS);
00819 it.FindBreakLocationFromPosition(source_position);
00820 it.ClearBreakPoint(break_point_object);
00821
00822
00823
00824 if (debug_info->GetBreakPointCount() == 0) {
00825 RemoveDebugInfo(debug_info);
00826 }
00827
00828 return;
00829 }
00830 node = node->next();
00831 }
00832 }
00833
00834
00835 void Debug::FloodWithOneShot(Handle<SharedFunctionInfo> shared) {
00836
00837 if (!EnsureDebugInfo(shared)) {
00838
00839 return;
00840 }
00841
00842
00843 BreakLocationIterator it(GetDebugInfo(shared), ALL_BREAK_LOCATIONS);
00844 while (!it.Done()) {
00845 it.SetOneShot();
00846 it.Next();
00847 }
00848 }
00849
00850
00851 void Debug::FloodHandlerWithOneShot() {
00852 StackFrame::Id id = Top::break_frame_id();
00853 for (JavaScriptFrameIterator it(id); !it.done(); it.Advance()) {
00854 JavaScriptFrame* frame = it.frame();
00855 if (frame->HasHandler()) {
00856 Handle<SharedFunctionInfo> shared =
00857 Handle<SharedFunctionInfo>(
00858 JSFunction::cast(frame->function())->shared());
00859
00860 FloodWithOneShot(shared);
00861 return;
00862 }
00863 }
00864 }
00865
00866
00867 void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
00868 if (type == BreakUncaughtException) {
00869 break_on_uncaught_exception_ = enable;
00870 } else {
00871 break_on_exception_ = enable;
00872 }
00873 }
00874
00875
00876 void Debug::PrepareStep(StepAction step_action, int step_count) {
00877 HandleScope scope;
00878 ASSERT(Debug::InDebugger());
00879
00880
00881 thread_local_.last_step_action_ = step_action;
00882 thread_local_.step_count_ = step_count;
00883
00884
00885
00886
00887
00888 StackFrame::Id id = Top::break_frame_id();
00889 JavaScriptFrameIterator frames_it(id);
00890 JavaScriptFrame* frame = frames_it.frame();
00891
00892
00893
00894 FloodHandlerWithOneShot();
00895
00896
00897
00898
00899 if (!frame->function()->IsJSFunction()) {
00900
00901
00902 frames_it.Advance();
00903
00904 JSFunction* function = JSFunction::cast(frames_it.frame()->function());
00905 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
00906 return;
00907 }
00908
00909
00910 Handle<SharedFunctionInfo> shared =
00911 Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
00912 if (!EnsureDebugInfo(shared)) {
00913
00914 return;
00915 }
00916 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
00917
00918
00919 BreakLocationIterator it(debug_info, ALL_BREAK_LOCATIONS);
00920 it.FindBreakLocationFromAddress(frame->pc());
00921
00922
00923 bool is_call_target = false;
00924 if (RelocInfo::IsCodeTarget(it.rinfo()->rmode())) {
00925 Address target = it.rinfo()->target_address();
00926 Code* code = Debug::GetCodeTarget(target);
00927 if (code->is_call_stub()) is_call_target = true;
00928 }
00929
00930
00931 if (it.IsExit() || step_action == StepOut) {
00932
00933
00934 frames_it.Advance();
00935 if (!frames_it.done()) {
00936
00937 JSFunction* function = JSFunction::cast(frames_it.frame()->function());
00938 FloodWithOneShot(Handle<SharedFunctionInfo>(function->shared()));
00939 }
00940 } else if (!(is_call_target || RelocInfo::IsConstructCall(it.rmode())) ||
00941 step_action == StepNext || step_action == StepMin) {
00942
00943
00944
00945 FloodWithOneShot(shared);
00946
00947
00948 thread_local_.last_statement_position_ =
00949 debug_info->code()->SourceStatementPosition(frame->pc());
00950 thread_local_.last_fp_ = frame->fp();
00951 } else {
00952
00953
00954
00955 FloodWithOneShot(shared);
00956
00957
00958 it.PrepareStepIn();
00959 ActivateStepIn(frame);
00960 }
00961 }
00962
00963
00964
00965
00966
00967
00968
00969
00970 bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
00971 JavaScriptFrame* frame) {
00972
00973
00974 if (thread_local_.last_step_action_ == StepNext ||
00975 thread_local_.last_step_action_ == StepIn) {
00976
00977 if (break_location_iterator->IsExit()) return false;
00978
00979
00980 int current_statement_position =
00981 break_location_iterator->code()->SourceStatementPosition(frame->pc());
00982 return thread_local_.last_fp_ == frame->fp() &&
00983 thread_local_.last_statement_position_ == current_statement_position;
00984 }
00985
00986
00987 return false;
00988 }
00989
00990
00991
00992
00993 bool Debug::IsDebugBreak(Address addr) {
00994 Code* code = GetCodeTarget(addr);
00995 return code->ic_state() == DEBUG_BREAK;
00996 }
00997
00998
00999
01000
01001 bool Debug::IsSourceBreakStub(Code* code) {
01002 CodeStub::Major major_key = code->major_key();
01003 return major_key == CodeStub::CallFunction;
01004 }
01005
01006
01007
01008
01009 bool Debug::IsBreakStub(Code* code) {
01010 CodeStub::Major major_key = code->major_key();
01011 return major_key == CodeStub::CallFunction ||
01012 major_key == CodeStub::StackCheck;
01013 }
01014
01015
01016
01017 Handle<Code> Debug::FindDebugBreak(RelocInfo* rinfo) {
01018
01019
01020 RelocInfo::Mode mode = rinfo->rmode();
01021
01022 if (RelocInfo::IsCodeTarget(mode)) {
01023 Address target = rinfo->target_address();
01024 Code* code = Debug::GetCodeTarget(target);
01025 if (code->is_inline_cache_stub()) {
01026 if (code->is_call_stub()) {
01027 return ComputeCallDebugBreak(code->arguments_count());
01028 }
01029 if (code->is_load_stub()) {
01030 return Handle<Code>(Builtins::builtin(Builtins::LoadIC_DebugBreak));
01031 }
01032 if (code->is_store_stub()) {
01033 return Handle<Code>(Builtins::builtin(Builtins::StoreIC_DebugBreak));
01034 }
01035 if (code->is_keyed_load_stub()) {
01036 Handle<Code> result =
01037 Handle<Code>(Builtins::builtin(Builtins::KeyedLoadIC_DebugBreak));
01038 return result;
01039 }
01040 if (code->is_keyed_store_stub()) {
01041 Handle<Code> result =
01042 Handle<Code>(Builtins::builtin(Builtins::KeyedStoreIC_DebugBreak));
01043 return result;
01044 }
01045 }
01046 if (RelocInfo::IsConstructCall(mode)) {
01047 Handle<Code> result =
01048 Handle<Code>(Builtins::builtin(Builtins::ConstructCall_DebugBreak));
01049 return result;
01050 }
01051 if (code->kind() == Code::STUB) {
01052 ASSERT(code->major_key() == CodeStub::CallFunction ||
01053 code->major_key() == CodeStub::StackCheck);
01054 Handle<Code> result =
01055 Handle<Code>(Builtins::builtin(Builtins::StubNoRegisters_DebugBreak));
01056 return result;
01057 }
01058 }
01059
01060 UNREACHABLE();
01061 return Handle<Code>::null();
01062 }
01063
01064
01065
01066 Handle<Object> Debug::GetSourceBreakLocations(
01067 Handle<SharedFunctionInfo> shared) {
01068 if (!HasDebugInfo(shared)) return Handle<Object>(Heap::undefined_value());
01069 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
01070 if (debug_info->GetBreakPointCount() == 0) {
01071 return Handle<Object>(Heap::undefined_value());
01072 }
01073 Handle<FixedArray> locations =
01074 Factory::NewFixedArray(debug_info->GetBreakPointCount());
01075 int count = 0;
01076 for (int i = 0; i < debug_info->break_points()->length(); i++) {
01077 if (!debug_info->break_points()->get(i)->IsUndefined()) {
01078 BreakPointInfo* break_point_info =
01079 BreakPointInfo::cast(debug_info->break_points()->get(i));
01080 if (break_point_info->GetBreakPointCount() > 0) {
01081 locations->set(count++, break_point_info->statement_position());
01082 }
01083 }
01084 }
01085 return locations;
01086 }
01087
01088
01089 void Debug::ClearStepping() {
01090
01091 ClearOneShot();
01092 ClearStepIn();
01093 ClearStepNext();
01094
01095
01096 thread_local_.step_count_ = 0;
01097 }
01098
01099
01100
01101
01102 void Debug::ClearOneShot() {
01103
01104
01105
01106
01107 DebugInfoListNode* node = debug_info_list_;
01108 while (node != NULL) {
01109 BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
01110 while (!it.Done()) {
01111 it.ClearOneShot();
01112 it.Next();
01113 }
01114 node = node->next();
01115 }
01116 }
01117
01118
01119 void Debug::ActivateStepIn(StackFrame* frame) {
01120 thread_local_.step_into_fp_ = frame->fp();
01121 }
01122
01123
01124 void Debug::ClearStepIn() {
01125 thread_local_.step_into_fp_ = 0;
01126 }
01127
01128
01129 void Debug::ClearStepNext() {
01130 thread_local_.last_step_action_ = StepNone;
01131 thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
01132 thread_local_.last_fp_ = 0;
01133 }
01134
01135
01136 bool Debug::EnsureCompiled(Handle<SharedFunctionInfo> shared) {
01137 if (shared->is_compiled()) return true;
01138 return CompileLazyShared(shared, CLEAR_EXCEPTION);
01139 }
01140
01141
01142
01143 bool Debug::EnsureDebugInfo(Handle<SharedFunctionInfo> shared) {
01144
01145 if (HasDebugInfo(shared)) return true;
01146
01147
01148 if (!EnsureCompiled(shared)) return false;
01149
01150
01151 Handle<DebugInfo> debug_info = Factory::NewDebugInfo(shared);
01152
01153
01154 DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
01155 node->set_next(debug_info_list_);
01156 debug_info_list_ = node;
01157
01158
01159 has_break_points_ = true;
01160
01161 return true;
01162 }
01163
01164
01165 void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
01166 ASSERT(debug_info_list_ != NULL);
01167
01168 DebugInfoListNode* prev = NULL;
01169 DebugInfoListNode* current = debug_info_list_;
01170 while (current != NULL) {
01171 if (*current->debug_info() == *debug_info) {
01172
01173 if (prev == NULL) {
01174 debug_info_list_ = current->next();
01175 } else {
01176 prev->set_next(current->next());
01177 }
01178 current->debug_info()->shared()->set_debug_info(Heap::undefined_value());
01179 delete current;
01180
01181
01182
01183 has_break_points_ = debug_info_list_ != NULL;
01184
01185 return;
01186 }
01187
01188 prev = current;
01189 current = current->next();
01190 }
01191 UNREACHABLE();
01192 }
01193
01194
01195 void Debug::SetAfterBreakTarget(JavaScriptFrame* frame) {
01196
01197 Handle<SharedFunctionInfo> shared =
01198 Handle<SharedFunctionInfo>(JSFunction::cast(frame->function())->shared());
01199 if (!EnsureDebugInfo(shared)) {
01200
01201 return;
01202 }
01203 Handle<DebugInfo> debug_info = GetDebugInfo(shared);
01204 Handle<Code> code(debug_info->code());
01205 Handle<Code> original_code(debug_info->original_code());
01206 #ifdef DEBUG
01207
01208 Handle<Code> frame_code(frame->FindCode());
01209 ASSERT(frame_code.is_identical_to(code));
01210 #endif
01211
01212
01213
01214
01215 Address addr = frame->pc() - Assembler::kTargetAddrToReturnAddrDist;
01216
01217
01218 bool at_js_exit = false;
01219 RelocIterator it(debug_info->code());
01220 while (!it.done()) {
01221 if (RelocInfo::IsJSReturn(it.rinfo()->rmode())) {
01222 at_js_exit = it.rinfo()->pc() == addr - 1;
01223 }
01224 it.next();
01225 }
01226
01227
01228
01229 if (at_js_exit) {
01230
01231
01232
01233 if (Assembler::target_address_at(addr) ==
01234 debug_break_return_entry()->entry()) {
01235
01236
01237 addr += original_code->instruction_start() - code->instruction_start();
01238 }
01239
01240
01241 thread_local_.after_break_target_ = addr - 1;
01242 } else {
01243
01244
01245
01246
01247
01248
01249
01250 if (IsDebugBreak(Assembler::target_address_at(addr))) {
01251
01252
01253
01254
01255 addr += original_code->instruction_start() - code->instruction_start();
01256 }
01257
01258
01259
01260 thread_local_.after_break_target_ = Assembler::target_address_at(addr);
01261 }
01262 }
01263
01264
01265 Code* Debug::GetCodeTarget(Address target) {
01266
01267 Code* result =
01268 Code::cast(HeapObject::FromAddress(target - Code::kHeaderSize));
01269 return result;
01270 }
01271
01272
01273 bool Debug::IsDebugGlobal(GlobalObject* global) {
01274 return IsLoaded() && global == Debug::debug_context()->global();
01275 }
01276
01277
01278 bool Debugger::debugger_active_ = false;
01279 bool Debugger::compiling_natives_ = false;
01280 bool Debugger::is_loading_debugger_ = false;
01281 DebugMessageThread* Debugger::message_thread_ = NULL;
01282 v8::DebugMessageHandler Debugger::debug_message_handler_ = NULL;
01283 void* Debugger::debug_message_handler_data_ = NULL;
01284
01285
01286 Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
01287 int argc, Object*** argv,
01288 bool* caught_exception) {
01289 ASSERT(Top::context() == *Debug::debug_context());
01290
01291
01292 Handle<String> constructor_str = Factory::LookupSymbol(constructor_name);
01293 Handle<Object> constructor(Top::global()->GetProperty(*constructor_str));
01294 ASSERT(constructor->IsJSFunction());
01295 if (!constructor->IsJSFunction()) {
01296 *caught_exception = true;
01297 return Factory::undefined_value();
01298 }
01299 Handle<Object> js_object = Execution::TryCall(
01300 Handle<JSFunction>::cast(constructor),
01301 Handle<JSObject>(Debug::debug_context()->global()), argc, argv,
01302 caught_exception);
01303 return js_object;
01304 }
01305
01306
01307 Handle<Object> Debugger::MakeExecutionState(bool* caught_exception) {
01308
01309 Handle<Object> break_id = Factory::NewNumberFromInt(Top::break_id());
01310 const int argc = 1;
01311 Object** argv[argc] = { break_id.location() };
01312 return MakeJSObject(CStrVector("MakeExecutionState"),
01313 argc, argv, caught_exception);
01314 }
01315
01316
01317 Handle<Object> Debugger::MakeBreakEvent(Handle<Object> exec_state,
01318 Handle<Object> break_points_hit,
01319 bool* caught_exception) {
01320
01321 const int argc = 2;
01322 Object** argv[argc] = { exec_state.location(),
01323 break_points_hit.location() };
01324 return MakeJSObject(CStrVector("MakeBreakEvent"),
01325 argc,
01326 argv,
01327 caught_exception);
01328 }
01329
01330
01331 Handle<Object> Debugger::MakeExceptionEvent(Handle<Object> exec_state,
01332 Handle<Object> exception,
01333 bool uncaught,
01334 bool* caught_exception) {
01335
01336 const int argc = 3;
01337 Object** argv[argc] = { exec_state.location(),
01338 exception.location(),
01339 uncaught ? Factory::true_value().location() :
01340 Factory::false_value().location()};
01341 return MakeJSObject(CStrVector("MakeExceptionEvent"),
01342 argc, argv, caught_exception);
01343 }
01344
01345
01346 Handle<Object> Debugger::MakeNewFunctionEvent(Handle<Object> function,
01347 bool* caught_exception) {
01348
01349 const int argc = 1;
01350 Object** argv[argc] = { function.location() };
01351 return MakeJSObject(CStrVector("MakeNewFunctionEvent"),
01352 argc, argv, caught_exception);
01353 }
01354
01355
01356 Handle<Object> Debugger::MakeCompileEvent(Handle<Script> script,
01357 Handle<Object> script_function,
01358 bool* caught_exception) {
01359
01360 Handle<Object> exec_state = MakeExecutionState(caught_exception);
01361 Handle<Object> script_source(script->source());
01362 Handle<Object> script_name(script->name());
01363 const int argc = 3;
01364 Object** argv[argc] = { script_source.location(),
01365 script_name.location(),
01366 script_function.location() };
01367 return MakeJSObject(CStrVector("MakeCompileEvent"),
01368 argc,
01369 argv,
01370 caught_exception);
01371 }
01372
01373
01374 Handle<String> Debugger::ProcessRequest(Handle<Object> exec_state,
01375 Handle<Object> request,
01376 bool stopped) {
01377
01378 Handle<JSFunction> process_denbug_request =
01379 Handle<JSFunction>(JSFunction::cast(
01380 Debug::debug_context()->global()->GetProperty(
01381 *Factory::LookupAsciiSymbol("ProcessDebugRequest"))));
01382
01383
01384
01385 bool caught_exception;
01386 const int argc = 3;
01387 Object** argv[argc] = { exec_state.location(),
01388 request.location(),
01389 stopped ? Factory::true_value().location() :
01390 Factory::false_value().location()};
01391 Handle<Object> result = Execution::TryCall(process_denbug_request,
01392 Factory::undefined_value(),
01393 argc, argv,
01394 &caught_exception);
01395 if (caught_exception) {
01396 return Factory::empty_symbol();
01397 }
01398
01399 return Handle<String>::cast(result);
01400 }
01401
01402
01403 void Debugger::OnException(Handle<Object> exception, bool uncaught) {
01404 HandleScope scope;
01405
01406
01407 if (Debug::InDebugger()) return;
01408 if (!Debugger::EventActive(v8::Exception)) return;
01409
01410
01411 if (uncaught) {
01412
01413 if (!(Debug::break_on_uncaught_exception() ||
01414 Debug::break_on_exception())) return;
01415 } else {
01416
01417 if (!Debug::break_on_exception()) return;
01418 }
01419
01420
01421 EnterDebugger debugger;
01422 if (debugger.FailedToEnter()) return;
01423
01424
01425 Debug::ClearStepping();
01426
01427 bool caught_exception = false;
01428 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
01429 Handle<Object> event_data;
01430 if (!caught_exception) {
01431 event_data = MakeExceptionEvent(exec_state, exception, uncaught,
01432 &caught_exception);
01433 }
01434
01435 if (caught_exception) {
01436 return;
01437 }
01438
01439
01440 ProcessDebugEvent(v8::Exception, event_data);
01441
01442 }
01443
01444
01445 void Debugger::OnDebugBreak(Handle<Object> break_points_hit) {
01446 HandleScope scope;
01447
01448
01449 ASSERT(Top::context() == *Debug::debug_context());
01450
01451
01452 if (!Debugger::EventActive(v8::Break)) return;
01453
01454
01455 ASSERT(Top::context() == *Debug::debug_context());
01456
01457
01458 bool caught_exception = false;
01459 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
01460 Handle<Object> event_data;
01461 if (!caught_exception) {
01462 event_data = MakeBreakEvent(exec_state, break_points_hit,
01463 &caught_exception);
01464 }
01465
01466 if (caught_exception) {
01467 return;
01468 }
01469
01470
01471 ProcessDebugEvent(v8::Break, event_data);
01472 }
01473
01474
01475 void Debugger::OnBeforeCompile(Handle<Script> script) {
01476 HandleScope scope;
01477
01478
01479 if (Debug::InDebugger()) return;
01480 if (compiling_natives()) return;
01481 if (!EventActive(v8::BeforeCompile)) return;
01482
01483
01484 EnterDebugger debugger;
01485 if (debugger.FailedToEnter()) return;
01486
01487
01488 bool caught_exception = false;
01489 Handle<Object> event_data = MakeCompileEvent(script,
01490 Factory::undefined_value(),
01491 &caught_exception);
01492
01493 if (caught_exception) {
01494 return;
01495 }
01496
01497
01498 ProcessDebugEvent(v8::BeforeCompile, event_data);
01499 }
01500
01501
01502
01503 void Debugger::OnAfterCompile(Handle<Script> script, Handle<JSFunction> fun) {
01504 HandleScope scope;
01505
01506
01507 if (compiling_natives()) return;
01508
01509
01510 if (!debugger_active()) return;
01511
01512
01513 EnterDebugger debugger;
01514 if (debugger.FailedToEnter()) return;
01515
01516
01517
01518
01519
01520 Handle<Object> update_script_break_points =
01521 Handle<Object>(Debug::debug_context()->global()->GetProperty(
01522 *Factory::LookupAsciiSymbol("UpdateScriptBreakPoints")));
01523 if (!update_script_break_points->IsJSFunction()) {
01524 return;
01525 }
01526 ASSERT(update_script_break_points->IsJSFunction());
01527
01528
01529
01530 Handle<JSValue> wrapper = GetScriptWrapper(script);
01531
01532
01533 bool caught_exception = false;
01534 const int argc = 1;
01535 Object** argv[argc] = { reinterpret_cast<Object**>(wrapper.location()) };
01536 Handle<Object> result = Execution::TryCall(
01537 Handle<JSFunction>::cast(update_script_break_points),
01538 Top::builtins(), argc, argv,
01539 &caught_exception);
01540 if (caught_exception) {
01541 return;
01542 }
01543
01544 if (Debug::InDebugger()) return;
01545 if (!Debugger::EventActive(v8::AfterCompile)) return;
01546
01547
01548 Handle<Object> event_data = MakeCompileEvent(script,
01549 Factory::undefined_value(),
01550 &caught_exception);
01551
01552 if (caught_exception) {
01553 return;
01554 }
01555
01556 ProcessDebugEvent(v8::AfterCompile, event_data);
01557 }
01558
01559
01560 void Debugger::OnNewFunction(Handle<JSFunction> function) {
01561 return;
01562 HandleScope scope;
01563
01564
01565 if (Debug::InDebugger()) return;
01566 if (compiling_natives()) return;
01567 if (!Debugger::EventActive(v8::NewFunction)) return;
01568
01569
01570 EnterDebugger debugger;
01571 if (debugger.FailedToEnter()) return;
01572
01573
01574 bool caught_exception = false;
01575 Handle<Object> event_data = MakeNewFunctionEvent(function, &caught_exception);
01576
01577 if (caught_exception) {
01578 return;
01579 }
01580
01581 ProcessDebugEvent(v8::NewFunction, event_data);
01582 }
01583
01584
01585 void Debugger::ProcessDebugEvent(v8::DebugEvent event,
01586 Handle<Object> event_data) {
01587
01588 bool caught_exception = false;
01589 Handle<Object> exec_state = MakeExecutionState(&caught_exception);
01590 if (caught_exception) {
01591 return;
01592 }
01593
01594 if (message_thread_ != NULL) {
01595 message_thread_->DebugEvent(event, exec_state, event_data);
01596 }
01597
01598
01599 v8::NeanderArray listeners(Factory::debug_event_listeners());
01600 int length = listeners.length();
01601 for (int i = 0; i < length; i++) {
01602 if (listeners.get(i)->IsUndefined()) continue;
01603 v8::NeanderObject listener(JSObject::cast(listeners.get(i)));
01604 Handle<Object> callback_data(listener.get(1));
01605 if (listener.get(0)->IsProxy()) {
01606
01607 Handle<Proxy> callback_obj(Proxy::cast(listener.get(0)));
01608 v8::DebugEventCallback callback =
01609 FUNCTION_CAST<v8::DebugEventCallback>(callback_obj->proxy());
01610 callback(event,
01611 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
01612 v8::Utils::ToLocal(Handle<JSObject>::cast(event_data)),
01613 v8::Utils::ToLocal(callback_data));
01614 } else {
01615
01616 ASSERT(listener.get(0)->IsJSFunction());
01617 Handle<JSFunction> fun(JSFunction::cast(listener.get(0)));
01618
01619
01620 const int argc = 4;
01621 Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(),
01622 exec_state.location(),
01623 event_data.location(),
01624 callback_data.location() };
01625 Handle<Object> result = Execution::TryCall(fun, Top::global(),
01626 argc, argv, &caught_exception);
01627 if (caught_exception) {
01628
01629 }
01630 }
01631 }
01632 }
01633
01634
01635 void Debugger::SetMessageHandler(v8::DebugMessageHandler handler, void* data) {
01636 debug_message_handler_ = handler;
01637 debug_message_handler_data_ = data;
01638 if (!message_thread_) {
01639 message_thread_ = new DebugMessageThread();
01640 message_thread_->Start();
01641 }
01642 UpdateActiveDebugger();
01643 }
01644
01645
01646
01647
01648
01649
01650 void Debugger::SendMessage(Vector< uint16_t> message) {
01651 if (debug_message_handler_ != NULL) {
01652 debug_message_handler_(message.start(), message.length(),
01653 debug_message_handler_data_);
01654 }
01655 }
01656
01657
01658 void Debugger::ProcessCommand(Vector<const uint16_t> command) {
01659 if (message_thread_ != NULL) {
01660 message_thread_->ProcessCommand(
01661 Vector<uint16_t>(const_cast<uint16_t *>(command.start()),
01662 command.length()));
01663 }
01664 }
01665
01666
01667 void Debugger::UpdateActiveDebugger() {
01668 v8::NeanderArray listeners(Factory::debug_event_listeners());
01669 int length = listeners.length();
01670 bool active_listener = false;
01671 for (int i = 0; i < length && !active_listener; i++) {
01672 active_listener = !listeners.get(i)->IsUndefined();
01673 }
01674 set_debugger_active((Debugger::message_thread_ != NULL &&
01675 Debugger::debug_message_handler_ != NULL) ||
01676 active_listener);
01677 if (!debugger_active() && message_thread_)
01678 message_thread_->OnDebuggerInactive();
01679 }
01680
01681
01682 DebugMessageThread::DebugMessageThread()
01683 : host_running_(true),
01684 command_queue_(kQueueInitialSize),
01685 message_queue_(kQueueInitialSize) {
01686 command_received_ = OS::CreateSemaphore(0);
01687 message_received_ = OS::CreateSemaphore(0);
01688 }
01689
01690
01691
01692 DebugMessageThread::~DebugMessageThread() {
01693 }
01694
01695
01696
01697
01698
01699
01700 void DebugMessageThread::SendMessage(Vector<uint16_t> message) {
01701 Vector<uint16_t> message_copy = message.Clone();
01702 Logger::DebugTag("Put message on event message_queue.");
01703 message_queue_.Put(message_copy);
01704 message_received_->Signal();
01705 }
01706
01707
01708 void DebugMessageThread::SetEventJSONFromEvent(Handle<Object> event_data) {
01709 v8::HandleScope scope;
01710
01711 v8::Local<v8::Object> api_event_data =
01712 v8::Utils::ToLocal(Handle<JSObject>::cast(event_data));
01713 v8::Local<v8::String> fun_name = v8::String::New("toJSONProtocol");
01714 v8::Local<v8::Function> fun =
01715 v8::Function::Cast(*api_event_data->Get(fun_name));
01716 v8::TryCatch try_catch;
01717 v8::Local<v8::Value> json_event = *fun->Call(api_event_data, 0, NULL);
01718 v8::Local<v8::String> json_event_string;
01719 if (!try_catch.HasCaught()) {
01720 if (!json_event->IsUndefined()) {
01721 json_event_string = json_event->ToString();
01722 if (FLAG_trace_debug_json) {
01723 PrintLn(json_event_string);
01724 }
01725 v8::String::Value val(json_event_string);
01726 Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
01727 json_event_string->Length());
01728 SendMessage(str);
01729 } else {
01730 SendMessage(Vector<uint16_t>::empty());
01731 }
01732 } else {
01733 PrintLn(try_catch.Exception());
01734 SendMessage(Vector<uint16_t>::empty());
01735 }
01736 }
01737
01738
01739 void DebugMessageThread::Run() {
01740
01741 while (true) {
01742
01743 message_received_->Wait();
01744 Logger::DebugTag("Get message from event message_queue.");
01745 Vector<uint16_t> message = message_queue_.Get();
01746 if (message.length() > 0) {
01747 Debugger::SendMessage(message);
01748 }
01749 }
01750 }
01751
01752
01753
01754
01755 void DebugMessageThread::DebugEvent(v8::DebugEvent event,
01756 Handle<Object> exec_state,
01757 Handle<Object> event_data) {
01758 if (!Debug::Load()) return;
01759
01760
01761 bool interactive = false;
01762 switch (event) {
01763 case v8::Break:
01764 interactive = true;
01765 break;
01766 case v8::Exception:
01767 interactive = true;
01768 break;
01769 case v8::BeforeCompile:
01770 break;
01771 case v8::AfterCompile:
01772 break;
01773 case v8::NewFunction:
01774 break;
01775 default:
01776 UNREACHABLE();
01777 }
01778
01779
01780 if (!interactive) return;
01781
01782
01783 v8::Local<v8::Object> api_exec_state =
01784 v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state));
01785 v8::Local<v8::String> fun_name =
01786 v8::String::New("debugCommandProcessor");
01787 v8::Local<v8::Function> fun =
01788 v8::Function::Cast(*api_exec_state->Get(fun_name));
01789 v8::TryCatch try_catch;
01790 v8::Local<v8::Object> cmd_processor =
01791 v8::Object::Cast(*fun->Call(api_exec_state, 0, NULL));
01792 if (try_catch.HasCaught()) {
01793 PrintLn(try_catch.Exception());
01794 return;
01795 }
01796
01797
01798 host_running_ = false;
01799 SetEventJSONFromEvent(event_data);
01800
01801
01802 while (true) {
01803 command_received_->Wait();
01804 Logger::DebugTag("Get command from command queue, in interactive loop.");
01805 Vector<uint16_t> command = command_queue_.Get();
01806 ASSERT(!host_running_);
01807 if (!Debugger::debugger_active()) {
01808 host_running_ = true;
01809 return;
01810 }
01811
01812
01813
01814
01815 v8::Local<v8::String> fun_name;
01816 v8::Local<v8::Function> fun;
01817 v8::Local<v8::Value> args[1];
01818 v8::TryCatch try_catch;
01819 fun_name = v8::String::New("processDebugCommand");
01820 fun = v8::Function::Cast(*cmd_processor->Get(fun_name));
01821 args[0] = v8::String::New(reinterpret_cast<uint16_t*>(command.start()),
01822 command.length());
01823 v8::Local<v8::Value> result_val = fun->Call(cmd_processor, 1, args);
01824
01825
01826 v8::Local<v8::String> result_string;
01827 bool running = false;
01828 if (!try_catch.HasCaught()) {
01829
01830 v8::Local<v8::Object> result = v8::Object::Cast(*result_val);
01831
01832
01833 if (FLAG_trace_debug_json) {
01834 PrintLn(result->Get(v8::String::New("request")));
01835 PrintLn(result->Get(v8::String::New("response")));
01836 }
01837
01838
01839 running = result->Get(v8::String::New("running"))->ToBoolean()->Value();
01840
01841
01842 v8::Local<v8::Value> text_result =
01843 result->Get(v8::String::New("response"));
01844 if (!text_result->IsUndefined()) {
01845 result_string = text_result->ToString();
01846 } else {
01847 result_string = v8::String::New("");
01848 }
01849 } else {
01850
01851 result_string = try_catch.Exception()->ToString();
01852 }
01853
01854
01855 v8::String::Value val(result_string);
01856 Vector<uint16_t> str(reinterpret_cast<uint16_t*>(*val),
01857 result_string->Length());
01858
01859
01860 host_running_ = running;
01861
01862
01863 SendMessage(str);
01864
01865
01866 if (running) {
01867 return;
01868 }
01869 }
01870 }
01871
01872
01873
01874
01875
01876
01877
01878
01879 void DebugMessageThread::ProcessCommand(Vector<uint16_t> command) {
01880 Vector<uint16_t> command_copy = command.Clone();
01881 Logger::DebugTag("Put command on command_queue.");
01882 command_queue_.Put(command_copy);
01883 command_received_->Signal();
01884 }
01885
01886
01887 void DebugMessageThread::OnDebuggerInactive() {
01888
01889
01890 if (!host_running_) {
01891 ProcessCommand(Vector<uint16_t>::empty());
01892 }
01893 }
01894
01895
01896 MessageQueue::MessageQueue(int size) : start_(0), end_(0), size_(size) {
01897 messages_ = NewArray<Vector<uint16_t> >(size);
01898 }
01899
01900
01901 MessageQueue::~MessageQueue() {
01902 DeleteArray(messages_);
01903 }
01904
01905
01906 Vector<uint16_t> MessageQueue::Get() {
01907 ASSERT(!IsEmpty());
01908 int result = start_;
01909 start_ = (start_ + 1) % size_;
01910 return messages_[result];
01911 }
01912
01913
01914 void MessageQueue::Put(const Vector<uint16_t>& message) {
01915 if ((end_ + 1) % size_ == start_) {
01916 Expand();
01917 }
01918 messages_[end_] = message;
01919 end_ = (end_ + 1) % size_;
01920 }
01921
01922
01923 void MessageQueue::Expand() {
01924 MessageQueue new_queue(size_ * 2);
01925 while (!IsEmpty()) {
01926 new_queue.Put(Get());
01927 }
01928 Vector<uint16_t>* array_to_free = messages_;
01929 *this = new_queue;
01930 new_queue.messages_ = array_to_free;
01931
01932 }
01933
01934
01935 LockingMessageQueue::LockingMessageQueue(int size) : queue_(size) {
01936 lock_ = OS::CreateMutex();
01937 }
01938
01939
01940 LockingMessageQueue::~LockingMessageQueue() {
01941 delete lock_;
01942 }
01943
01944
01945 bool LockingMessageQueue::IsEmpty() const {
01946 ScopedLock sl(lock_);
01947 return queue_.IsEmpty();
01948 }
01949
01950
01951 Vector<uint16_t> LockingMessageQueue::Get() {
01952 ScopedLock sl(lock_);
01953 Vector<uint16_t> result = queue_.Get();
01954 Logger::DebugEvent("Get", result);
01955 return result;
01956 }
01957
01958
01959 void LockingMessageQueue::Put(const Vector<uint16_t>& message) {
01960 ScopedLock sl(lock_);
01961 queue_.Put(message);
01962 Logger::DebugEvent("Put", message);
01963 }
01964
01965
01966 void LockingMessageQueue::Clear() {
01967 ScopedLock sl(lock_);
01968 queue_.Clear();
01969 }
01970
01971
01972 } }