Move and expose dumpStack for use in debuggers
This commit is contained in:
parent
3daf95bd47
commit
37353c2b88
51
src/debug.c
51
src/debug.c
@ -6,6 +6,57 @@
|
||||
#include "util.h"
|
||||
#include "compiler.h"
|
||||
|
||||
/**
|
||||
* When tracing is enabled, we will present the elements on the stack with
|
||||
* a safe printer; the format of values printed by krk_printValueSafe will
|
||||
* look different from those printed by printValue, but they guarantee that
|
||||
* the VM will never be called to produce a string, which would result in
|
||||
* a nasty infinite recursion if we did it while trying to trace the VM!
|
||||
*/
|
||||
void krk_debug_dumpStack(FILE * file, KrkCallFrame * frame) {
|
||||
size_t i = 0;
|
||||
for (KrkValue * slot = krk_currentThread.stack; slot < krk_currentThread.stackTop; slot++) {
|
||||
fprintf(file, "[%c", frame->slots == i ? '*' : ' ');
|
||||
|
||||
for (size_t x = krk_currentThread.frameCount; x > 0; x--) {
|
||||
if (krk_currentThread.frames[x-1].slots > i) continue;
|
||||
KrkCallFrame * f = &krk_currentThread.frames[x-1];
|
||||
size_t relative = i - f->slots;
|
||||
|
||||
/* Figure out the name of this value */
|
||||
if (relative < (size_t)f->closure->function->requiredArgs) {
|
||||
fprintf(file, "%s=", AS_CSTRING(f->closure->function->requiredArgNames.values[relative]));
|
||||
break;
|
||||
} else if (relative < (size_t)f->closure->function->requiredArgs + (size_t)f->closure->function->keywordArgs) {
|
||||
fprintf(file, "%s=", AS_CSTRING(f->closure->function->keywordArgNames.values[relative - f->closure->function->requiredArgs]));
|
||||
break;
|
||||
} else {
|
||||
int found = 0;
|
||||
for (size_t j = 0; j < f->closure->function->localNameCount; ++j) {
|
||||
if (relative == f->closure->function->localNames[j].id
|
||||
/* Only display this name if it's currently valid */
|
||||
&& f->closure->function->localNames[j].birthday <= (size_t)(f->ip - f->closure->function->chunk.code)
|
||||
) {
|
||||
fprintf(file, "%s=", f->closure->function->localNames[j].name->chars);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
}
|
||||
|
||||
krk_printValueSafe(file, *slot);
|
||||
fprintf(file, " ]");
|
||||
i++;
|
||||
}
|
||||
if (i == frame->slots) {
|
||||
fprintf(file, " * ");
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
|
||||
void krk_disassembleCodeObject(FILE * f, KrkFunction * func, const char * name) {
|
||||
KrkChunk * chunk = &func->chunk;
|
||||
/* Function header */
|
||||
|
@ -211,6 +211,15 @@ extern void krk_debug_dumpTraceback(void);
|
||||
*/
|
||||
extern int krk_debug_examineBreakpoint(int breakIndex, KrkFunction ** funcOut, size_t * offsetOut, int * flagsOut, int *enabledOut);
|
||||
|
||||
/**
|
||||
* @brief Print the elements on the stack.
|
||||
*
|
||||
* Prints the elements on the stack for the current thread to @p file,
|
||||
* highlighting @p frame as the activate call point and indicating
|
||||
* where its arguments start.
|
||||
*/
|
||||
extern void krk_debug_dumpStack(FILE * f, KrkCallFrame * frame);
|
||||
|
||||
/**
|
||||
* @def KRK_BREAKPOINT_NORMAL
|
||||
*
|
||||
|
@ -293,6 +293,8 @@ static int debuggerHook(KrkCallFrame * frame) {
|
||||
frame->closure->function,
|
||||
(size_t)(frame->ip - frame->closure->function->chunk.code));
|
||||
|
||||
krk_debug_dumpStack(stderr, frame);
|
||||
|
||||
while (1) {
|
||||
char buf[4096] = {0};
|
||||
#ifndef NO_RLINE
|
||||
|
66
src/vm.c
66
src/vm.c
@ -78,10 +78,11 @@ KrkThreadState krk_currentThread;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When threading is enabled, `krk_currentThread` becomes
|
||||
* a macro to call this outside of `vm.c` - we reference
|
||||
* the static TLS version above locally. When threading
|
||||
* is not enabled, there is a global `krk_currentThread`.
|
||||
* In some threading configurations, particular on Windows,
|
||||
* we can't have executables reference our thread-local thread
|
||||
* state object directly; in order to provide a consistent API
|
||||
* we make @ref krk_currentThread a macro outside of the core
|
||||
* sources that will call this function.
|
||||
*/
|
||||
KrkThreadState * krk_getCurrentThread(void) {
|
||||
return &krk_currentThread;
|
||||
@ -104,61 +105,6 @@ void krk_resetStack() {
|
||||
krk_currentThread.currentException = NONE_VAL();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TRACING
|
||||
/**
|
||||
* When tracing is enabled, we will present the elements on the stack with
|
||||
* a safe printer; the format of values printed by krk_printValueSafe will
|
||||
* look different from those printed by printValue, but they guarantee that
|
||||
* the VM will never be called to produce a string, which would result in
|
||||
* a nasty infinite recursion if we did it while trying to trace the VM!
|
||||
*/
|
||||
static void dumpStack(KrkCallFrame * frame) {
|
||||
fprintf(stderr, " | ");
|
||||
size_t i = 0;
|
||||
for (KrkValue * slot = krk_currentThread.stack; slot < krk_currentThread.stackTop; slot++) {
|
||||
fprintf(stderr, "[ ");
|
||||
if (i == frame->slots) fprintf(stderr, "*");
|
||||
|
||||
for (size_t x = krk_currentThread.frameCount; x > 0; x--) {
|
||||
if (krk_currentThread.frames[x-1].slots > i) continue;
|
||||
KrkCallFrame * f = &krk_currentThread.frames[x-1];
|
||||
size_t relative = i - f->slots;
|
||||
//fprintf(stderr, "(%s[%d])", f->closure->function->name->chars, (int)relative);
|
||||
/* Should resolve here? */
|
||||
if (relative < (size_t)f->closure->function->requiredArgs) {
|
||||
fprintf(stderr, "%s=", AS_CSTRING(f->closure->function->requiredArgNames.values[relative]));
|
||||
break;
|
||||
} else if (relative < (size_t)f->closure->function->requiredArgs + (size_t)f->closure->function->keywordArgs) {
|
||||
fprintf(stderr, "%s=", AS_CSTRING(f->closure->function->keywordArgNames.values[relative - f->closure->function->requiredArgs]));
|
||||
break;
|
||||
} else {
|
||||
int found = 0;
|
||||
for (size_t j = 0; j < f->closure->function->localNameCount; ++j) {
|
||||
if (relative == f->closure->function->localNames[j].id
|
||||
/* Only display this name if it's currently valid */
|
||||
&& f->closure->function->localNames[j].birthday <= (size_t)(f->ip - f->closure->function->chunk.code)
|
||||
) {
|
||||
fprintf(stderr,"%s=", f->closure->function->localNames[j].name->chars);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
krk_printValueSafe(stderr, *slot);
|
||||
fprintf(stderr, " ]");
|
||||
i++;
|
||||
}
|
||||
if (i == frame->slots) {
|
||||
fprintf(stderr, " * ");
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Display a traceback by scanning up the stack / call frames.
|
||||
* The format of the output here is modeled after the output
|
||||
@ -1846,7 +1792,7 @@ static KrkValue run() {
|
||||
while (1) {
|
||||
#ifdef ENABLE_TRACING
|
||||
if (krk_currentThread.flags & KRK_THREAD_ENABLE_TRACING) {
|
||||
dumpStack(frame);
|
||||
krk_debug_dumpStack(stderr, frame);
|
||||
krk_disassembleInstruction(stderr, frame->closure->function,
|
||||
(size_t)(frame->ip - frame->closure->function->chunk.code));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user