ref: 5ce44f9d4a73250fefc15a6102e60773f7b3b8db
parent: 10ffd559dea1f37fe3f0b7d6a5b179b956ebd2b5
author: Tor Andersson <tor@ccxvii.net>
date: Fri Jan 17 11:00:51 EST 2014
Remember file name and line where a function object came from. Make "debugger" statement useful: dump current function bytecode, stack, and environment scope chain.
--- a/jscompile.c
+++ b/jscompile.c
@@ -18,7 +18,8 @@
js_Function *F = malloc(sizeof *F);
memset(F, 0, sizeof *F);
- F->name = name ? name->string : "<anonymous>";
+ F->filename = js_intern(J, J->filename);
+ F->line = name ? name->line : params ? params->line : body->line;
F->next = J->fun;
J->fun = F;
@@ -727,8 +728,11 @@
static void cfunbody(JF, js_Ast *name, js_Ast *params, js_Ast *body)
{
if (name) {
+ F->name = name->string;
emitfunction(J, F, F);
emitstring(J, F, OP_FUNDEC, name->string);
+ } else {
+ F->name = "<anonymous>";
}
cparams(J, F, params);
--- a/jscompile.h
+++ b/jscompile.h
@@ -90,6 +90,7 @@
struct js_Function
{
const char *name;
+
int numparams;
const char **params;
@@ -104,6 +105,9 @@
const char **strtab;
int strcap, strlen;
+
+ const char *filename;
+ int line;
js_Function *next; /* alloc list */
};
--- a/jsdump.c
+++ b/jsdump.c
@@ -599,12 +599,12 @@
for (i = 0; i < F->numparams; ++i)
printf("%s%s", i > 0 ? ", " : "", F->params[i]);
printf(")\n");
+ printf("\tsource %s:%d\n", F->filename, F->line);
for (i = 0; i < F->funlen; ++i)
printf("\tfunction %p %s\n", F->funtab[i], F->funtab[i]->name);
for (i = 0; i < F->strlen; ++i) {
ps("\tstring "); pstr(F->strtab[i]); ps("\n");
}
- // TODO: regexp
for (i = 0; i < F->numlen; ++i)
printf("\tnumber %.9g\n", F->numtab[i]);
@@ -652,7 +652,6 @@
for (i = 0; i < F->funlen; ++i) {
if (F->funtab[i] != F) {
- nl();
jsC_dumpfunction(J, F->funtab[i]);
}
}
@@ -672,7 +671,14 @@
switch (v.u.object->type) {
case JS_COBJECT: printf("object(%p)", v.u.object); break;
case JS_CARRAY: printf("array(%p)", v.u.object); break;
- case JS_CFUNCTION: printf("function(%s)", v.u.object->function->name); break;
+ case JS_CFUNCTION:
+ printf("function(%p, %s, %s:%d)",
+ v.u.object,
+ v.u.object->function->name,
+ v.u.object->function->filename,
+ v.u.object->function->line);
+ break;
+ case JS_CSCRIPT: printf("script(%s)", v.u.object->function->filename); break;
case JS_CCFUNCTION: printf("cfunction(%p)", v.u.object->cfunction); break;
case JS_CBOOLEAN: printf("boolean(%d)", v.u.object->primitive.boolean); break;
case JS_CNUMBER: printf("number(%g)", v.u.object->primitive.number); break;
--- a/jsrun.c
+++ b/jsrun.c
@@ -386,21 +386,36 @@
/* Main interpreter loop */
-void js_dumpstack(js_State *J)
+void jsR_dumpstack(js_State *J)
{
int i;
+ printf("stack {\n");
for (i = 0; i < top; ++i) {
- printf("stack %d: ", i);
+ putchar(i == bot ? '>' : ' ');
+ printf("% 3d: ", i);
js_dumpvalue(J, stack[i]);
putchar('\n');
}
+ printf("}\n");
}
-void js_trap(js_State *J)
+void jsR_dumpenvironment(js_State *J, js_Environment *E, int d)
{
- fprintf(stderr, "trap!\n");
+ printf("scope %d ", d);
+ js_dumpobject(J, E->variables);
+ if (E->outer)
+ jsR_dumpenvironment(J, E->outer, d+1);
}
+void js_trap(js_State *J, int pc)
+{
+ fprintf(stderr, "trap at %d in ", pc);
+ js_Function *F = stack[bot-1].u.object->function;
+ jsC_dumpfunction(J, F);
+ jsR_dumpstack(J);
+ jsR_dumpenvironment(J, J->E, 0);
+}
+
static void jsR_run(js_State *J, js_Function *F)
{
js_Function **FT = F->funtab;
@@ -691,7 +706,7 @@
/* Branching */
case OP_DEBUGGER:
- js_trap(J);
+ js_trap(J, (int)(pc - pcstart) - 1);
break;
case OP_JUMP: