Skip to content

Commit

Permalink
Error on bytecodes longer than 0xFFFF (fix #269)
Browse files Browse the repository at this point in the history
This lets us use uint16_t for the program counter. JVM
languages have the same limit on method size so it is a
reasonable limit.
  • Loading branch information
dtolnay committed Jul 26, 2015
1 parent 8295baf commit 21309bc
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 7 deletions.
16 changes: 11 additions & 5 deletions compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,7 @@ static int expand_call_arglist(block* b) {
return errors;
}

static int compile(struct bytecode* bc, block b) {
static int compile(struct bytecode* bc, block b, struct locfile* lf) {
int errors = 0;
int pos = 0;
int var_frame_idx = 0;
Expand Down Expand Up @@ -1088,6 +1088,13 @@ static int compile(struct bytecode* bc, block b) {
curr->imm.intval = idx;
}
}
if (pos > 0xFFFF) {
// too long for program counter to fit in uint16_t
locfile_locate(lf, UNKNOWN_LOCATION,
"function compiled to %d bytes which is too long", pos);
errors++;
}
bc->codelen = pos;
bc->debuginfo = jv_object_set(bc->debuginfo, jv_string("locals"), localnames);
if (bc->nsubfunctions) {
bc->subfunctions = jv_mem_alloc(sizeof(struct bytecode*) * bc->nsubfunctions);
Expand All @@ -1108,14 +1115,13 @@ static int compile(struct bytecode* bc, block b) {
params = jv_array_append(params, jv_string(param->symbol));
}
subfn->debuginfo = jv_object_set(subfn->debuginfo, jv_string("params"), params);
errors += compile(subfn, curr->subfn);
errors += compile(subfn, curr->subfn, lf);
curr->subfn = gen_noop();
}
}
} else {
bc->subfunctions = 0;
}
bc->codelen = pos;
uint16_t* code = jv_mem_alloc(sizeof(uint16_t) * bc->codelen);
bc->code = code;
pos = 0;
Expand Down Expand Up @@ -1174,7 +1180,7 @@ static int compile(struct bytecode* bc, block b) {
return errors;
}

int block_compile(block b, struct bytecode** out) {
int block_compile(block b, struct bytecode** out, struct locfile* lf) {
struct bytecode* bc = jv_mem_alloc(sizeof(struct bytecode));
bc->parent = 0;
bc->nclosures = 0;
Expand All @@ -1184,7 +1190,7 @@ int block_compile(block b, struct bytecode** out) {
bc->globals->cfunctions = jv_mem_alloc(sizeof(struct cfunction) * ncfunc);
bc->globals->cfunc_names = jv_array();
bc->debuginfo = jv_object_set(jv_object(), jv_string("name"), jv_null());
int nerrors = compile(bc, b);
int nerrors = compile(bc, b, lf);
assert(bc->globals->ncfunctions == ncfunc);
if (nerrors > 0) {
bytecode_free(bc);
Expand Down
2 changes: 1 addition & 1 deletion compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ block block_drop_unreferenced(block body);

jv block_take_imports(block* body);

int block_compile(block, struct bytecode**);
int block_compile(block, struct bytecode**, struct locfile*);

void block_free(block);

Expand Down
2 changes: 1 addition & 1 deletion execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ int jq_compile_args(jq_state *jq, const char* str, jv args) {

nerrors = builtins_bind(jq, &program);
if (nerrors == 0) {
nerrors = block_compile(program, &jq->bc);
nerrors = block_compile(program, &jq->bc, locations);
}
}
if (nerrors)
Expand Down

0 comments on commit 21309bc

Please sign in to comment.