Move and expose dumpStack for use in debuggers

This commit is contained in:
K. Lange 2021-03-04 08:05:59 +09:00
parent 3daf95bd47
commit 37353c2b88
4 changed files with 68 additions and 60 deletions

View File

@ -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 */

View File

@ -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
*

View File

@ -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

View File

@ -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));
}