mirror of
https://github.com/DoneJS-Runtime/quickjs-done-nextgen.git
synced 2025-01-09 17:43:15 +00:00
Improve line:column tracking (#660)
Emit source locations manually for more precise tracking. Don't infer them from emitted bytecode opcodes because that leads to inaccurate and sometimes surprising results. Speeds up code generation (although infinitesimally) as a bonus. Fixes: https://github.com/quickjs-ng/quickjs/issues/236
This commit is contained in:
parent
c8be383367
commit
73cc00e57e
7 changed files with 21 additions and 21 deletions
Binary file not shown.
BIN
gen/hello.c
BIN
gen/hello.c
Binary file not shown.
Binary file not shown.
BIN
gen/repl.c
BIN
gen/repl.c
Binary file not shown.
BIN
gen/test_fib.c
BIN
gen/test_fib.c
Binary file not shown.
30
quickjs.c
30
quickjs.c
|
@ -18711,8 +18711,6 @@ typedef struct JSFunctionDef {
|
|||
|
||||
DynBuf byte_code;
|
||||
int last_opcode_pos; /* -1 if no last opcode */
|
||||
int last_opcode_line_num;
|
||||
int last_opcode_col_num;
|
||||
BOOL use_short_opcodes; /* true if short opcodes are used in byte_code */
|
||||
|
||||
LabelSlot *label_slots;
|
||||
|
@ -19558,6 +19556,7 @@ static __exception int next_token(JSParseState *s)
|
|||
case '_':
|
||||
case '$':
|
||||
/* identifier */
|
||||
s->mark = p;
|
||||
p++;
|
||||
ident_has_escape = FALSE;
|
||||
has_ident:
|
||||
|
@ -19873,7 +19872,7 @@ static __exception int next_token(JSParseState *s)
|
|||
p++;
|
||||
break;
|
||||
}
|
||||
s->token.col_num = s->mark - s->eol;
|
||||
s->token.col_num = max_int(1, s->mark - s->eol);
|
||||
s->buf_ptr = p;
|
||||
|
||||
// dump_token(s, &s->token);
|
||||
|
@ -20338,22 +20337,21 @@ static void emit_u32(JSParseState *s, uint32_t val)
|
|||
dbuf_put_u32(&s->cur_func->byte_code, val);
|
||||
}
|
||||
|
||||
static void emit_source_loc(JSParseState *s)
|
||||
{
|
||||
JSFunctionDef *fd = s->cur_func;
|
||||
DynBuf *bc = &fd->byte_code;
|
||||
|
||||
dbuf_putc(bc, OP_source_loc);
|
||||
dbuf_put_u32(bc, s->last_line_num);
|
||||
dbuf_put_u32(bc, s->last_col_num);
|
||||
}
|
||||
|
||||
static void emit_op(JSParseState *s, uint8_t val)
|
||||
{
|
||||
JSFunctionDef *fd = s->cur_func;
|
||||
DynBuf *bc = &fd->byte_code;
|
||||
|
||||
/* Use the line and column number of the last token used,
|
||||
not the next token, nor the current offset in the source file.
|
||||
*/
|
||||
if (unlikely(fd->last_opcode_line_num != s->last_line_num ||
|
||||
fd->last_opcode_col_num != s->last_col_num)) {
|
||||
dbuf_putc(bc, OP_source_loc);
|
||||
dbuf_put_u32(bc, s->last_line_num);
|
||||
dbuf_put_u32(bc, s->last_col_num);
|
||||
fd->last_opcode_line_num = s->last_line_num;
|
||||
fd->last_opcode_col_num = s->last_col_num;
|
||||
}
|
||||
fd->last_opcode_pos = bc->size;
|
||||
dbuf_putc(bc, val);
|
||||
}
|
||||
|
@ -23481,6 +23479,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
|
|||
emit_atom(s, JS_ATOM_new_target);
|
||||
emit_u16(s, 0);
|
||||
} else {
|
||||
emit_source_loc(s);
|
||||
if (js_parse_postfix_expr(s, 0))
|
||||
return -1;
|
||||
accept_lparen = TRUE;
|
||||
|
@ -23580,6 +23579,7 @@ static __exception int js_parse_postfix_expr(JSParseState *s, int parse_flags)
|
|||
|
||||
if (call_type == FUNC_CALL_NORMAL) {
|
||||
parse_func_call2:
|
||||
emit_source_loc(s);
|
||||
switch(opcode = get_prev_opcode(fd)) {
|
||||
case OP_get_field:
|
||||
/* keep the object on the stack */
|
||||
|
@ -26035,6 +26035,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
|
|||
|
||||
default:
|
||||
hasexpr:
|
||||
emit_source_loc(s);
|
||||
if (js_parse_expr(s))
|
||||
goto fail;
|
||||
if (s->cur_func->eval_ret_idx >= 0) {
|
||||
|
@ -28329,7 +28330,6 @@ static JSFunctionDef *js_new_function_def(JSContext *ctx,
|
|||
js_dbuf_init(ctx, &fd->pc2line);
|
||||
//fd->pc2line_last_line_num = line_num;
|
||||
//fd->pc2line_last_pc = 0;
|
||||
fd->last_opcode_line_num = line_num;
|
||||
|
||||
fd->ic = init_ic(ctx);
|
||||
return fd;
|
||||
|
|
|
@ -7,12 +7,12 @@ function test_exception_source_pos()
|
|||
var e;
|
||||
|
||||
try {
|
||||
throw new Error(""); // line 10, column 19
|
||||
throw new Error(""); // line 10, column 15
|
||||
} catch(_e) {
|
||||
e = _e;
|
||||
}
|
||||
|
||||
assert(e.stack.includes("test_builtin.js:10:19"));
|
||||
assert(e.stack.includes("test_builtin.js:10:15"));
|
||||
}
|
||||
|
||||
// Keep this at the top; it tests source positions.
|
||||
|
@ -36,7 +36,7 @@ function test_exception_prepare_stack()
|
|||
};
|
||||
|
||||
try {
|
||||
throw new Error(""); // line 39, column 19
|
||||
throw new Error(""); // line 39, column 15
|
||||
} catch(_e) {
|
||||
e = _e;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ function test_exception_prepare_stack()
|
|||
assert(f.getFunctionName(), 'test_exception_prepare_stack');
|
||||
assert(f.getFileName().endsWith('test_builtin.js'));
|
||||
assert(f.getLineNumber(), 39);
|
||||
assert(f.getColumnNumber(), 19);
|
||||
assert(f.getColumnNumber(), 15);
|
||||
assert(!f.isNative());
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ function test_exception_stack_size_limit()
|
|||
};
|
||||
|
||||
try {
|
||||
throw new Error(""); // line 67, column 19
|
||||
throw new Error(""); // line 67, column 15
|
||||
} catch(_e) {
|
||||
e = _e;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ function test_exception_stack_size_limit()
|
|||
assert(f.getFunctionName(), 'test_exception_stack_size_limit');
|
||||
assert(f.getFileName().endsWith('test_builtin.js'));
|
||||
assert(f.getLineNumber(), 67);
|
||||
assert(f.getColumnNumber(), 19);
|
||||
assert(f.getColumnNumber(), 15);
|
||||
assert(!f.isNative());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue