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.
This commit is contained in:
Rene Gollent
2014-10-28 23:30:01 -04:00
parent feab8604c9
commit 2d5794a1a3
8 changed files with 166 additions and 4 deletions
+1
View File
@@ -150,6 +150,7 @@ Application Debugger :
ReturnValueID.cpp ReturnValueID.cpp
# jobs # jobs
ExpressionEvaluationJob.cpp
GetCPUStateJob.cpp GetCPUStateJob.cpp
GetStackTraceJob.cpp GetStackTraceJob.cpp
GetThreadStateJob.cpp GetThreadStateJob.cpp
+1
View File
@@ -68,6 +68,7 @@ enum {
MSG_SHOW_EXPRESSION_WINDOW = 'seww', MSG_SHOW_EXPRESSION_WINDOW = 'seww',
MSG_EXPRESSION_WINDOW_CLOSED = 'ewwc', MSG_EXPRESSION_WINDOW_CLOSED = 'ewwc',
MSG_INSPECT_ADDRESS = 'isad', MSG_INSPECT_ADDRESS = 'isad',
MSG_EVALUATE_EXPRESSION = 'evex',
MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp', MSG_SHOW_TYPECAST_NODE_PROMPT = 'stnp',
MSG_TYPECAST_TO_ARRAY = 'stta', MSG_TYPECAST_TO_ARRAY = 'stta',
MSG_TYPECAST_NODE = 'tyno', MSG_TYPECAST_NODE = 'tyno',
@@ -40,6 +40,7 @@
#include "MessageCodes.h" #include "MessageCodes.h"
#include "SettingsManager.h" #include "SettingsManager.h"
#include "SourceCode.h" #include "SourceCode.h"
#include "SourceLanguage.h"
#include "SpecificImageDebugInfo.h" #include "SpecificImageDebugInfo.h"
#include "SpecificImageDebugInfoLoadingState.h" #include "SpecificImageDebugInfoLoadingState.h"
#include "StackFrame.h" #include "StackFrame.h"
@@ -701,6 +702,40 @@ TeamDebugger::MessageReceived(BMessage* message)
break; break;
} }
case MSG_EVALUATE_EXPRESSION:
{
SourceLanguage* language;
if (message->FindPointer("language",
reinterpret_cast<void**>(&language)) != B_OK) {
break;
}
// ExpressionEvaluationRequested() acquires a reference
// on our behalf.
BReference<SourceLanguage> reference(language, true);
const char* expression;
if (message->FindString("expression", &expression) != B_OK)
break;
type_code resultType;
if (message->FindInt32("type",
reinterpret_cast<int32*>(&resultType)) != B_OK) {
break;
}
StackFrame* frame;
if (message->FindPointer("frame",
reinterpret_cast<void**>(&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: case MSG_GENERATE_DEBUG_REPORT:
{ {
fReportGenerator->PostMessage(message); 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<SourceLanguage> reference(language);
if (PostMessage(&message) == B_OK)
reference.Detach();
}
void void
TeamDebugger::DebugReportRequested(entry_ref* targetPath) 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 status_t
TeamDebugger::_HandleSetArguments(int argc, const char* const* argv) TeamDebugger::_HandleSetArguments(int argc, const char* const* argv)
{ {
@@ -102,6 +102,12 @@ private:
virtual void InspectRequested(target_addr_t address, virtual void InspectRequested(target_addr_t address,
TeamMemoryBlock::Listener* listener); 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 DebugReportRequested(entry_ref* targetPath);
virtual void TeamRestartRequested(); virtual void TeamRestartRequested();
@@ -182,6 +188,13 @@ private:
void _HandleInspectAddress( void _HandleInspectAddress(
target_addr_t address, target_addr_t address,
TeamMemoryBlock::Listener* listener); TeamMemoryBlock::Listener* listener);
void _HandleEvaluateExpression(
SourceLanguage* language,
const char* expression,
type_code resultType,
StackFrame* frame);
status_t _HandleSetArguments(int argc, status_t _HandleSetArguments(int argc,
const char* const* argv); const char* const* argv);
+45 -1
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2009-2012, Ingo Weinhold, ingo_weinhold@gmx.de. * 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. * Distributed under the terms of the MIT License.
*/ */
@@ -21,6 +21,7 @@
#include "Statement.h" #include "Statement.h"
#include "TeamDebugInfo.h" #include "TeamDebugInfo.h"
#include "Tracing.h" #include "Tracing.h"
#include "Value.h"
#include "Watchpoint.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 void
Team::_NotifyThreadAdded(Thread* thread) 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 // #pragma mark - Listener
@@ -1012,3 +1049,10 @@ void
Team::Listener::DebugReportChanged(const Team::DebugReportEvent& event) Team::Listener::DebugReportChanged(const Team::DebugReportEvent& event)
{ {
} }
void
Team::Listener::ExpressionEvaluated(
const Team::ExpressionEvaluationEvent& event)
{
}
+33 -2
View File
@@ -1,6 +1,6 @@
/* /*
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. * 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. * Distributed under the terms of the MIT License.
*/ */
#ifndef TEAM_H #ifndef TEAM_H
@@ -48,8 +48,9 @@ enum {
TEAM_EVENT_WATCHPOINT_REMOVED, TEAM_EVENT_WATCHPOINT_REMOVED,
TEAM_EVENT_WATCHPOINT_CHANGED, 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 TeamMemory;
class TeamTypeInformation; class TeamTypeInformation;
class UserBreakpoint; class UserBreakpoint;
class Value;
class Team { class Team {
@@ -75,6 +77,7 @@ public:
class BreakpointEvent; class BreakpointEvent;
class ConsoleOutputEvent; class ConsoleOutputEvent;
class DebugReportEvent; class DebugReportEvent;
class ExpressionEvaluationEvent;
class ImageEvent; class ImageEvent;
class ImageLoadEvent; class ImageLoadEvent;
class ImageLoadNameEvent; class ImageLoadNameEvent;
@@ -225,6 +228,11 @@ public:
void NotifyDebugReportChanged( void NotifyDebugReportChanged(
const char* reportPath); const char* reportPath);
// expression evaluation related service methods
void NotifyExpressionEvaluated(
const char* expression,
status_t result, Value* value);
private: private:
struct BreakpointByAddressPredicate; struct BreakpointByAddressPredicate;
struct WatchpointByAddressPredicate; 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<Team::Listener> { class Team::Listener : public DoublyLinkedListLinkImpl<Team::Listener> {
public: public:
virtual ~Listener(); virtual ~Listener();
@@ -428,6 +455,10 @@ public:
virtual void WatchpointChanged( virtual void WatchpointChanged(
const Team::WatchpointEvent& event); const Team::WatchpointEvent& event);
virtual void ExpressionEvaluated(
const Team::ExpressionEvaluationEvent&
event);
virtual void DebugReportChanged( virtual void DebugReportChanged(
const Team::DebugReportEvent& event); const Team::DebugReportEvent& event);
}; };
@@ -21,6 +21,7 @@ class CpuState;
class FunctionInstance; class FunctionInstance;
class Image; class Image;
class LocatableFile; class LocatableFile;
class SourceLanguage;
class StackFrame; class StackFrame;
class Team; class Team;
class TeamUiSettings; class TeamUiSettings;
@@ -136,6 +137,12 @@ public:
target_addr_t address, target_addr_t address,
TeamMemoryBlock::Listener* listener) = 0; 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 DebugReportRequested(entry_ref* path) = 0;
virtual void TeamRestartRequested() = 0; virtual void TeamRestartRequested() = 0;
@@ -19,7 +19,6 @@
enum { enum {
MSG_EVALUATE_EXPRESSION = 'evex',
MSG_CHANGE_EVALUATION_TYPE = 'chet' MSG_CHANGE_EVALUATION_TYPE = 'chet'
}; };