From be56273bbb3af34010db4251513ee5efe0dc79dd Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 11 Dec 2012 22:50:49 -0500 Subject: [PATCH] Refactor DebugReportGenerator to use jobs. - Instead of asking nodes to resolve themselves directly, DebugReportGenerator now uses the interface listener to ask the debugger's workers to resolve them on its behalf. --- .../controllers/DebugReportGenerator.cpp | 75 +++++++++++++------ .../controllers/DebugReportGenerator.h | 16 +++- .../debugger/controllers/TeamDebugger.cpp | 2 +- 3 files changed, 67 insertions(+), 26 deletions(-) diff --git a/src/apps/debugger/controllers/DebugReportGenerator.cpp b/src/apps/debugger/controllers/DebugReportGenerator.cpp index 6bcfa1f3af..a5b985c4a4 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.cpp +++ b/src/apps/debugger/controllers/DebugReportGenerator.cpp @@ -28,6 +28,7 @@ #include "Thread.h" #include "Type.h" #include "UiUtils.h" +#include "UserInterface.h" #include "Value.h" #include "ValueLoader.h" #include "ValueLocation.h" @@ -35,13 +36,17 @@ #include "ValueNodeManager.h" -DebugReportGenerator::DebugReportGenerator(::Team* team) +DebugReportGenerator::DebugReportGenerator(::Team* team, + UserInterfaceListener* listener) : BLooper("DebugReportGenerator"), fTeam(team), fArchitecture(team->GetArchitecture()), fTeamDataSem(-1), - fNodeManager(NULL) + fNodeManager(NULL), + fListener(listener), + fWaitingNode(NULL), + fTraceWaitingThread(NULL) { fTeam->AddListener(this); fArchitecture->AcquireReference(); @@ -52,8 +57,10 @@ DebugReportGenerator::~DebugReportGenerator() { fTeam->RemoveListener(this); fArchitecture->ReleaseReference(); - if (fNodeManager != NULL) + if (fNodeManager != NULL) { + fNodeManager->RemoveListener(this); fNodeManager->ReleaseReference(); + } } @@ -68,6 +75,8 @@ DebugReportGenerator::Init() if (fNodeManager == NULL) return B_NO_MEMORY; + fNodeManager->AddListener(this); + Run(); return B_OK; @@ -75,9 +84,9 @@ DebugReportGenerator::Init() DebugReportGenerator* -DebugReportGenerator::Create(::Team* team) +DebugReportGenerator::Create(::Team* team, UserInterfaceListener* listener) { - DebugReportGenerator* self = new DebugReportGenerator(team); + DebugReportGenerator* self = new DebugReportGenerator(team, listener); try { self->Init(); @@ -145,7 +154,20 @@ DebugReportGenerator::MessageReceived(BMessage* message) void DebugReportGenerator::ThreadStackTraceChanged(const ::Team::ThreadEvent& event) { - release_sem(fTeamDataSem); + if (fTraceWaitingThread == event.GetThread()) { + fTraceWaitingThread = NULL; + release_sem(fTeamDataSem); + } +} + + +void +DebugReportGenerator::ValueNodeValueChanged(ValueNode* node) +{ + if (node == fWaitingNode) { + fWaitingNode = NULL; + release_sem(fTeamDataSem); + } } @@ -280,6 +302,7 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, break; locker.Unlock(); + fTraceWaitingThread = thread; status_t result = acquire_sem(fTeamDataSem); if (result != B_OK) return result; @@ -312,9 +335,10 @@ DebugReportGenerator::_DumpDebuggedThreadInfo(BString& _output, AutoLocker containerLocker(container); for (int32 i = 0; i < container->CountChildren(); i++) { ValueNodeChild* child = container->ChildAt(i); - _ResolveLocationIfNeeded(child, frame); - _ResolveValueIfNeeded(child->Node(), frame, 4); - UiUtils::PrintValueNodeGraph(_output, frame, child, 3, 2); + containerLocker.Unlock(); + _ResolveValueIfNeeded(child->Node(), frame, 1); + containerLocker.Lock(); + UiUtils::PrintValueNodeGraph(_output, frame, child, 3, 1); } _output << "\n"; } @@ -342,21 +366,20 @@ status_t DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, int32 maxDepth) { - ValueLocation* location = NULL; - Value* value = NULL; - ValueLoader loader(fTeam->GetArchitecture(), fTeam->GetTeamMemory(), - fTeam->GetTeamTypeInformation(), frame->GetCpuState()); - status_t result = node->ResolvedLocationAndValue(&loader, location, - value); - node->SetLocationAndValue(location, value, result); - if (location != NULL) - location->ReleaseReference(); - if (value != NULL) - value->ReleaseReference(); + status_t result = B_OK; + if (node->LocationAndValueResolutionState() == VALUE_NODE_UNRESOLVED) { + fWaitingNode = node; + fListener->ValueNodeValueRequested(frame->GetCpuState(), + fNodeManager->GetContainer(), node); + result = acquire_sem(fTeamDataSem); + } - if (result == B_OK && maxDepth > 0) { + if (node->LocationAndValueResolutionState() == B_OK && maxDepth > 0) { + AutoLocker containerLocker( + fNodeManager->GetContainer()); for (int32 i = 0; i < node->CountChildren(); i++) { ValueNodeChild* child = node->ChildAt(i); + containerLocker.Unlock(); result = _ResolveLocationIfNeeded(child, frame); if (result != B_OK) continue; @@ -365,7 +388,15 @@ DebugReportGenerator::_ResolveValueIfNeeded(ValueNode* node, StackFrame* frame, if (result != B_OK) continue; - _ResolveValueIfNeeded(child->Node(), frame, maxDepth - 1); + // since in the case of a pointer to a compound we hide + // the intervening compound, don't consider the hidden node + // a level for the purposes of depth traversal + if (node->GetType()->Kind() == TYPE_ADDRESS + && child->GetType()->Kind() == TYPE_COMPOUND) { + _ResolveValueIfNeeded(child->Node(), frame, maxDepth); + } else + _ResolveValueIfNeeded(child->Node(), frame, maxDepth - 1); + containerLocker.Lock(); } } diff --git a/src/apps/debugger/controllers/DebugReportGenerator.h b/src/apps/debugger/controllers/DebugReportGenerator.h index 17b1a54f5a..677334cfd5 100644 --- a/src/apps/debugger/controllers/DebugReportGenerator.h +++ b/src/apps/debugger/controllers/DebugReportGenerator.h @@ -9,6 +9,7 @@ #include #include "Team.h" +#include "ValueNodeContainer.h" class entry_ref; @@ -17,26 +18,32 @@ class BString; class StackFrame; class Team; class Thread; +class UserInterfaceListener; class Value; class ValueNode; class ValueNodeChild; class ValueNodeManager; -class DebugReportGenerator : public BLooper, public Team::Listener { +class DebugReportGenerator : public BLooper, private Team::Listener, + private ValueNodeContainer::Listener { public: - DebugReportGenerator(::Team* team); + DebugReportGenerator(::Team* team, + UserInterfaceListener* listener); ~DebugReportGenerator(); status_t Init(); - static DebugReportGenerator* Create(::Team* team); + static DebugReportGenerator* Create(::Team* team, + UserInterfaceListener* listener); virtual void MessageReceived(BMessage* message); virtual void ThreadStackTraceChanged( const Team::ThreadEvent& event); + virtual void ValueNodeValueChanged(ValueNode* node); + private: status_t _GenerateReport(const entry_ref& outputPath); status_t _GenerateReportHeader(BString& output); @@ -55,6 +62,9 @@ private: Architecture* fArchitecture; sem_id fTeamDataSem; ValueNodeManager* fNodeManager; + UserInterfaceListener* fListener; + ValueNode* fWaitingNode; + ::Thread* fTraceWaitingThread; }; #endif // DEBUG_REPORT_GENERATOR_H diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index a84a3205ad..634eba0d0d 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -416,7 +416,7 @@ TeamDebugger::Init(team_id teamID, thread_id threadID, bool stopInMain) return error; // create the debug report generator - fReportGenerator = new(std::nothrow) DebugReportGenerator(fTeam); + fReportGenerator = new(std::nothrow) DebugReportGenerator(fTeam, this); if (fReportGenerator == NULL) return B_NO_MEMORY;