Skip to content

Commit

Permalink
refactor: extract the static functions and VM registry module of Lua
Browse files Browse the repository at this point in the history
  • Loading branch information
sssooonnnggg committed Nov 27, 2024
1 parent 856924a commit 6af239f
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 155 deletions.
2 changes: 2 additions & 0 deletions debugger/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ target_sources(${library_name}
src/internal/breakpoint.cpp
src/internal/file.cpp
src/internal/debug_bridge.cpp
src/internal/lua_statics.cpp
src/internal/variable.cpp
src/internal/variable_registry.cpp
src/internal/vm_registry.cpp
src/internal/utils/lua_utils.cpp
)

Expand Down
144 changes: 14 additions & 130 deletions debugger/src/internal/debug_bridge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,102 +10,24 @@
#include <lualib.h>

#include <dap/protocol.h>
#include <dap/session.h>
#include <dap/types.h>

#include <dap/session.h>
#include <internal/breakpoint.h>
#include <internal/debug_bridge.h>
#include <internal/file.h>
#include <internal/log.h>
#include <internal/lua_statics.h>
#include <internal/utils.h>
#include <internal/variable.h>

#include "debugger.h"

namespace luau::debugger {

class LuaCallbacks {
public:
static void debugbreak(lua_State* L, lua_Debug* ar) {
auto bridge = DebugBridge::getDebugBridge(L);
if (bridge == nullptr)
return;
bridge->onDebugBreak(L, ar,
bridge->isBreakOnEntry(L)
? DebugBridge::BreakReason::Entry
: DebugBridge::BreakReason::BreakPoint);
};

static void interrupt(lua_State* L, int gc) {
auto bridge = DebugBridge::getDebugBridge(L);
if (bridge == nullptr)
return;
bridge->interruptUpdate();
};

static void userthread(lua_State* LP, lua_State* L) {
auto bridge = DebugBridge::getDebugBridge(L);
if (bridge == nullptr)
return;

if (LP == nullptr)
bridge->markDead(L);
else
bridge->markAlive(L, LP);
};

static void debugstep(lua_State* L, lua_Debug* ar) {
auto bridge = DebugBridge::getDebugBridge(L);
if (bridge == nullptr)
return;
if (bridge->single_step_processor_ != nullptr)
if ((bridge->single_step_processor_)(L, ar))
bridge->onDebugBreak(L, ar, DebugBridge::BreakReason::Step);
};

static int print(lua_State* L) {
int lua_print = lua_upvalueindex(1);

int args = lua_gettop(L);
int begin = lua_absindex(L, -args);
int end = lua_absindex(L, -1) + 1;

lua_checkstack(L, args + 1);
lua_pushvalue(L, lua_print);
for (int i = begin; i < end; ++i)
lua_pushvalue(L, i);

lua_call(L, args, 0);

auto bridge = DebugBridge::getDebugBridge(L);
if (bridge == nullptr)
return 0;

int n = lua_gettop(L);
std::string output;
for (int i = 1; i <= n; i++) {
size_t l;
const char* s = luaL_tolstring(L, i, &l);
if (i > 1)
output += "\t";
output.append(s, l);
lua_pop(L, 1); // pop result
}
output += "\n";

bridge->writeDebugConsole(output, L, 1);
return 0;
}
};

DebugBridge::DebugBridge(bool stop_on_entry) : stop_on_entry_(stop_on_entry) {}

DebugBridge::~DebugBridge() {
for (auto L : lua_vms_)
lua_setthreaddata(L, nullptr);
}

DebugBridge* DebugBridge::getDebugBridge(lua_State* L) {
DebugBridge* DebugBridge::get(lua_State* L) {
lua_State* main_vm = lua_mainthread(L);
auto* debugger = reinterpret_cast<Debugger*>(lua_getthreaddata(main_vm));
if (debugger == nullptr)
Expand All @@ -114,20 +36,19 @@ DebugBridge* DebugBridge::getDebugBridge(lua_State* L) {
}

void DebugBridge::initialize(lua_State* L) {
lua_vms_.push_back(L);
vm_registry_.registerVM(L);

initializeCallbacks(L);
captureOutput(L);

lua_singlestep(L, true);
markAlive(L, nullptr);
}

void DebugBridge::initializeCallbacks(lua_State* L) {
lua_Callbacks* cb = lua_callbacks(L);
cb->debugbreak = LuaCallbacks::debugbreak;
cb->interrupt = LuaCallbacks::interrupt;
cb->userthread = LuaCallbacks::userthread;
cb->debugbreak = LuaStatics::debugbreak;
cb->interrupt = LuaStatics::interrupt;
cb->userthread = LuaStatics::userthread;
}

void DebugBridge::captureOutput(lua_State* L) {
Expand All @@ -136,7 +57,7 @@ void DebugBridge::captureOutput(lua_State* L) {
lua_setreadonly(L, LUA_GLOBALSINDEX, false);
lua_getglobal(L, global_print);
if (lua_isfunction(L, -1)) {
lua_pushcclosure(L, LuaCallbacks::print, "debugprint", 1);
lua_pushcclosure(L, LuaStatics::print, "debugprint", 1);
lua_setglobal(L, global_print);
}
lua_setreadonly(L, LUA_GLOBALSINDEX, enable);
Expand Down Expand Up @@ -369,10 +290,10 @@ BreakContext DebugBridge::getBreakContext(lua_State* L) const {

int DebugBridge::getStackDepth(lua_State* L) const {
int depth = lua_stackdepth(L);
auto* parent = getParent(L);
auto* parent = vm_registry_.getParent(L);
while (parent != nullptr) {
depth += lua_stackdepth(parent);
parent = getParent(parent);
parent = vm_registry_.getParent(parent);
}
return depth;
}
Expand Down Expand Up @@ -444,12 +365,12 @@ void DebugBridge::stepOver() {
auto old_ctx = getBreakContext(break_vm_);
processSingleStep([this, old_ctx](lua_State* L, lua_Debug* ar) -> bool {
// Step over yield boundary
if (isAlive(old_ctx.L_) && old_ctx.L_->status == LUA_YIELD)
if (vm_registry_.isAlive(old_ctx.L_) && old_ctx.L_->status == LUA_YIELD)
return false;

auto ctx = getBreakContext(L);

if (L != old_ctx.L_ && !isChild(old_ctx.L_, L))
if (L != old_ctx.L_ && !vm_registry_.isChild(old_ctx.L_, L))
return false;

// Normal step over
Expand All @@ -465,14 +386,14 @@ void DebugBridge::processSingleStep(SingleStepProcessor processor) {
}

void DebugBridge::enableDebugStep(bool enable) {
lua_State* L = getRoot(break_vm_);
lua_State* L = vm_registry_.getRoot(break_vm_);
auto callbacks = lua_callbacks(L);
if (!enable) {
callbacks->debugstep = nullptr;
return;
}

callbacks->debugstep = LuaCallbacks::debugstep;
callbacks->debugstep = LuaStatics::debugstep;
}

void DebugBridge::resumeInternal() {
Expand Down Expand Up @@ -548,43 +469,6 @@ ResponseOrError<EvaluateResponse> DebugBridge::evalWithEnv(
return response;
}

bool DebugBridge::isAlive(lua_State* L) const {
return alive_threads_.find(L) != alive_threads_.end();
}

lua_State* DebugBridge::getParent(lua_State* L) const {
auto it = alive_threads_.find(L);
if (it == alive_threads_.end())
return nullptr;
return it->second;
}

lua_State* DebugBridge::getRoot(lua_State* L) const {
lua_State* current = L;
while (auto* p = getParent(current))
current = p;
return current;
}

bool DebugBridge::isChild(lua_State* L, lua_State* parent) const {
lua_State* current = L;
while (auto* p = getParent(current)) {
if (p == parent)
return true;
else
current = p;
}
return false;
}

void DebugBridge::markAlive(lua_State* L, lua_State* parent) {
alive_threads_[L] = parent;
}

void DebugBridge::markDead(lua_State* L) {
alive_threads_.erase(L);
}

void DebugBridge::writeDebugConsole(std::string_view output,
lua_State* L,
int level) {
Expand Down
22 changes: 8 additions & 14 deletions debugger/src/internal/debug_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@

#include <internal/breakpoint.h>
#include <internal/file.h>
#include <internal/lua_statics.h>
#include <internal/variable.h>
#include <internal/variable_registry.h>
#include <internal/vm_registry.h>

namespace luau::debugger {

Expand All @@ -31,9 +33,8 @@ using namespace dap;
class LuaCallbacks;
class DebugBridge final {
public:
static DebugBridge* getDebugBridge(lua_State* L);
static DebugBridge* get(lua_State* L);
DebugBridge(bool stop_on_entry);
~DebugBridge();

void initialize(lua_State* L);
bool isDebugBreak();
Expand Down Expand Up @@ -103,6 +104,8 @@ class DebugBridge final {

void writeDebugConsole(std::string_view msg, lua_State* L, int level = 0);

VMRegistry& vms() { return vm_registry_; }

private:
void initializeCallbacks(lua_State* L);
void captureOutput(lua_State* L);
Expand Down Expand Up @@ -136,20 +139,14 @@ class DebugBridge final {

ResponseOrError<EvaluateResponse> evalWithEnv(const EvaluateRequest& request);

bool isAlive(lua_State* L) const;
bool isChild(lua_State* L, lua_State* parent) const;
lua_State* getParent(lua_State* L) const;
lua_State* getRoot(lua_State* L) const;
void markAlive(lua_State* L, lua_State* parent);
void markDead(lua_State* L);

private:
friend class LuaCallbacks;
friend class LuaStatics;

VMRegistry vm_registry_;

bool stop_on_entry_ = false;
std::string entry_path_;

std::vector<lua_State*> lua_vms_;
std::unordered_map<std::string, File> files_;
lua_State* break_vm_ = nullptr;

Expand All @@ -166,8 +163,5 @@ class DebugBridge final {
std::mutex deferred_mutex_;

SingleStepProcessor single_step_processor_ = nullptr;

// Record alive threads with its parent
std::unordered_map<lua_State*, lua_State*> alive_threads_;
};
} // namespace luau::debugger
10 changes: 0 additions & 10 deletions debugger/src/internal/file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,6 @@ void File::addBreakPoint(int line) {
}
}

void File::removeBreakPoint(int line) {
auto it = breakpoints_.find(line);
if (it != breakpoints_.end()) {
DEBUGGER_LOG_INFO("Remove breakpoint: {}:{}", path_, line);
BreakPoint& bp = it->second;
enableBreakPoint(bp, false);
breakpoints_.erase(it);
}
}

void File::clearBreakPoints() {
DEBUGGER_LOG_INFO("Clear all breakpoints: {}", path_);
for (auto& [line, bp] : breakpoints_)
Expand Down
1 change: 0 additions & 1 deletion debugger/src/internal/file.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ class File {
void addRef(FileRef ref);

void addBreakPoint(int line);
void removeBreakPoint(int line);
void clearBreakPoints();

template <class Predicate>
Expand Down
Loading

0 comments on commit 6af239f

Please sign in to comment.