Make -DDUMP_BYTECODE=64 print executed bytecode (#158)

Basically a poor man's bytecode tracer.
This commit is contained in:
Ben Noordhuis 2023-11-29 23:53:01 +01:00 committed by GitHub
parent 39c8acd312
commit a140e1cf2c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

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