| Index: src/debug.cc
|
| ===================================================================
|
| --- src/debug.cc (revision 3427)
|
| +++ src/debug.cc (working copy)
|
| @@ -503,38 +503,42 @@
|
| #endif
|
| }
|
|
|
| +DebugData::DebugData()
|
| + :has_break_points_(false),
|
| + script_cache_(NULL),
|
| + debug_info_list_(NULL),
|
| + disable_break_(false),
|
| + break_on_exception_(false),
|
| + break_on_uncaught_exception_(true),
|
| + debug_context_(Handle<Context>()),
|
| + debug_break_return_(NULL) {
|
| +}
|
|
|
| -bool Debug::has_break_points_ = false;
|
| -ScriptCache* Debug::script_cache_ = NULL;
|
| -DebugInfoListNode* Debug::debug_info_list_ = NULL;
|
| -
|
| -
|
| // Threading support.
|
| void Debug::ThreadInit() {
|
| - thread_local_.break_count_ = 0;
|
| - thread_local_.break_id_ = 0;
|
| - thread_local_.break_frame_id_ = StackFrame::NO_ID;
|
| - thread_local_.last_step_action_ = StepNone;
|
| - thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
|
| - thread_local_.step_count_ = 0;
|
| - thread_local_.last_fp_ = 0;
|
| - thread_local_.step_into_fp_ = 0;
|
| - thread_local_.step_out_fp_ = 0;
|
| - thread_local_.after_break_target_ = 0;
|
| - thread_local_.debugger_entry_ = NULL;
|
| - thread_local_.pending_interrupts_ = 0;
|
| + ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_;
|
| + thread_local.break_count_ = 0;
|
| + thread_local.break_id_ = 0;
|
| + thread_local.break_frame_id_ = StackFrame::NO_ID;
|
| + thread_local.last_step_action_ = StepNone;
|
| + thread_local.last_statement_position_ = RelocInfo::kNoPosition;
|
| + thread_local.step_count_ = 0;
|
| + thread_local.last_fp_ = 0;
|
| + thread_local.step_into_fp_ = 0;
|
| + thread_local.step_out_fp_ = 0;
|
| + thread_local.after_break_target_ = 0;
|
| + thread_local.debugger_entry_ = NULL;
|
| + thread_local.pending_interrupts_ = 0;
|
| }
|
|
|
| -
|
| -JSCallerSavedBuffer Debug::registers_;
|
| -Debug::ThreadLocal Debug::thread_local_;
|
| -
|
| -
|
| char* Debug::ArchiveDebug(char* storage) {
|
| char* to = storage;
|
| - memcpy(to, reinterpret_cast<char*>(&thread_local_), sizeof(ThreadLocal));
|
| + DebugData& data = v8_context()->debug_data_;
|
| + memcpy(to, reinterpret_cast<char*>(&data.thread_local_),
|
| + sizeof(ThreadLocal));
|
| to += sizeof(ThreadLocal);
|
| - memcpy(to, reinterpret_cast<char*>(®isters_), sizeof(registers_));
|
| + memcpy(to, reinterpret_cast<char*>(&data.registers_),
|
| + sizeof(JSCallerSavedBuffer));
|
| ThreadInit();
|
| ASSERT(to <= storage + ArchiveSpacePerThread());
|
| return storage + ArchiveSpacePerThread();
|
| @@ -543,30 +547,21 @@
|
|
|
| char* Debug::RestoreDebug(char* storage) {
|
| char* from = storage;
|
| - memcpy(reinterpret_cast<char*>(&thread_local_), from, sizeof(ThreadLocal));
|
| + DebugData& data = v8_context()->debug_data_;
|
| + memcpy(reinterpret_cast<char*>(&data.thread_local_), from,
|
| + sizeof(ThreadLocal));
|
| from += sizeof(ThreadLocal);
|
| - memcpy(reinterpret_cast<char*>(®isters_), from, sizeof(registers_));
|
| + memcpy(reinterpret_cast<char*>(&data.registers_), from,
|
| + sizeof(JSCallerSavedBuffer));
|
| ASSERT(from <= storage + ArchiveSpacePerThread());
|
| return storage + ArchiveSpacePerThread();
|
| }
|
|
|
|
|
| int Debug::ArchiveSpacePerThread() {
|
| - return sizeof(ThreadLocal) + sizeof(registers_);
|
| + return sizeof(ThreadLocal) + sizeof(JSCallerSavedBuffer);
|
| }
|
|
|
| -
|
| -// Default break enabled.
|
| -bool Debug::disable_break_ = false;
|
| -
|
| -// Default call debugger on uncaught exception.
|
| -bool Debug::break_on_exception_ = false;
|
| -bool Debug::break_on_uncaught_exception_ = true;
|
| -
|
| -Handle<Context> Debug::debug_context_ = Handle<Context>();
|
| -Code* Debug::debug_break_return_ = NULL;
|
| -
|
| -
|
| void ScriptCache::Add(Handle<Script> script) {
|
| // Create an entry in the hash map for the script.
|
| int id = Smi::cast(script->id())->value();
|
| @@ -644,10 +639,11 @@
|
| void Debug::Setup(bool create_heap_objects) {
|
| ThreadInit();
|
| if (create_heap_objects) {
|
| + DebugData& data = v8_context()->debug_data_;
|
| // Get code to handle debug break on return.
|
| - debug_break_return_ =
|
| + data.debug_break_return_ =
|
| Builtins::builtin(Builtins::Return_DebugBreak);
|
| - ASSERT(debug_break_return_->IsCode());
|
| + ASSERT(data.debug_break_return_->IsCode());
|
| }
|
| }
|
|
|
| @@ -656,7 +652,7 @@
|
| DebugInfoListNode* node = reinterpret_cast<DebugInfoListNode*>(data);
|
| RemoveDebugInfo(node->debug_info());
|
| #ifdef DEBUG
|
| - node = Debug::debug_info_list_;
|
| + node = v8_context()->debug_data_.debug_info_list_;
|
| while (node != NULL) {
|
| ASSERT(node != reinterpret_cast<DebugInfoListNode*>(data));
|
| node = node->next();
|
| @@ -776,7 +772,8 @@
|
| if (caught_exception) return false;
|
|
|
| // Debugger loaded.
|
| - debug_context_ = Handle<Context>::cast(GlobalHandles::Create(*context));
|
| + v8_context()->debug_data_.debug_context_ =
|
| + Handle<Context>::cast(GlobalHandles::Create(*context));
|
|
|
| return true;
|
| }
|
| @@ -791,9 +788,11 @@
|
| // Clear the script cache.
|
| DestroyScriptCache();
|
|
|
| + DebugData& data = v8_context()->debug_data_;
|
| // Clear debugger context global handle.
|
| - GlobalHandles::Destroy(reinterpret_cast<Object**>(debug_context_.location()));
|
| - debug_context_ = Handle<Context>();
|
| + GlobalHandles::Destroy(
|
| + reinterpret_cast<Object**>(data.debug_context_.location()));
|
| + data.debug_context_ = Handle<Context>();
|
| }
|
|
|
|
|
| @@ -805,7 +804,8 @@
|
|
|
|
|
| void Debug::Iterate(ObjectVisitor* v) {
|
| - v->VisitPointer(bit_cast<Object**, Code**>(&(debug_break_return_)));
|
| + v->VisitPointer(bit_cast<Object**, Code**>(
|
| + &(v8_context()->debug_data_.debug_break_return_)));
|
| }
|
|
|
|
|
| @@ -841,12 +841,13 @@
|
| BreakLocationIterator break_location_iterator(debug_info,
|
| ALL_BREAK_LOCATIONS);
|
| break_location_iterator.FindBreakLocationFromAddress(frame->pc());
|
| + ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_;
|
|
|
| // Check whether step next reached a new statement.
|
| if (!StepNextContinue(&break_location_iterator, frame)) {
|
| // Decrease steps left if performing multiple steps.
|
| - if (thread_local_.step_count_ > 0) {
|
| - thread_local_.step_count_--;
|
| + if (thread_local.step_count_ > 0) {
|
| + thread_local.step_count_--;
|
| }
|
| }
|
|
|
| @@ -864,10 +865,10 @@
|
| if (Debug::StepOutActive() && frame->fp() != Debug::step_out_fp() &&
|
| break_points_hit->IsUndefined() ) {
|
| // Step count should always be 0 for StepOut.
|
| - ASSERT(thread_local_.step_count_ == 0);
|
| + ASSERT(thread_local.step_count_ == 0);
|
| } else if (!break_points_hit->IsUndefined() ||
|
| - (thread_local_.last_step_action_ != StepNone &&
|
| - thread_local_.step_count_ == 0)) {
|
| + (thread_local.last_step_action_ != StepNone &&
|
| + thread_local.step_count_ == 0)) {
|
| // Notify debugger if a real break point is triggered or if performing
|
| // single stepping with no more steps to perform. Otherwise do another step.
|
|
|
| @@ -876,11 +877,11 @@
|
|
|
| // Notify the debug event listeners.
|
| Debugger::OnDebugBreak(break_points_hit, false);
|
| - } else if (thread_local_.last_step_action_ != StepNone) {
|
| + } else if (thread_local.last_step_action_ != StepNone) {
|
| // Hold on to last step action as it is cleared by the call to
|
| // ClearStepping.
|
| - StepAction step_action = thread_local_.last_step_action_;
|
| - int step_count = thread_local_.step_count_;
|
| + StepAction step_action = thread_local.last_step_action_;
|
| + int step_count = thread_local.step_count_;
|
|
|
| // Clear all current stepping setup.
|
| ClearStepping();
|
| @@ -1006,7 +1007,8 @@
|
| void Debug::ClearBreakPoint(Handle<Object> break_point_object) {
|
| HandleScope scope;
|
|
|
| - DebugInfoListNode* node = debug_info_list_;
|
| + DebugData& data = v8_context()->debug_data_;
|
| + DebugInfoListNode* node = data.debug_info_list_;
|
| while (node != NULL) {
|
| Object* result = DebugInfo::FindBreakPointInfo(node->debug_info(),
|
| break_point_object);
|
| @@ -1039,7 +1041,8 @@
|
|
|
|
|
| void Debug::ClearAllBreakPoints() {
|
| - DebugInfoListNode* node = debug_info_list_;
|
| + DebugData& data = v8_context()->debug_data_;
|
| + DebugInfoListNode* node = data.debug_info_list_;
|
| while (node != NULL) {
|
| // Remove all debug break code.
|
| BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
|
| @@ -1048,8 +1051,8 @@
|
| }
|
|
|
| // Remove all debug info.
|
| - while (debug_info_list_ != NULL) {
|
| - RemoveDebugInfo(debug_info_list_->debug_info());
|
| + while (data.debug_info_list_ != NULL) {
|
| + RemoveDebugInfo(data.debug_info_list_->debug_info());
|
| }
|
| }
|
|
|
| @@ -1092,10 +1095,11 @@
|
|
|
|
|
| void Debug::ChangeBreakOnException(ExceptionBreakType type, bool enable) {
|
| + DebugData& data = v8_context()->debug_data_;
|
| if (type == BreakUncaughtException) {
|
| - break_on_uncaught_exception_ = enable;
|
| + data.break_on_uncaught_exception_ = enable;
|
| } else {
|
| - break_on_exception_ = enable;
|
| + data.break_on_exception_ = enable;
|
| }
|
| }
|
|
|
| @@ -1103,15 +1107,16 @@
|
| void Debug::PrepareStep(StepAction step_action, int step_count) {
|
| HandleScope scope;
|
| ASSERT(Debug::InDebugger());
|
| + ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_;
|
|
|
| // Remember this step action and count.
|
| - thread_local_.last_step_action_ = step_action;
|
| + thread_local.last_step_action_ = step_action;
|
| if (step_action == StepOut) {
|
| // For step out target frame will be found on the stack so there is no need
|
| // to set step counter for it. It's expected to always be 0 for StepOut.
|
| - thread_local_.step_count_ = 0;
|
| + thread_local.step_count_ = 0;
|
| } else {
|
| - thread_local_.step_count_ = step_count;
|
| + thread_local.step_count_ = step_count;
|
| }
|
|
|
| // Get the frame where the execution has stopped and skip the debug frame if
|
| @@ -1223,9 +1228,9 @@
|
| FloodWithOneShot(shared);
|
|
|
| // Remember source position and frame to handle step next.
|
| - thread_local_.last_statement_position_ =
|
| + thread_local.last_statement_position_ =
|
| debug_info->code()->SourceStatementPosition(frame->pc());
|
| - thread_local_.last_fp_ = frame->fp();
|
| + thread_local.last_fp_ = frame->fp();
|
| } else {
|
| // If it's CallFunction stub ensure target function is compiled and flood
|
| // it with one shot breakpoints.
|
| @@ -1277,9 +1282,9 @@
|
| // there is a custom getter/setter it will be handled in
|
| // Object::Get/SetPropertyWithCallback, otherwise the step action will be
|
| // propagated on the next Debug::Break.
|
| - thread_local_.last_statement_position_ =
|
| + thread_local.last_statement_position_ =
|
| debug_info->code()->SourceStatementPosition(frame->pc());
|
| - thread_local_.last_fp_ = frame->fp();
|
| + thread_local.last_fp_ = frame->fp();
|
| }
|
|
|
| // Step in or Step in min
|
| @@ -1297,18 +1302,19 @@
|
| // steps before reporting break back to the debugger.
|
| bool Debug::StepNextContinue(BreakLocationIterator* break_location_iterator,
|
| JavaScriptFrame* frame) {
|
| + ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_;
|
| // If the step last action was step next or step in make sure that a new
|
| // statement is hit.
|
| - if (thread_local_.last_step_action_ == StepNext ||
|
| - thread_local_.last_step_action_ == StepIn) {
|
| + if (thread_local.last_step_action_ == StepNext ||
|
| + thread_local.last_step_action_ == StepIn) {
|
| // Never continue if returning from function.
|
| if (break_location_iterator->IsExit()) return false;
|
|
|
| // Continue if we are still on the same frame and in the same statement.
|
| int current_statement_position =
|
| break_location_iterator->code()->SourceStatementPosition(frame->pc());
|
| - return thread_local_.last_fp_ == frame->fp() &&
|
| - thread_local_.last_statement_position_ == current_statement_position;
|
| + return thread_local.last_fp_ == frame->fp() &&
|
| + thread_local.last_statement_position_ == current_statement_position;
|
| }
|
|
|
| // No step next action - don't continue.
|
| @@ -1409,14 +1415,16 @@
|
|
|
|
|
| void Debug::NewBreak(StackFrame::Id break_frame_id) {
|
| - thread_local_.break_frame_id_ = break_frame_id;
|
| - thread_local_.break_id_ = ++thread_local_.break_count_;
|
| + ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_;
|
| + thread_local.break_frame_id_ = break_frame_id;
|
| + thread_local.break_id_ = ++thread_local.break_count_;
|
| }
|
|
|
|
|
| void Debug::SetBreak(StackFrame::Id break_frame_id, int break_id) {
|
| - thread_local_.break_frame_id_ = break_frame_id;
|
| - thread_local_.break_id_ = break_id;
|
| + ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_;
|
| + thread_local.break_frame_id_ = break_frame_id;
|
| + thread_local.break_id_ = break_id;
|
| }
|
|
|
|
|
| @@ -1472,7 +1480,7 @@
|
| ClearStepNext();
|
|
|
| // Clear multiple step counter.
|
| - thread_local_.step_count_ = 0;
|
| + v8_context()->debug_data_.thread_local_.step_count_ = 0;
|
| }
|
|
|
| // Clears all the one-shot break points that are currently set. Normally this
|
| @@ -1483,7 +1491,7 @@
|
| // last break point for a function is removed that function is automatically
|
| // removed from the list.
|
|
|
| - DebugInfoListNode* node = debug_info_list_;
|
| + DebugInfoListNode* node = v8_context()->debug_data_.debug_info_list_;
|
| while (node != NULL) {
|
| BreakLocationIterator it(node->debug_info(), ALL_BREAK_LOCATIONS);
|
| while (!it.Done()) {
|
| @@ -1497,30 +1505,31 @@
|
|
|
| void Debug::ActivateStepIn(StackFrame* frame) {
|
| ASSERT(!StepOutActive());
|
| - thread_local_.step_into_fp_ = frame->fp();
|
| + v8_context()->debug_data_.thread_local_.step_into_fp_ = frame->fp();
|
| }
|
|
|
|
|
| void Debug::ClearStepIn() {
|
| - thread_local_.step_into_fp_ = 0;
|
| + v8_context()->debug_data_.thread_local_.step_into_fp_ = 0;
|
| }
|
|
|
|
|
| void Debug::ActivateStepOut(StackFrame* frame) {
|
| ASSERT(!StepInActive());
|
| - thread_local_.step_out_fp_ = frame->fp();
|
| + v8_context()->debug_data_.thread_local_.step_out_fp_ = frame->fp();
|
| }
|
|
|
|
|
| void Debug::ClearStepOut() {
|
| - thread_local_.step_out_fp_ = 0;
|
| + v8_context()->debug_data_.thread_local_.step_out_fp_ = 0;
|
| }
|
|
|
|
|
| void Debug::ClearStepNext() {
|
| - thread_local_.last_step_action_ = StepNone;
|
| - thread_local_.last_statement_position_ = RelocInfo::kNoPosition;
|
| - thread_local_.last_fp_ = 0;
|
| + ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_;
|
| + thread_local.last_step_action_ = StepNone;
|
| + thread_local.last_statement_position_ = RelocInfo::kNoPosition;
|
| + thread_local.last_fp_ = 0;
|
| }
|
|
|
|
|
| @@ -1543,26 +1552,28 @@
|
|
|
| // Add debug info to the list.
|
| DebugInfoListNode* node = new DebugInfoListNode(*debug_info);
|
| - node->set_next(debug_info_list_);
|
| - debug_info_list_ = node;
|
| + DebugData& data = v8_context()->debug_data_;
|
| + node->set_next(data.debug_info_list_);
|
| + data.debug_info_list_ = node;
|
|
|
| // Now there is at least one break point.
|
| - has_break_points_ = true;
|
| + data.has_break_points_ = true;
|
|
|
| return true;
|
| }
|
|
|
|
|
| void Debug::RemoveDebugInfo(Handle<DebugInfo> debug_info) {
|
| - ASSERT(debug_info_list_ != NULL);
|
| + DebugData& data = v8_context()->debug_data_;
|
| + ASSERT(data.debug_info_list_ != NULL);
|
| // Run through the debug info objects to find this one and remove it.
|
| DebugInfoListNode* prev = NULL;
|
| - DebugInfoListNode* current = debug_info_list_;
|
| + DebugInfoListNode* current = data.debug_info_list_;
|
| while (current != NULL) {
|
| if (*current->debug_info() == *debug_info) {
|
| // Unlink from list. If prev is NULL we are looking at the first element.
|
| if (prev == NULL) {
|
| - debug_info_list_ = current->next();
|
| + data.debug_info_list_ = current->next();
|
| } else {
|
| prev->set_next(current->next());
|
| }
|
| @@ -1571,7 +1582,7 @@
|
|
|
| // If there are no more debug info objects there are not more break
|
| // points.
|
| - has_break_points_ = debug_info_list_ != NULL;
|
| + data.has_break_points_ = data.debug_info_list_ != NULL;
|
|
|
| return;
|
| }
|
| @@ -1620,6 +1631,7 @@
|
| it.next();
|
| }
|
|
|
| + ThreadLocal& thread_local = v8_context()->debug_data_.thread_local_;
|
| // Handle the jump to continue execution after break point depending on the
|
| // break location.
|
| if (at_js_return) {
|
| @@ -1631,7 +1643,7 @@
|
| }
|
|
|
| // Move back to where the call instruction sequence started.
|
| - thread_local_.after_break_target_ =
|
| + thread_local.after_break_target_ =
|
| addr - Assembler::kPatchReturnSequenceAddressOffset;
|
| } else {
|
| // Check if there still is a debug break call at the target address. If the
|
| @@ -1651,7 +1663,7 @@
|
|
|
| // Install jump to the call address in the original code. This will be the
|
| // call which was overwritten by the call to DebugBreakXXX.
|
| - thread_local_.after_break_target_ = Assembler::target_address_at(addr);
|
| + thread_local.after_break_target_ = Assembler::target_address_at(addr);
|
| }
|
| }
|
|
|
| @@ -1687,8 +1699,9 @@
|
| Heap::CollectAllGarbage(false);
|
| Heap::CollectAllGarbage(false);
|
|
|
| - ASSERT(script_cache_ == NULL);
|
| - script_cache_ = new ScriptCache();
|
| + DebugData& data = v8_context()->debug_data_;
|
| + ASSERT(data.script_cache_ == NULL);
|
| + data.script_cache_ = new ScriptCache();
|
|
|
| // Scan heap for Script objects.
|
| int count = 0;
|
| @@ -1697,7 +1710,7 @@
|
| HeapObject* obj = iterator.next();
|
| ASSERT(obj != NULL);
|
| if (obj->IsScript() && Script::cast(obj)->HasValidSource()) {
|
| - script_cache_->Add(Handle<Script>(Script::cast(obj)));
|
| + data.script_cache_->Add(Handle<Script>(Script::cast(obj)));
|
| count++;
|
| }
|
| }
|
| @@ -1705,31 +1718,34 @@
|
|
|
|
|
| void Debug::DestroyScriptCache() {
|
| + DebugData& data = v8_context()->debug_data_;
|
| // Get rid of the script cache if it was created.
|
| - if (script_cache_ != NULL) {
|
| - delete script_cache_;
|
| - script_cache_ = NULL;
|
| + if (data.script_cache_ != NULL) {
|
| + delete data.script_cache_;
|
| + data.script_cache_ = NULL;
|
| }
|
| }
|
|
|
|
|
| void Debug::AddScriptToScriptCache(Handle<Script> script) {
|
| - if (script_cache_ != NULL) {
|
| - script_cache_->Add(script);
|
| + DebugData& data = v8_context()->debug_data_;
|
| + if (data.script_cache_ != NULL) {
|
| + data.script_cache_->Add(script);
|
| }
|
| }
|
|
|
|
|
| Handle<FixedArray> Debug::GetLoadedScripts() {
|
| + DebugData& data = v8_context()->debug_data_;
|
| // Create and fill the script cache when the loaded scripts is requested for
|
| // the first time.
|
| - if (script_cache_ == NULL) {
|
| + if (data.script_cache_ == NULL) {
|
| CreateScriptCache();
|
| }
|
|
|
| // If the script cache is not active just return an empty array.
|
| - ASSERT(script_cache_ != NULL);
|
| - if (script_cache_ == NULL) {
|
| + ASSERT(data.script_cache_ != NULL);
|
| + if (data.script_cache_ == NULL) {
|
| Factory::NewFixedArray(0);
|
| }
|
|
|
| @@ -1738,35 +1754,34 @@
|
| Heap::CollectAllGarbage(false);
|
|
|
| // Get the scripts from the cache.
|
| - return script_cache_->GetScripts();
|
| + return data.script_cache_->GetScripts();
|
| }
|
|
|
|
|
| void Debug::AfterGarbageCollection() {
|
| + DebugData& data = v8_context()->debug_data_;
|
| // Generate events for collected scripts.
|
| - if (script_cache_ != NULL) {
|
| - script_cache_->ProcessCollectedScripts();
|
| + if (data.script_cache_ != NULL) {
|
| + data.script_cache_->ProcessCollectedScripts();
|
| }
|
| }
|
|
|
| +DebuggerData::DebuggerData()
|
| + :debugger_access_(OS::CreateMutex()),
|
| + event_listener_(Handle<Object>()),
|
| + event_listener_data_(Handle<Object>()),
|
| + compiling_natives_(false),
|
| + is_loading_debugger_(false),
|
| + never_unload_debugger_(false),
|
| + message_handler_(NULL),
|
| + debugger_unload_pending_(false),
|
| + host_dispatch_handler_(NULL),
|
| + host_dispatch_micros_(100 * 1000),
|
| + agent_(NULL),
|
| + command_queue_(kQueueInitialSize),
|
| + command_received_(OS::CreateSemaphore(0)) {
|
| +}
|
|
|
| -Mutex* Debugger::debugger_access_ = OS::CreateMutex();
|
| -Handle<Object> Debugger::event_listener_ = Handle<Object>();
|
| -Handle<Object> Debugger::event_listener_data_ = Handle<Object>();
|
| -bool Debugger::compiling_natives_ = false;
|
| -bool Debugger::is_loading_debugger_ = false;
|
| -bool Debugger::never_unload_debugger_ = false;
|
| -v8::Debug::MessageHandler2 Debugger::message_handler_ = NULL;
|
| -bool Debugger::debugger_unload_pending_ = false;
|
| -v8::Debug::HostDispatchHandler Debugger::host_dispatch_handler_ = NULL;
|
| -v8::Debug::DebugMessageDispatchHandler
|
| - Debugger::debug_message_dispatch_handler_ = NULL;
|
| -int Debugger::host_dispatch_micros_ = 100 * 1000;
|
| -DebuggerAgent* Debugger::agent_ = NULL;
|
| -LockingCommandMessageQueue Debugger::command_queue_(kQueueInitialSize);
|
| -Semaphore* Debugger::command_received_ = OS::CreateSemaphore(0);
|
| -
|
| -
|
| Handle<Object> Debugger::MakeJSObject(Vector<const char> constructor_name,
|
| int argc, Object*** argv,
|
| bool* caught_exception) {
|
| @@ -2107,8 +2122,10 @@
|
| if (caught_exception) {
|
| return;
|
| }
|
| +
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| // First notify the message handler if any.
|
| - if (message_handler_ != NULL) {
|
| + if (data.message_handler_ != NULL) {
|
| NotifyMessageHandler(event,
|
| Handle<JSObject>::cast(exec_state),
|
| event_data,
|
| @@ -2116,27 +2133,28 @@
|
| }
|
| // Notify registered debug event listener. This can be either a C or a
|
| // JavaScript function.
|
| - if (!event_listener_.is_null()) {
|
| - if (event_listener_->IsProxy()) {
|
| + if (!data.event_listener_.is_null()) {
|
| + if (data.event_listener_->IsProxy()) {
|
| // C debug event listener.
|
| - Handle<Proxy> callback_obj(Handle<Proxy>::cast(event_listener_));
|
| + Handle<Proxy> callback_obj(Handle<Proxy>::cast(data.event_listener_));
|
| v8::Debug::EventCallback callback =
|
| FUNCTION_CAST<v8::Debug::EventCallback>(callback_obj->proxy());
|
| callback(event,
|
| v8::Utils::ToLocal(Handle<JSObject>::cast(exec_state)),
|
| v8::Utils::ToLocal(event_data),
|
| - v8::Utils::ToLocal(Handle<Object>::cast(event_listener_data_)));
|
| + v8::Utils::ToLocal(Handle<Object>::cast(
|
| + data.event_listener_data_)));
|
| } else {
|
| // JavaScript debug event listener.
|
| - ASSERT(event_listener_->IsJSFunction());
|
| - Handle<JSFunction> fun(Handle<JSFunction>::cast(event_listener_));
|
| + ASSERT(data.event_listener_->IsJSFunction());
|
| + Handle<JSFunction> fun(Handle<JSFunction>::cast(data.event_listener_));
|
|
|
| // Invoke the JavaScript debug event listener.
|
| const int argc = 4;
|
| Object** argv[argc] = { Handle<Object>(Smi::FromInt(event)).location(),
|
| exec_state.location(),
|
| Handle<Object>::cast(event_data).location(),
|
| - event_listener_data_.location() };
|
| + data.event_listener_data_.location() };
|
| Handle<Object> result = Execution::TryCall(fun, Top::global(),
|
| argc, argv, &caught_exception);
|
| // Silently ignore exceptions from debug event listeners.
|
| @@ -2149,13 +2167,14 @@
|
| // Make sure that there are no breakpoints left.
|
| Debug::ClearAllBreakPoints();
|
|
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| // Unload the debugger if feasible.
|
| - if (!never_unload_debugger_) {
|
| + if (!data.never_unload_debugger_) {
|
| Debug::Unload();
|
| }
|
|
|
| // Clear the flag indicating that the debugger should be unloaded.
|
| - debugger_unload_pending_ = false;
|
| + data.debugger_unload_pending_ = false;
|
| }
|
|
|
|
|
| @@ -2239,24 +2258,25 @@
|
| }
|
|
|
| bool running = auto_continue;
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
|
|
| // Process requests from the debugger.
|
| while (true) {
|
| // Wait for new command in the queue.
|
| - if (Debugger::host_dispatch_handler_) {
|
| + if (data.host_dispatch_handler_) {
|
| // In case there is a host dispatch - do periodic dispatches.
|
| - if (!command_received_->Wait(host_dispatch_micros_)) {
|
| + if (!data.command_received_->Wait(data.host_dispatch_micros_)) {
|
| // Timout expired, do the dispatch.
|
| - Debugger::host_dispatch_handler_();
|
| + data.host_dispatch_handler_();
|
| continue;
|
| }
|
| } else {
|
| // In case there is no host dispatch - just wait.
|
| - command_received_->Wait();
|
| + data.command_received_->Wait();
|
| }
|
|
|
| // Get the command from the queue.
|
| - CommandMessage command = command_queue_.Get();
|
| + CommandMessage command = data.command_queue_.Get();
|
| Logger::DebugTag("Got request from command queue, in interactive loop.");
|
| if (!Debugger::IsDebuggerActive()) {
|
| // Delete command text and user data.
|
| @@ -2333,27 +2353,31 @@
|
| Handle<Object> data) {
|
| HandleScope scope;
|
|
|
| + DebuggerData& debugger_data = v8_context()->debugger_data_;
|
| +
|
| // Clear the global handles for the event listener and the event listener data
|
| // object.
|
| - if (!event_listener_.is_null()) {
|
| + if (!debugger_data.event_listener_.is_null()) {
|
| GlobalHandles::Destroy(
|
| - reinterpret_cast<Object**>(event_listener_.location()));
|
| - event_listener_ = Handle<Object>();
|
| + reinterpret_cast<Object**>(debugger_data.event_listener_.location()));
|
| + debugger_data.event_listener_ = Handle<Object>();
|
| }
|
| - if (!event_listener_data_.is_null()) {
|
| - GlobalHandles::Destroy(
|
| - reinterpret_cast<Object**>(event_listener_data_.location()));
|
| - event_listener_data_ = Handle<Object>();
|
| + if (!debugger_data.event_listener_data_.is_null()) {
|
| + GlobalHandles::Destroy(reinterpret_cast<Object**>(
|
| + debugger_data.event_listener_data_.location()));
|
| + debugger_data.event_listener_data_ = Handle<Object>();
|
| }
|
|
|
| // If there is a new debug event listener register it together with its data
|
| // object.
|
| if (!callback->IsUndefined() && !callback->IsNull()) {
|
| - event_listener_ = Handle<Object>::cast(GlobalHandles::Create(*callback));
|
| + debugger_data.event_listener_ =
|
| + Handle<Object>::cast(GlobalHandles::Create(*callback));
|
| if (data.is_null()) {
|
| data = Factory::undefined_value();
|
| }
|
| - event_listener_data_ = Handle<Object>::cast(GlobalHandles::Create(*data));
|
| + debugger_data.event_listener_data_ =
|
| + Handle<Object>::cast(GlobalHandles::Create(*data));
|
| }
|
|
|
| ListenersChanged();
|
| @@ -2361,9 +2385,10 @@
|
|
|
|
|
| void Debugger::SetMessageHandler(v8::Debug::MessageHandler2 handler) {
|
| - ScopedLock with(debugger_access_);
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| + ScopedLock with(data.debugger_access_);
|
|
|
| - message_handler_ = handler;
|
| + data.message_handler_ = handler;
|
| ListenersChanged();
|
| if (handler == NULL) {
|
| // Send an empty command to the debugger if in a break to make JavaScript
|
| @@ -2386,7 +2411,7 @@
|
| if (Debug::InDebugger()) {
|
| // If we are in debugger set the flag to unload the debugger when last
|
| // EnterDebugger on the current stack is destroyed.
|
| - debugger_unload_pending_ = true;
|
| + v8_context()->debugger_data_.debugger_unload_pending_ = true;
|
| } else {
|
| UnloadDebugger();
|
| }
|
| @@ -2396,24 +2421,26 @@
|
|
|
| void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
|
| int period) {
|
| - host_dispatch_handler_ = handler;
|
| - host_dispatch_micros_ = period * 1000;
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| + data.host_dispatch_handler_ = handler;
|
| + data.host_dispatch_micros_ = period * 1000;
|
| }
|
|
|
|
|
| void Debugger::SetDebugMessageDispatchHandler(
|
| v8::Debug::DebugMessageDispatchHandler handler) {
|
| - debug_message_dispatch_handler_ = handler;
|
| + v8_context()->debugger_data_.debug_message_dispatch_handler_ = handler;
|
| }
|
|
|
|
|
| // Calls the registered debug message handler. This callback is part of the
|
| // public API.
|
| void Debugger::InvokeMessageHandler(MessageImpl message) {
|
| - ScopedLock with(debugger_access_);
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| + ScopedLock with(data.debugger_access_);
|
|
|
| - if (message_handler_ != NULL) {
|
| - message_handler_(message);
|
| + if (data.message_handler_ != NULL) {
|
| + data.message_handler_(message);
|
| }
|
| }
|
|
|
| @@ -2430,29 +2457,31 @@
|
| command.length()),
|
| client_data);
|
| Logger::DebugTag("Put command on command_queue.");
|
| - command_queue_.Put(message);
|
| - command_received_->Signal();
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| + data.command_queue_.Put(message);
|
| + data.command_received_->Signal();
|
|
|
| // Set the debug command break flag to have the command processed.
|
| if (!Debug::InDebugger()) {
|
| StackGuard::DebugCommand();
|
| }
|
|
|
| - if (Debugger::debug_message_dispatch_handler_ != NULL) {
|
| - Debugger::debug_message_dispatch_handler_();
|
| + if (data.debug_message_dispatch_handler_ != NULL) {
|
| + data.debug_message_dispatch_handler_();
|
| }
|
| }
|
|
|
|
|
| bool Debugger::HasCommands() {
|
| - return !command_queue_.IsEmpty();
|
| + return !v8_context()->debugger_data_.command_queue_.IsEmpty();
|
| }
|
|
|
|
|
| bool Debugger::IsDebuggerActive() {
|
| - ScopedLock with(debugger_access_);
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| + ScopedLock with(data.debugger_access_);
|
|
|
| - return message_handler_ != NULL || !event_listener_.is_null();
|
| + return data.message_handler_ != NULL || !data.event_listener_.is_null();
|
| }
|
|
|
|
|
| @@ -2460,7 +2489,7 @@
|
| Handle<Object> data,
|
| bool* pending_exception) {
|
| // When calling functions in the debugger prevent it from beeing unloaded.
|
| - Debugger::never_unload_debugger_ = true;
|
| + v8_context()->debugger_data_.never_unload_debugger_ = true;
|
|
|
| // Enter the debugger.
|
| EnterDebugger debugger;
|
| @@ -2485,8 +2514,9 @@
|
|
|
| bool Debugger::StartAgent(const char* name, int port) {
|
| if (Socket::Setup()) {
|
| - agent_ = new DebuggerAgent(name, port);
|
| - agent_->Start();
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| + data.agent_ = new DebuggerAgent(name, port);
|
| + data.agent_->Start();
|
| return true;
|
| }
|
|
|
| @@ -2495,18 +2525,20 @@
|
|
|
|
|
| void Debugger::StopAgent() {
|
| - if (agent_ != NULL) {
|
| - agent_->Shutdown();
|
| - agent_->Join();
|
| - delete agent_;
|
| - agent_ = NULL;
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| + if (data.agent_ != NULL) {
|
| + data.agent_->Shutdown();
|
| + data.agent_->Join();
|
| + delete data.agent_;
|
| + data.agent_ = NULL;
|
| }
|
| }
|
|
|
|
|
| void Debugger::WaitForAgent() {
|
| - if (agent_ != NULL)
|
| - agent_->WaitUntilListening();
|
| + DebuggerData& data = v8_context()->debugger_data_;
|
| + if (data.agent_ != NULL)
|
| + data.agent_->WaitUntilListening();
|
| }
|
|
|
| MessageImpl MessageImpl::NewEvent(DebugEvent event,
|
|
|