Make -DDUMP_BYTECODE=64 print executed bytecode (#158)
Basically a poor man's bytecode tracer.
This commit is contained in:
parent
39c8acd312
commit
a140e1cf2c
1 changed files with 51 additions and 2 deletions
53
quickjs.c
53
quickjs.c
|
@ -81,6 +81,7 @@
|
||||||
8: dump stdlib functions
|
8: dump stdlib functions
|
||||||
16: dump bytecode in hex
|
16: dump bytecode in hex
|
||||||
32: dump line number table
|
32: dump line number table
|
||||||
|
64: dump executed bytecode
|
||||||
*/
|
*/
|
||||||
//#define DUMP_BYTECODE (1)
|
//#define DUMP_BYTECODE (1)
|
||||||
/* dump the occurence of the automatic GC */
|
/* dump the occurence of the automatic GC */
|
||||||
|
@ -14345,6 +14346,12 @@ typedef enum {
|
||||||
#define FUNC_RET_YIELD 1
|
#define FUNC_RET_YIELD 1
|
||||||
#define FUNC_RET_YIELD_STAR 2
|
#define FUNC_RET_YIELD_STAR 2
|
||||||
|
|
||||||
|
#ifdef DUMP_BYTECODE
|
||||||
|
static void dump_single_byte_code(JSContext *ctx, const uint8_t *pc,
|
||||||
|
JSFunctionBytecode *b);
|
||||||
|
static void print_func_name(JSFunctionBytecode *b);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */
|
/* argv[] is modified if (flags & JS_CALL_FLAG_COPY_ARGV) = 0. */
|
||||||
static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
JSValueConst this_obj, JSValueConst new_target,
|
JSValueConst this_obj, JSValueConst new_target,
|
||||||
|
@ -14362,8 +14369,14 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
size_t alloca_size;
|
size_t alloca_size;
|
||||||
JSInlineCache *ic;
|
JSInlineCache *ic;
|
||||||
|
|
||||||
|
#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 64)
|
||||||
|
#define DUMP_BYTECODE_OR_DONT(pc) dump_single_byte_code(ctx, pc, b);
|
||||||
|
#else
|
||||||
|
#define DUMP_BYTECODE_OR_DONT(pc)
|
||||||
|
#endif
|
||||||
|
|
||||||
#if !DIRECT_DISPATCH
|
#if !DIRECT_DISPATCH
|
||||||
#define SWITCH(pc) switch (opcode = *pc++)
|
#define SWITCH(pc) DUMP_BYTECODE_OR_DONT(pc) switch (opcode = *pc++)
|
||||||
#define CASE(op) case op
|
#define CASE(op) case op
|
||||||
#define DEFAULT default
|
#define DEFAULT default
|
||||||
#define BREAK break
|
#define BREAK break
|
||||||
|
@ -14374,7 +14387,7 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
#include "quickjs-opcode.h"
|
#include "quickjs-opcode.h"
|
||||||
[ OP_COUNT ... 255 ] = &&case_default
|
[ OP_COUNT ... 255 ] = &&case_default
|
||||||
};
|
};
|
||||||
#define SWITCH(pc) goto *dispatch_table[opcode = *pc++];
|
#define SWITCH(pc) DUMP_BYTECODE_OR_DONT(pc) goto *dispatch_table[opcode = *pc++];
|
||||||
#define CASE(op) case_ ## op
|
#define CASE(op) case_ ## op
|
||||||
#define DEFAULT case_default
|
#define DEFAULT case_default
|
||||||
#define BREAK SWITCH(pc)
|
#define BREAK SWITCH(pc)
|
||||||
|
@ -14465,6 +14478,10 @@ static JSValue JS_CallInternal(JSContext *caller_ctx, JSValueConst func_obj,
|
||||||
ctx = b->realm; /* set the current realm */
|
ctx = b->realm; /* set the current realm */
|
||||||
ic = b->ic;
|
ic = b->ic;
|
||||||
|
|
||||||
|
#if defined(DUMP_BYTECODE) && (DUMP_BYTECODE & 64)
|
||||||
|
print_func_name(b);
|
||||||
|
#endif
|
||||||
|
|
||||||
restart:
|
restart:
|
||||||
for(;;) {
|
for(;;) {
|
||||||
int call_argc;
|
int call_argc;
|
||||||
|
@ -27252,6 +27269,38 @@ static void dump_byte_code(JSContext *ctx, int pass,
|
||||||
js_free(ctx, bits);
|
js_free(ctx, bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// caveat emptor: intended to be called during execution of bytecode
|
||||||
|
// and only works for pass3 bytecode
|
||||||
|
static __maybe_unused void dump_single_byte_code(JSContext *ctx,
|
||||||
|
const uint8_t *pc,
|
||||||
|
JSFunctionBytecode *b)
|
||||||
|
{
|
||||||
|
JSVarDef *args, *vars;
|
||||||
|
int line_num;
|
||||||
|
|
||||||
|
args = vars = b->vardefs;
|
||||||
|
if (vars)
|
||||||
|
vars = &vars[b->arg_count];
|
||||||
|
|
||||||
|
line_num = -1;
|
||||||
|
if (b->has_debug)
|
||||||
|
line_num = b->debug.line_num;
|
||||||
|
|
||||||
|
dump_byte_code(ctx, /*pass*/3, pc, short_opcode_info(*pc).size,
|
||||||
|
args, b->arg_count, vars, b->var_count,
|
||||||
|
b->closure_var, b->closure_var_count,
|
||||||
|
b->cpool, b->cpool_count,
|
||||||
|
NULL, line_num,
|
||||||
|
NULL, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __maybe_unused void print_func_name(JSFunctionBytecode *b)
|
||||||
|
{
|
||||||
|
if (b->has_debug)
|
||||||
|
if (b->debug.source)
|
||||||
|
print_lines(b->debug.source, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int len,
|
static __maybe_unused void dump_pc2line(JSContext *ctx, const uint8_t *buf, int len,
|
||||||
int line_num)
|
int line_num)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue