mirror of
https://github.com/stedolan/jq.git
synced 2024-05-11 05:55:39 +00:00
Simplify frame logic.
This commit is contained in:
32
execute.c
32
execute.c
@@ -125,11 +125,11 @@ static struct closure make_closure(struct jq_state* jq, stack_ptr fridx, uint16_
|
|||||||
uint16_t level = *pc++;
|
uint16_t level = *pc++;
|
||||||
uint16_t idx = *pc++;
|
uint16_t idx = *pc++;
|
||||||
fridx = frame_get_level(&jq->stk, fridx, level);
|
fridx = frame_get_level(&jq->stk, fridx, level);
|
||||||
frame_ptr fr = frame_current(&jq->stk, fridx);
|
struct frame* fr = frame_current(&jq->stk, fridx);
|
||||||
if (idx & ARG_NEWCLOSURE) {
|
if (idx & ARG_NEWCLOSURE) {
|
||||||
int subfn_idx = idx & ~ARG_NEWCLOSURE;
|
int subfn_idx = idx & ~ARG_NEWCLOSURE;
|
||||||
assert(subfn_idx < frame_self(fr)->bc->nsubfunctions);
|
assert(subfn_idx < fr->bc->nsubfunctions);
|
||||||
struct closure cl = {frame_self(fr)->bc->subfunctions[subfn_idx],
|
struct closure cl = {fr->bc->subfunctions[subfn_idx],
|
||||||
fridx};
|
fridx};
|
||||||
return cl;
|
return cl;
|
||||||
} else {
|
} else {
|
||||||
@@ -159,7 +159,7 @@ jv jq_next(jq_state *jq) {
|
|||||||
uint16_t opcode = *pc;
|
uint16_t opcode = *pc;
|
||||||
|
|
||||||
if (jq->debug_trace_enabled) {
|
if (jq->debug_trace_enabled) {
|
||||||
dump_operation(frame_current_bytecode(&jq->stk, jq->curr_frame), pc);
|
dump_operation(frame_current(&jq->stk, jq->curr_frame)->bc, pc);
|
||||||
printf("\t");
|
printf("\t");
|
||||||
const struct opcode_description* opdesc = opcode_describe(opcode);
|
const struct opcode_description* opdesc = opcode_describe(opcode);
|
||||||
stack_ptr param = 0;
|
stack_ptr param = 0;
|
||||||
@@ -196,7 +196,7 @@ jv jq_next(jq_state *jq) {
|
|||||||
default: assert(0 && "invalid instruction");
|
default: assert(0 && "invalid instruction");
|
||||||
|
|
||||||
case LOADK: {
|
case LOADK: {
|
||||||
jv v = jv_array_get(jv_copy(frame_current_bytecode(&jq->stk, jq->curr_frame)->constants), *pc++);
|
jv v = jv_array_get(jv_copy(frame_current(&jq->stk, jq->curr_frame)->bc->constants), *pc++);
|
||||||
assert(jv_is_valid(v));
|
assert(jv_is_valid(v));
|
||||||
jv_free(stack_pop(jq));
|
jv_free(stack_pop(jq));
|
||||||
stack_push(jq, v);
|
stack_push(jq, v);
|
||||||
@@ -246,7 +246,7 @@ jv jq_next(jq_state *jq) {
|
|||||||
jv v = stack_pop(jq);
|
jv v = stack_pop(jq);
|
||||||
uint16_t level = *pc++;
|
uint16_t level = *pc++;
|
||||||
uint16_t vidx = *pc++;
|
uint16_t vidx = *pc++;
|
||||||
frame_ptr fp = frame_current(&jq->stk, frame_get_level(&jq->stk, jq->curr_frame, level));
|
struct frame* fp = frame_current(&jq->stk, frame_get_level(&jq->stk, jq->curr_frame, level));
|
||||||
jv* var = frame_local_var(fp, vidx);
|
jv* var = frame_local_var(fp, vidx);
|
||||||
assert(jv_get_kind(*var) == JV_KIND_ARRAY);
|
assert(jv_get_kind(*var) == JV_KIND_ARRAY);
|
||||||
*var = jv_array_append(*var, v);
|
*var = jv_array_append(*var, v);
|
||||||
@@ -278,7 +278,7 @@ jv jq_next(jq_state *jq) {
|
|||||||
case RANGE: {
|
case RANGE: {
|
||||||
uint16_t level = *pc++;
|
uint16_t level = *pc++;
|
||||||
uint16_t v = *pc++;
|
uint16_t v = *pc++;
|
||||||
frame_ptr fp = frame_current(&jq->stk, frame_get_level(&jq->stk, jq->curr_frame, level));
|
struct frame* fp = frame_current(&jq->stk, frame_get_level(&jq->stk, jq->curr_frame, level));
|
||||||
jv* var = frame_local_var(fp, v);
|
jv* var = frame_local_var(fp, v);
|
||||||
jv max = stack_pop(jq);
|
jv max = stack_pop(jq);
|
||||||
if (jv_get_kind(*var) != JV_KIND_NUMBER ||
|
if (jv_get_kind(*var) != JV_KIND_NUMBER ||
|
||||||
@@ -306,7 +306,7 @@ jv jq_next(jq_state *jq) {
|
|||||||
case LOADV: {
|
case LOADV: {
|
||||||
uint16_t level = *pc++;
|
uint16_t level = *pc++;
|
||||||
uint16_t v = *pc++;
|
uint16_t v = *pc++;
|
||||||
frame_ptr fp = frame_current(&jq->stk, frame_get_level(&jq->stk, jq->curr_frame, level));
|
struct frame* fp = frame_current(&jq->stk, frame_get_level(&jq->stk, jq->curr_frame, level));
|
||||||
jv* var = frame_local_var(fp, v);
|
jv* var = frame_local_var(fp, v);
|
||||||
if (jq->debug_trace_enabled) {
|
if (jq->debug_trace_enabled) {
|
||||||
printf("V%d = ", v);
|
printf("V%d = ", v);
|
||||||
@@ -322,7 +322,7 @@ jv jq_next(jq_state *jq) {
|
|||||||
case LOADVN: {
|
case LOADVN: {
|
||||||
uint16_t level = *pc++;
|
uint16_t level = *pc++;
|
||||||
uint16_t v = *pc++;
|
uint16_t v = *pc++;
|
||||||
frame_ptr fp = frame_current(&jq->stk, frame_get_level(&jq->stk, jq->curr_frame, level));
|
struct frame* fp = frame_current(&jq->stk, frame_get_level(&jq->stk, jq->curr_frame, level));
|
||||||
jv* var = frame_local_var(fp, v);
|
jv* var = frame_local_var(fp, v);
|
||||||
if (jq->debug_trace_enabled) {
|
if (jq->debug_trace_enabled) {
|
||||||
printf("V%d = ", v);
|
printf("V%d = ", v);
|
||||||
@@ -338,7 +338,7 @@ jv jq_next(jq_state *jq) {
|
|||||||
case STOREV: {
|
case STOREV: {
|
||||||
uint16_t level = *pc++;
|
uint16_t level = *pc++;
|
||||||
uint16_t v = *pc++;
|
uint16_t v = *pc++;
|
||||||
frame_ptr fp = frame_current(&jq->stk, frame_get_level(&jq->stk, jq->curr_frame, level));
|
struct frame* fp = frame_current(&jq->stk, frame_get_level(&jq->stk, jq->curr_frame, level));
|
||||||
jv* var = frame_local_var(fp, v);
|
jv* var = frame_local_var(fp, v);
|
||||||
jv val = stack_pop(jq);
|
jv val = stack_pop(jq);
|
||||||
if (jq->debug_trace_enabled) {
|
if (jq->debug_trace_enabled) {
|
||||||
@@ -504,7 +504,7 @@ jv jq_next(jq_state *jq) {
|
|||||||
for (int i = 1; i < nargs; i++) {
|
for (int i = 1; i < nargs; i++) {
|
||||||
cfunc_input[i] = stack_pop(jq);
|
cfunc_input[i] = stack_pop(jq);
|
||||||
}
|
}
|
||||||
struct cfunction* func = &frame_current_bytecode(&jq->stk, jq->curr_frame)->globals->cfunctions[*pc++];
|
struct cfunction* func = &frame_current(&jq->stk, jq->curr_frame)->bc->globals->cfunctions[*pc++];
|
||||||
top = cfunction_invoke(func, cfunc_input);
|
top = cfunction_invoke(func, cfunc_input);
|
||||||
if (jv_is_valid(top)) {
|
if (jv_is_valid(top)) {
|
||||||
stack_push(jq, top);
|
stack_push(jq, top);
|
||||||
@@ -525,22 +525,22 @@ jv jq_next(jq_state *jq) {
|
|||||||
retaddr, jq->stk_top);
|
retaddr, jq->stk_top);
|
||||||
pc += 2;
|
pc += 2;
|
||||||
|
|
||||||
frame_ptr new_frame = frame_current(&jq->stk, jq->curr_frame);
|
struct frame* new_frame = frame_current(&jq->stk, jq->curr_frame);
|
||||||
assert(nclosures == frame_self(new_frame)->bc->nclosures);
|
assert(nclosures == new_frame->bc->nclosures);
|
||||||
for (int i=0; i<nclosures; i++) {
|
for (int i=0; i<nclosures; i++) {
|
||||||
*frame_closure_arg(new_frame, i) = make_closure(jq, old_frame, pc);
|
*frame_closure_arg(new_frame, i) = make_closure(jq, old_frame, pc);
|
||||||
pc += 2;
|
pc += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
pc = frame_current_bytecode(&jq->stk, jq->curr_frame)->code;
|
pc = frame_current(&jq->stk, jq->curr_frame)->bc->code;
|
||||||
stack_push(jq, input);
|
stack_push(jq, input);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case RET: {
|
case RET: {
|
||||||
jv value = stack_pop(jq);
|
jv value = stack_pop(jq);
|
||||||
assert(jq->stk_top == frame_self(frame_current(&jq->stk, jq->curr_frame))->retdata);
|
assert(jq->stk_top == frame_current(&jq->stk, jq->curr_frame)->retdata);
|
||||||
uint16_t* retaddr = *frame_current_retaddr(&jq->stk, jq->curr_frame);
|
uint16_t* retaddr = frame_current(&jq->stk, jq->curr_frame)->retaddr;
|
||||||
if (retaddr) {
|
if (retaddr) {
|
||||||
// function return
|
// function return
|
||||||
pc = retaddr;
|
pc = retaddr;
|
||||||
|
@@ -7,88 +7,65 @@ struct closure {
|
|||||||
stack_ptr env;
|
stack_ptr env;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct continuation {
|
union frame_entry {
|
||||||
|
struct closure closure;
|
||||||
|
jv localvar;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct frame {
|
||||||
struct bytecode* bc;
|
struct bytecode* bc;
|
||||||
stack_ptr env;
|
stack_ptr env;
|
||||||
stack_ptr retdata;
|
stack_ptr retdata;
|
||||||
uint16_t* retaddr;
|
uint16_t* retaddr;
|
||||||
|
/* bc->nclosures closures followed by bc->nlocals local variables */
|
||||||
|
union frame_entry entries[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef union frame_elem {
|
|
||||||
struct continuation cont;
|
|
||||||
struct closure closure;
|
|
||||||
jv jsonval;
|
|
||||||
} *frame_ptr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Frame layout
|
|
||||||
* fr[0] - FORKABLE_STACK_HEADER (next pointer)
|
|
||||||
* fr[1] - self (used to store return addresses, etc)
|
|
||||||
* fr[2...nclosures+2] - closure params
|
|
||||||
* fr[nclosures+2..nclosures+nlocals+2] - local variables
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int frame_size(struct bytecode* bc) {
|
static int frame_size(struct bytecode* bc) {
|
||||||
return sizeof(union frame_elem) * (bc->nclosures + bc->nlocals + 2);
|
return sizeof(struct frame) + sizeof(union frame_entry) * (bc->nclosures + bc->nlocals);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct continuation* frame_self(frame_ptr fr) {
|
static struct closure* frame_closure_arg(struct frame* fr, int closure) {
|
||||||
return &fr[1].cont;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct closure* frame_closure_arg(frame_ptr fr, int closure) {
|
|
||||||
assert(closure >= 0);
|
assert(closure >= 0);
|
||||||
assert(closure < frame_self(fr)->bc->nclosures);
|
assert(closure < fr->bc->nclosures);
|
||||||
return &fr[2+closure].closure;
|
return &fr->entries[closure].closure;
|
||||||
}
|
}
|
||||||
|
|
||||||
static jv* frame_local_var(frame_ptr fr, int var) {
|
static jv* frame_local_var(struct frame* fr, int var) {
|
||||||
assert(var >= 0);
|
assert(var >= 0);
|
||||||
assert(var < frame_self(fr)->bc->nlocals);
|
assert(var < fr->bc->nlocals);
|
||||||
return &fr[2 + frame_self(fr)->bc->nclosures + var].jsonval;
|
return &fr->entries[fr->bc->nclosures + var].localvar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct frame* frame_current(struct stack* stk, stack_ptr idx) {
|
||||||
static frame_ptr frame_current(struct stack* stk, stack_ptr idx) {
|
struct frame* fp = stack_block(stk, idx);
|
||||||
frame_ptr fp = stack_block(stk, idx);
|
|
||||||
|
|
||||||
stack_ptr next = *stack_block_next(stk, idx);
|
stack_ptr next = *stack_block_next(stk, idx);
|
||||||
if (next) {
|
if (next) {
|
||||||
frame_ptr fpnext = stack_block(stk, next);
|
struct frame* fpnext = stack_block(stk, next);
|
||||||
struct bytecode* bc = frame_self(fpnext)->bc;
|
struct bytecode* bc = fpnext->bc;
|
||||||
assert(frame_self(fp)->retaddr >= bc->code && frame_self(fp)->retaddr < bc->code + bc->codelen);
|
assert(fp->retaddr >= bc->code && fp->retaddr < bc->code + bc->codelen);
|
||||||
} else {
|
} else {
|
||||||
assert(frame_self(fp)->retaddr == 0);
|
assert(fp->retaddr == 0);
|
||||||
}
|
}
|
||||||
return fp;
|
return fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct bytecode* frame_current_bytecode(struct stack* stk, stack_ptr curr) {
|
|
||||||
return frame_self(frame_current(stk, curr))->bc;
|
|
||||||
}
|
|
||||||
static uint16_t** frame_current_retaddr(struct stack* stk, stack_ptr curr) {
|
|
||||||
return &frame_self(frame_current(stk, curr))->retaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static stack_ptr frame_get_parent(struct stack* stk, stack_ptr fr) {
|
|
||||||
return frame_self(stack_block(stk, fr))->env;
|
|
||||||
}
|
|
||||||
|
|
||||||
static stack_ptr frame_get_level(struct stack* stk, stack_ptr fr, int level) {
|
static stack_ptr frame_get_level(struct stack* stk, stack_ptr fr, int level) {
|
||||||
for (int i=0; i<level; i++) {
|
for (int i=0; i<level; i++) {
|
||||||
fr = frame_get_parent(stk, fr);
|
struct frame* fp = stack_block(stk, fr);
|
||||||
|
fr = fp->env;
|
||||||
}
|
}
|
||||||
return fr;
|
return fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static stack_ptr frame_push(struct stack* stk, stack_ptr curr, struct closure cl, uint16_t* retaddr, stack_ptr datastk) {
|
static stack_ptr frame_push(struct stack* stk, stack_ptr curr, struct closure cl, uint16_t* retaddr, stack_ptr datastk) {
|
||||||
stack_ptr fpidx = stack_push_block(stk, curr, frame_size(cl.bc));
|
stack_ptr fpidx = stack_push_block(stk, curr, frame_size(cl.bc));
|
||||||
frame_ptr fp = stack_block(stk, fpidx);
|
struct frame* fp = stack_block(stk, fpidx);
|
||||||
struct continuation* cc = frame_self(fp);
|
fp->bc = cl.bc;
|
||||||
cc->bc = cl.bc;
|
fp->env = cl.env;
|
||||||
cc->env = cl.env;
|
fp->retdata = datastk;
|
||||||
cc->retdata = datastk;
|
fp->retaddr = retaddr;
|
||||||
cc->retaddr = retaddr;
|
|
||||||
for (int i=0; i<cl.bc->nlocals; i++) {
|
for (int i=0; i<cl.bc->nlocals; i++) {
|
||||||
*frame_local_var(fp, i) = jv_invalid();
|
*frame_local_var(fp, i) = jv_invalid();
|
||||||
}
|
}
|
||||||
@@ -96,14 +73,14 @@ static stack_ptr frame_push(struct stack* stk, stack_ptr curr, struct closure cl
|
|||||||
}
|
}
|
||||||
|
|
||||||
static stack_ptr frame_pop(struct stack* stk, stack_ptr curr) {
|
static stack_ptr frame_pop(struct stack* stk, stack_ptr curr) {
|
||||||
frame_ptr fp = frame_current(stk, curr);
|
struct frame* fp = frame_current(stk, curr);
|
||||||
if (stack_pop_will_free(stk, curr)) {
|
if (stack_pop_will_free(stk, curr)) {
|
||||||
int nlocals = frame_self(fp)->bc->nlocals;
|
int nlocals = fp->bc->nlocals;
|
||||||
for (int i=0; i<nlocals; i++) {
|
for (int i=0; i<nlocals; i++) {
|
||||||
jv_free(*frame_local_var(fp, i));
|
jv_free(*frame_local_var(fp, i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return stack_pop_block(stk, curr, frame_size(frame_self(fp)->bc));
|
return stack_pop_block(stk, curr, frame_size(fp->bc));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
15
newstack.h
15
newstack.h
@@ -86,18 +86,3 @@ stack_ptr stack_pop_block(struct stack* s, stack_ptr p, size_t sz) {
|
|||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
int main() {
|
|
||||||
stack s;
|
|
||||||
stack_init(&s);
|
|
||||||
stack_ptr top = 0;
|
|
||||||
top = stack_push_block(&s, top, sizeof(double));
|
|
||||||
double* d1 = stack_block(&s, top);
|
|
||||||
*d1 = 42;
|
|
||||||
top = stack_push_block(&s, top, sizeof(double));
|
|
||||||
double* d2 = stack_block(&s, top);
|
|
||||||
*d2 = 33;
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
Reference in New Issue
Block a user