Commit 3775f6dc by Ben Clayton

Vulkan/Debug: Expose Frames from Thread

Previously Frame was an Thread-internally managed structure, with special accessors for the variable containers of the top most frame. With this change, the Frame can be modified by calling `Thread::update()`. This allows for more powerful edits of the frame, while still preserving a mutex lock over the structure. Bug: b/145351270 Change-Id: I81e87884e26bdd6f22b47e8f71b37bbfc91c7830 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/39882 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarAntonio Maiorano <amaiorano@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent f97fb9df
...@@ -293,9 +293,9 @@ std::vector<std::shared_ptr<File>> Context::Lock::files() ...@@ -293,9 +293,9 @@ std::vector<std::shared_ptr<File>> Context::Lock::files()
} }
std::shared_ptr<Frame> Context::Lock::createFrame( std::shared_ptr<Frame> Context::Lock::createFrame(
const std::shared_ptr<File> &file) const std::shared_ptr<File> &file, std::string function)
{ {
auto frame = std::make_shared<Frame>(ctx->nextFrameID++); auto frame = std::make_shared<Frame>(ctx->nextFrameID++, std::move(function));
ctx->frames.add(frame->id, frame); ctx->frames.add(frame->id, frame);
frame->arguments = createScope(file); frame->arguments = createScope(file);
frame->locals = createScope(file); frame->locals = createScope(file);
......
...@@ -89,9 +89,10 @@ public: ...@@ -89,9 +89,10 @@ public:
// files() returns the full list of files. // files() returns the full list of files.
std::vector<std::shared_ptr<File>> files(); std::vector<std::shared_ptr<File>> files();
// createFrame() returns a new frame for the given file. // createFrame() returns a new frame for the given file and function
// name.
std::shared_ptr<Frame> createFrame( std::shared_ptr<Frame> createFrame(
const std::shared_ptr<File> &file); const std::shared_ptr<File> &file, std::string function);
// get() returns the frame with the given ID, or null if the frame // get() returns the frame with the given ID, or null if the frame
// does not exist or no longer has any external shared_ptr references. // does not exist or no longer has any external shared_ptr references.
......
...@@ -26,17 +26,32 @@ class File; ...@@ -26,17 +26,32 @@ class File;
struct Location struct Location
{ {
Location() = default; Location() = default;
inline Location(int line, const std::shared_ptr<File> &file); inline Location(const std::shared_ptr<File> &file, int line, int column = 0);
inline bool operator==(const Location &o) const;
inline bool operator!=(const Location &o) const;
int line = 0; // 1 based. 0 represents no line.
std::shared_ptr<File> file; std::shared_ptr<File> file;
int line = 0; // 1 based. 0 represents no line.
int column = 0; // 1 based. 0 represents no particular column.
}; };
Location::Location(int line, const std::shared_ptr<File> &file) Location::Location(const std::shared_ptr<File> &file, int line, int column /* = 0 */)
: line(line) : file(file)
, file(file) , line(line)
, column(column)
{} {}
bool Location::operator==(const Location &o) const
{
return file == o.file && line == o.line && column == o.column;
}
bool Location::operator!=(const Location &o) const
{
return !(*this == o);
}
} // namespace dbg } // namespace dbg
} // namespace vk } // namespace vk
......
...@@ -198,8 +198,9 @@ Server::Impl::Impl(const std::shared_ptr<Context> &context, int port) ...@@ -198,8 +198,9 @@ Server::Impl::Impl(const std::shared_ptr<Context> &context, int port)
dap::StackTraceResponse response; dap::StackTraceResponse response;
response.totalFrames = stack.size(); response.totalFrames = stack.size();
response.stackFrames.reserve(stack.size()); response.stackFrames.reserve(stack.size());
for(auto const &frame : stack) for(int i = static_cast<int>(stack.size()) - 1; i >= 0; i--)
{ {
auto const &frame = stack[i];
auto const &loc = frame.location; auto const &loc = frame.location;
dap::StackFrame sf; dap::StackFrame sf;
sf.column = 0; sf.column = 0;
......
...@@ -38,10 +38,9 @@ std::string Thread::name() const ...@@ -38,10 +38,9 @@ std::string Thread::name() const
return name_; return name_;
} }
void Thread::update(const Location &location) void Thread::onLocationUpdate(std::unique_lock<std::mutex> &lock)
{ {
std::unique_lock<std::mutex> lock(mutex); auto location = frames.back()->location;
frames.back()->location = location;
if(state_ == State::Running) if(state_ == State::Running)
{ {
...@@ -79,11 +78,10 @@ void Thread::update(const Location &location) ...@@ -79,11 +78,10 @@ void Thread::update(const Location &location)
void Thread::enter(Context::Lock &ctxlck, const std::shared_ptr<File> &file, const std::string &function) void Thread::enter(Context::Lock &ctxlck, const std::shared_ptr<File> &file, const std::string &function)
{ {
auto frame = ctxlck.createFrame(file); auto frame = ctxlck.createFrame(file, function);
auto isFunctionBreakpoint = ctxlck.isFunctionBreakpoint(function); auto isFunctionBreakpoint = ctxlck.isFunctionBreakpoint(function);
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
frame->function = function;
frames.push_back(frame); frames.push_back(frame);
if(isFunctionBreakpoint) if(isFunctionBreakpoint)
{ {
...@@ -98,28 +96,22 @@ void Thread::exit() ...@@ -98,28 +96,22 @@ void Thread::exit()
frames.pop_back(); frames.pop_back();
} }
std::shared_ptr<VariableContainer> Thread::registers() const void Thread::update(std::function<void(Frame &)> f)
{
std::unique_lock<std::mutex> lock(mutex);
return frames.back()->registers->variables;
}
std::shared_ptr<VariableContainer> Thread::locals() const
{ {
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
return frames.back()->locals->variables; auto &frame = *frames.back();
} auto oldLocation = frame.location;
f(frame);
std::shared_ptr<VariableContainer> Thread::arguments() const if(frame.location != oldLocation)
{ {
std::unique_lock<std::mutex> lock(mutex); onLocationUpdate(lock);
return frames.back()->arguments->variables; }
} }
std::shared_ptr<VariableContainer> Thread::hovers() const Frame Thread::frame() const
{ {
std::unique_lock<std::mutex> lock(mutex); std::unique_lock<std::mutex> lock(mutex);
return frames.back()->hovers->variables; return *frames.back();
} }
std::vector<Frame> Thread::stack() const std::vector<Frame> Thread::stack() const
......
...@@ -70,13 +70,13 @@ class Frame ...@@ -70,13 +70,13 @@ class Frame
public: public:
using ID = dbg::ID<Frame>; using ID = dbg::ID<Frame>;
inline Frame(ID id); inline Frame(ID id, std::string function);
// The unique identifier of the stack frame. // The unique identifier of the stack frame.
const ID id; const ID id;
// The name of function for this stack frame. // The name of function for this stack frame.
std::string function; const std::string function;
// The current execution location within the stack frame. // The current execution location within the stack frame.
Location location; Location location;
...@@ -94,8 +94,9 @@ public: ...@@ -94,8 +94,9 @@ public:
std::shared_ptr<Scope> hovers; std::shared_ptr<Scope> hovers;
}; };
Frame::Frame(ID id) Frame::Frame(ID id, std::string function)
: id(id) : id(id)
, function(std::move(function))
{} {}
// Thread holds the state for a single thread of execution. // Thread holds the state for a single thread of execution.
...@@ -127,17 +128,8 @@ public: ...@@ -127,17 +128,8 @@ public:
// exit() pops the thread's stack frame. // exit() pops the thread's stack frame.
void exit(); void exit();
// registers() returns the thread's current stack frame's register variables. // frame() returns a copy of the thread's top most stack frame.
std::shared_ptr<VariableContainer> registers() const; Frame frame() const;
// locals() returns the thread's current stack frame's local variables.
std::shared_ptr<VariableContainer> locals() const;
// arguments() returns the thread's current stack frame's argument variables.
std::shared_ptr<VariableContainer> arguments() const;
// hovers() returns the thread's current stack frame's hover variables.
std::shared_ptr<VariableContainer> hovers() const;
// stack() returns a copy of the thread's current stack frames. // stack() returns a copy of the thread's current stack frames.
std::vector<Frame> stack() const; std::vector<Frame> stack() const;
...@@ -145,6 +137,11 @@ public: ...@@ -145,6 +137,11 @@ public:
// state() returns the current thread's state. // state() returns the current thread's state.
State state() const; State state() const;
// update() calls f to modify the top most frame of the stack.
// If the frame's location is changed, update() potentially blocks until the
// thread is resumed with one of the methods below.
void update(std::function<void(Frame &)> f);
// resume() resumes execution of the thread by unblocking a call to // resume() resumes execution of the thread by unblocking a call to
// update() and setting the thread's state to State::Running. // update() and setting the thread's state to State::Running.
void resume(); void resume();
...@@ -170,16 +167,14 @@ public: ...@@ -170,16 +167,14 @@ public:
// suspend execution again. // suspend execution again.
void stepOut(); void stepOut();
// update() updates the current stack frame's location, and potentially
// blocks until the thread is resumed with one of the methods above.
void update(const Location &location);
// The unique identifier of the thread. // The unique identifier of the thread.
const ID id; const ID id;
private: private:
EventListener *const broadcast; EventListener *const broadcast;
void onLocationUpdate(std::unique_lock<std::mutex> &lock);
mutable std::mutex mutex; mutable std::mutex mutex;
std::string name_; std::string name_;
std::vector<std::shared_ptr<Frame>> frames; std::vector<std::shared_ptr<Frame>> frames;
......
...@@ -1785,7 +1785,9 @@ void CommandBuffer::submit(CommandBuffer::ExecutionState &executionState) ...@@ -1785,7 +1785,9 @@ void CommandBuffer::submit(CommandBuffer::ExecutionState &executionState)
#ifdef ENABLE_VK_DEBUGGER #ifdef ENABLE_VK_DEBUGGER
if(debuggerThread) if(debuggerThread)
{ {
debuggerThread->update({ line++, debuggerFile }); debuggerThread->update([&](vk::dbg::Frame &frame) {
frame.location = { debuggerFile, line++, 0 };
});
} }
#endif // ENABLE_VK_DEBUGGER #endif // ENABLE_VK_DEBUGGER
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment