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:
@@ -150,6 +150,7 @@ Application Debugger :
|
||||
ReturnValueID.cpp
|
||||
|
||||
# jobs
|
||||
ExpressionEvaluationJob.cpp
|
||||
GetCPUStateJob.cpp
|
||||
GetStackTraceJob.cpp
|
||||
GetThreadStateJob.cpp
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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<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:
|
||||
{
|
||||
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
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright 2009-2012, Ingo Weinhold, [email protected].
|
||||
* Copyright 2013, Rene Gollent, [email protected].
|
||||
* Copyright 2013-2014, Rene Gollent, [email protected].
|
||||
* 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)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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<Team::Listener> {
|
||||
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);
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
|
||||
enum {
|
||||
MSG_EVALUATE_EXPRESSION = 'evex',
|
||||
MSG_CHANGE_EVALUATION_TYPE = 'chet'
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user