From 2d5794a1a3614749dc4f680c4c95c58617b4cd85 Mon Sep 17 00:00:00 2001 From: Rene Gollent Date: Tue, 28 Oct 2014 15:24:34 -0400 Subject: [PATCH] Debugger: Add asynchronous expression evaluation interface. - Add UserInterfaceListener hook to request expression evaluation. - Add corresponding events/handlers in Team and TeamDebugger. These allow callers to request evaluation of expressions by the debugger core's worker threads with asynchronous notifications of results. While not strictly necessary right now, this paves the way for further changes to come, as handling of variables will potentially require resolving their values if they haven't been already, and this shouldn't be done from user interface threads. --- src/apps/debugger/Jamfile | 1 + src/apps/debugger/MessageCodes.h | 1 + .../debugger/controllers/TeamDebugger.cpp | 66 +++++++++++++++++++ src/apps/debugger/controllers/TeamDebugger.h | 13 ++++ src/apps/debugger/model/Team.cpp | 46 ++++++++++++- src/apps/debugger/model/Team.h | 35 +++++++++- .../debugger/user_interface/UserInterface.h | 7 ++ .../ExpressionEvaluationWindow.cpp | 1 - 8 files changed, 166 insertions(+), 4 deletions(-) diff --git a/src/apps/debugger/Jamfile b/src/apps/debugger/Jamfile index 9b3c91a56b..43ad3133db 100644 --- a/src/apps/debugger/Jamfile +++ b/src/apps/debugger/Jamfile @@ -150,6 +150,7 @@ Application Debugger : ReturnValueID.cpp # jobs + ExpressionEvaluationJob.cpp GetCPUStateJob.cpp GetStackTraceJob.cpp GetThreadStateJob.cpp diff --git a/src/apps/debugger/MessageCodes.h b/src/apps/debugger/MessageCodes.h index ca68f7ac88..63dcd001e7 100644 --- a/src/apps/debugger/MessageCodes.h +++ b/src/apps/debugger/MessageCodes.h @@ -68,6 +68,7 @@ enum { MSG_SHOW_EXPRESSION_WINDOW = 'seww', MSG_EXPRESSION_WINDOW_CLOSED = 'ewwc', MSG_INSPECT_ADDRESS = 'isad', + MSG_EVALUATE_EXPRESSION = 'evex', MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp', MSG_TYPECAST_TO_ARRAY = 'stta', MSG_TYPECAST_NODE = 'tyno', diff --git a/src/apps/debugger/controllers/TeamDebugger.cpp b/src/apps/debugger/controllers/TeamDebugger.cpp index d551bd0859..5485e67ef6 100644 --- a/src/apps/debugger/controllers/TeamDebugger.cpp +++ b/src/apps/debugger/controllers/TeamDebugger.cpp @@ -40,6 +40,7 @@ #include "MessageCodes.h" #include "SettingsManager.h" #include "SourceCode.h" +#include "SourceLanguage.h" #include "SpecificImageDebugInfo.h" #include "SpecificImageDebugInfoLoadingState.h" #include "StackFrame.h" @@ -701,6 +702,40 @@ TeamDebugger::MessageReceived(BMessage* message) break; } + case MSG_EVALUATE_EXPRESSION: + { + SourceLanguage* language; + if (message->FindPointer("language", + reinterpret_cast(&language)) != B_OK) { + break; + } + + // ExpressionEvaluationRequested() acquires a reference + // on our behalf. + BReference reference(language, true); + + const char* expression; + if (message->FindString("expression", &expression) != B_OK) + break; + + type_code resultType; + if (message->FindInt32("type", + reinterpret_cast(&resultType)) != B_OK) { + break; + } + + StackFrame* frame; + if (message->FindPointer("frame", + reinterpret_cast(&frame)) != B_OK) { + // the stack frame isn't needed, unless variable + // evaluation is desired. + frame = NULL; + } + + _HandleEvaluateExpression(language, expression, resultType, frame); + break; + } + case MSG_GENERATE_DEBUG_REPORT: { fReportGenerator->PostMessage(message); @@ -1050,6 +1085,23 @@ TeamDebugger::InspectRequested(target_addr_t address, } +void +TeamDebugger::ExpressionEvaluationRequested(SourceLanguage* language, + const char* expression, type_code resultType, StackFrame* frame) +{ + BMessage message(MSG_EVALUATE_EXPRESSION); + message.AddPointer("language", language); + message.AddString("expression", expression); + message.AddInt32("type", resultType); + if (frame != NULL) + message.AddPointer("frame", frame); + + BReference reference(language); + if (PostMessage(&message) == B_OK) + reference.Detach(); +} + + void TeamDebugger::DebugReportRequested(entry_ref* targetPath) { @@ -1928,6 +1980,20 @@ TeamDebugger::_HandleInspectAddress(target_addr_t address, } +void +TeamDebugger::_HandleEvaluateExpression(SourceLanguage* language, + const char* expression, type_code resultType, StackFrame* frame) +{ + status_t result = fWorker->ScheduleJob( + new(std::nothrow) ExpressionEvaluationJob(fTeam, language, + expression, resultType, frame)); + if (result != B_OK) { + _NotifyUser("Evaluate Expression", "Failed to evaluate expression: %s", + strerror(result)); + } +} + + status_t TeamDebugger::_HandleSetArguments(int argc, const char* const* argv) { diff --git a/src/apps/debugger/controllers/TeamDebugger.h b/src/apps/debugger/controllers/TeamDebugger.h index d48c8487f6..4ef9cba66f 100644 --- a/src/apps/debugger/controllers/TeamDebugger.h +++ b/src/apps/debugger/controllers/TeamDebugger.h @@ -102,6 +102,12 @@ private: virtual void InspectRequested(target_addr_t address, TeamMemoryBlock::Listener* listener); + virtual void ExpressionEvaluationRequested( + SourceLanguage* language, + const char* expression, + type_code resultType, + StackFrame* frame = NULL); + virtual void DebugReportRequested(entry_ref* targetPath); virtual void TeamRestartRequested(); @@ -182,6 +188,13 @@ private: void _HandleInspectAddress( target_addr_t address, TeamMemoryBlock::Listener* listener); + + void _HandleEvaluateExpression( + SourceLanguage* language, + const char* expression, + type_code resultType, + StackFrame* frame); + status_t _HandleSetArguments(int argc, const char* const* argv); diff --git a/src/apps/debugger/model/Team.cpp b/src/apps/debugger/model/Team.cpp index 47ca84dc99..89bb18bfbb 100644 --- a/src/apps/debugger/model/Team.cpp +++ b/src/apps/debugger/model/Team.cpp @@ -1,6 +1,6 @@ /* * Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2013, Rene Gollent, rene@gollent.com. + * Copyright 2013-2014, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -21,6 +21,7 @@ #include "Statement.h" #include "TeamDebugInfo.h" #include "Tracing.h" +#include "Value.h" #include "Watchpoint.h" @@ -731,6 +732,19 @@ Team::NotifyDebugReportChanged(const char* reportPath) } +void +Team::NotifyExpressionEvaluated(const char* expression, status_t result, + Value* value) +{ + for (ListenerList::Iterator it = fListeners.GetIterator(); + Listener* listener = it.Next();) { + listener->ExpressionEvaluated(ExpressionEvaluationEvent( + TEAM_EVENT_EXPRESSION_EVALUATED, this, expression, result, + value)); + } +} + + void Team::_NotifyThreadAdded(Thread* thread) { @@ -890,6 +904,29 @@ Team::UserBreakpointEvent::UserBreakpointEvent(uint32 type, Team* team, } +// #pragma mark - ExpressionEvaluationEvent + + +Team::ExpressionEvaluationEvent::ExpressionEvaluationEvent(uint32 type, + Team* team, const char* expression, status_t result, Value* value) + : + Event(type, team), + fExpression(expression), + fEvaluationResult(result), + fValue(value) +{ + if (fValue != NULL) + fValue->AcquireReference(); +} + + +Team::ExpressionEvaluationEvent::~ExpressionEvaluationEvent() +{ + if (fValue != NULL) + fValue->ReleaseReference(); +} + + // #pragma mark - Listener @@ -1012,3 +1049,10 @@ void Team::Listener::DebugReportChanged(const Team::DebugReportEvent& event) { } + + +void +Team::Listener::ExpressionEvaluated( + const Team::ExpressionEvaluationEvent& event) +{ +} diff --git a/src/apps/debugger/model/Team.h b/src/apps/debugger/model/Team.h index 5428084796..dc3c49bb3e 100644 --- a/src/apps/debugger/model/Team.h +++ b/src/apps/debugger/model/Team.h @@ -1,6 +1,6 @@ /* * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. - * Copyright 2013, Rene Gollent, rene@gollent.com. + * Copyright 2013-2014, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ #ifndef TEAM_H @@ -48,8 +48,9 @@ enum { TEAM_EVENT_WATCHPOINT_REMOVED, TEAM_EVENT_WATCHPOINT_CHANGED, - TEAM_EVENT_DEBUG_REPORT_CHANGED + TEAM_EVENT_DEBUG_REPORT_CHANGED, + TEAM_EVENT_EXPRESSION_EVALUATED }; @@ -67,6 +68,7 @@ class TeamDebugInfo; class TeamMemory; class TeamTypeInformation; class UserBreakpoint; +class Value; class Team { @@ -75,6 +77,7 @@ public: class BreakpointEvent; class ConsoleOutputEvent; class DebugReportEvent; + class ExpressionEvaluationEvent; class ImageEvent; class ImageLoadEvent; class ImageLoadNameEvent; @@ -225,6 +228,11 @@ public: void NotifyDebugReportChanged( const char* reportPath); + // expression evaluation related service methods + void NotifyExpressionEvaluated( + const char* expression, + status_t result, Value* value); + private: struct BreakpointByAddressPredicate; struct WatchpointByAddressPredicate; @@ -384,6 +392,25 @@ protected: }; +class Team::ExpressionEvaluationEvent : public Event { +public: + ExpressionEvaluationEvent(uint32 type, + Team* team, const char* expression, + status_t result, Value* value); + virtual ~ExpressionEvaluationEvent(); + + status_t GetResult() const + { return fEvaluationResult; } + BString GetExpression() const { return fExpression; } + Value* GetValue() const { return fValue; } + +protected: + BString fExpression; + status_t fEvaluationResult; + Value* fValue; +}; + + class Team::Listener : public DoublyLinkedListLinkImpl { public: virtual ~Listener(); @@ -428,6 +455,10 @@ public: virtual void WatchpointChanged( const Team::WatchpointEvent& event); + virtual void ExpressionEvaluated( + const Team::ExpressionEvaluationEvent& + event); + virtual void DebugReportChanged( const Team::DebugReportEvent& event); }; diff --git a/src/apps/debugger/user_interface/UserInterface.h b/src/apps/debugger/user_interface/UserInterface.h index 50e293ef7b..748b6a8625 100644 --- a/src/apps/debugger/user_interface/UserInterface.h +++ b/src/apps/debugger/user_interface/UserInterface.h @@ -21,6 +21,7 @@ class CpuState; class FunctionInstance; class Image; class LocatableFile; +class SourceLanguage; class StackFrame; class Team; class TeamUiSettings; @@ -136,6 +137,12 @@ public: target_addr_t address, TeamMemoryBlock::Listener* listener) = 0; + virtual void ExpressionEvaluationRequested( + SourceLanguage* language, + const char* expression, + type_code resultType, + StackFrame* frame = NULL) = 0; + virtual void DebugReportRequested(entry_ref* path) = 0; virtual void TeamRestartRequested() = 0; diff --git a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp index bc841a47c7..a17cfc4e75 100644 --- a/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp +++ b/src/apps/debugger/user_interface/gui/team_window/ExpressionEvaluationWindow.cpp @@ -19,7 +19,6 @@ enum { - MSG_EVALUATE_EXPRESSION = 'evex', MSG_CHANGE_EVALUATION_TYPE = 'chet' };