bc: in execution loop, reload stack only after insts which can change it

Only these functions affect G.prog.exestack:
zbc_program_read
zbc_program_call
zbc_program_return
zbc_program_nquit
zbc_program_execStr

function                                             old     new   delta
zbc_program_exec                                    3995    4093     +98
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/0 up/down: 98/0)               Total: 98 bytes
   text	   data	    bss	    dec	    hex	filename
 981364	    485	   7296	 989145	  f17d9	busybox_old
 981462	    485	   7296	 989243	  f183b	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-12-19 12:35:27 +01:00
parent d6e24bd795
commit b80d7aad1b

View File

@ -167,8 +167,9 @@
# include "dc.c" # include "dc.c"
#else #else
#define DEBUG_LEXER 0 #define DEBUG_LEXER 0
#define DEBUG_EXEC 0 #define DEBUG_COMPILE 0
#define DEBUG_EXEC 0
#if DEBUG_LEXER #if DEBUG_LEXER
static uint8_t lex_indent; static uint8_t lex_indent;
@ -193,6 +194,12 @@ static uint8_t lex_indent;
# define dbg_lex_done(...) ((void)0) # define dbg_lex_done(...) ((void)0)
#endif #endif
#if DEBUG_COMPILE
# define dbg_compile(...) bb_error_msg(__VA_ARGS__)
#else
# define dbg_compile(...) ((void)0)
#endif
#if DEBUG_EXEC #if DEBUG_EXEC
# define dbg_exec(...) bb_error_msg(__VA_ARGS__) # define dbg_exec(...) bb_error_msg(__VA_ARGS__)
#else #else
@ -683,7 +690,7 @@ typedef struct BcProgram {
#endif #endif
BcVec results; BcVec results;
BcVec stack; BcVec exestack;
BcVec fns; BcVec fns;
BcVec fn_map; BcVec fn_map;
@ -3448,7 +3455,7 @@ static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx)
static void bc_parse_push(BcParse *p, char i) static void bc_parse_push(BcParse *p, char i)
{ {
dbg_lex("%s:%d pushing opcode %d", __func__, __LINE__, i); dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, p->func->code.len, i);
bc_vec_pushByte(&p->func->code, i); bc_vec_pushByte(&p->func->code, i);
} }
@ -3537,11 +3544,11 @@ static void bc_program_reset(void)
BcFunc *f; BcFunc *f;
BcInstPtr *ip; BcInstPtr *ip;
bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1); bc_vec_npop(&G.prog.exestack, G.prog.exestack.len - 1);
bc_vec_pop_all(&G.prog.results); bc_vec_pop_all(&G.prog.results);
f = bc_program_func(0); f = bc_program_func(0);
ip = bc_vec_top(&G.prog.stack); ip = bc_vec_top(&G.prog.exestack);
ip->idx = f->code.len; ip->idx = f->code.len;
} }
@ -5145,7 +5152,7 @@ static BC_STATUS zbc_program_read(void)
f = bc_program_func(BC_PROG_READ); f = bc_program_func(BC_PROG_READ);
bc_vec_pushByte(&f->code, BC_INST_POP_EXEC); bc_vec_pushByte(&f->code, BC_INST_POP_EXEC);
bc_vec_push(&G.prog.stack, &ip); bc_vec_push(&G.prog.exestack, &ip);
exec_err: exec_err:
bc_parse_free(&parse); bc_parse_free(&parse);
G.in_read = 0; G.in_read = 0;
@ -5824,12 +5831,13 @@ static BC_STATUS zbc_program_incdec(char inst)
static BC_STATUS zbc_program_call(char *code, size_t *idx) static BC_STATUS zbc_program_call(char *code, size_t *idx)
{ {
BcInstPtr ip; BcInstPtr ip;
size_t i, nparams = bc_program_index(code, idx); size_t i, nparams;
BcFunc *func; BcFunc *func;
BcId *a; BcId *a;
BcResultData param; BcResultData param;
BcResult *arg; BcResult *arg;
nparams = bc_program_index(code, idx);
ip.idx = 0; ip.idx = 0;
ip.func = bc_program_index(code, idx); ip.func = bc_program_index(code, idx);
func = bc_program_func(ip.func); func = bc_program_func(ip.func);
@ -5870,7 +5878,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx)
} }
} }
bc_vec_push(&G.prog.stack, &ip); bc_vec_push(&G.prog.exestack, &ip);
RETURN_STATUS(BC_STATUS_SUCCESS); RETURN_STATUS(BC_STATUS_SUCCESS);
} }
@ -5881,7 +5889,7 @@ static BC_STATUS zbc_program_return(char inst)
BcResult res; BcResult res;
BcFunc *f; BcFunc *f;
size_t i; size_t i;
BcInstPtr *ip = bc_vec_top(&G.prog.stack); BcInstPtr *ip = bc_vec_top(&G.prog.exestack);
if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET))
RETURN_STATUS(bc_error_stack_has_too_few_elements()); RETURN_STATUS(bc_error_stack_has_too_few_elements());
@ -5914,7 +5922,7 @@ static BC_STATUS zbc_program_return(char inst)
bc_vec_npop(&G.prog.results, G.prog.results.len - ip->len); bc_vec_npop(&G.prog.results, G.prog.results.len - ip->len);
bc_vec_push(&G.prog.results, &res); bc_vec_push(&G.prog.results, &res);
bc_vec_pop(&G.prog.stack); bc_vec_pop(&G.prog.exestack);
RETURN_STATUS(BC_STATUS_SUCCESS); RETURN_STATUS(BC_STATUS_SUCCESS);
} }
@ -6184,13 +6192,13 @@ static BC_STATUS zbc_program_nquit(void)
bc_vec_pop(&G.prog.results); bc_vec_pop(&G.prog.results);
if (G.prog.stack.len < val) if (G.prog.exestack.len < val)
RETURN_STATUS(bc_error_stack_has_too_few_elements()); RETURN_STATUS(bc_error_stack_has_too_few_elements());
if (G.prog.stack.len == val) { if (G.prog.exestack.len == val) {
QUIT_OR_RETURN_TO_MAIN; QUIT_OR_RETURN_TO_MAIN;
} }
bc_vec_npop(&G.prog.stack, val); bc_vec_npop(&G.prog.exestack, val);
RETURN_STATUS(s); RETURN_STATUS(s);
} }
@ -6283,7 +6291,7 @@ static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond)
ip.func = fidx; ip.func = fidx;
bc_vec_pop(&G.prog.results); bc_vec_pop(&G.prog.results);
bc_vec_push(&G.prog.stack, &ip); bc_vec_push(&G.prog.exestack, &ip);
RETURN_STATUS(BC_STATUS_SUCCESS); RETURN_STATUS(BC_STATUS_SUCCESS);
err: err:
@ -6348,15 +6356,16 @@ static BC_STATUS zbc_program_exec(void)
{ {
BcResult r, *ptr; BcResult r, *ptr;
BcNum *num; BcNum *num;
BcInstPtr *ip = bc_vec_top(&G.prog.stack); BcInstPtr *ip = bc_vec_top(&G.prog.exestack);
BcFunc *func = bc_program_func(ip->func); BcFunc *func = bc_program_func(ip->func);
char *code = func->code.v; char *code = func->code.v;
dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->idx);
while (ip->idx < func->code.len) { while (ip->idx < func->code.len) {
BcStatus s = BC_STATUS_SUCCESS; BcStatus s = BC_STATUS_SUCCESS;
char inst = code[(ip->idx)++]; char inst = code[ip->idx++];
dbg_exec("inst:%d", inst); dbg_exec("inst at %zd:%d", ip->idx - 1, inst);
switch (inst) { switch (inst) {
#if ENABLE_BC #if ENABLE_BC
case BC_INST_JUMP_ZERO: { case BC_INST_JUMP_ZERO: {
@ -6382,7 +6391,7 @@ static BC_STATUS zbc_program_exec(void)
case BC_INST_CALL: case BC_INST_CALL:
dbg_exec("BC_INST_CALL:"); dbg_exec("BC_INST_CALL:");
s = zbc_program_call(code, &ip->idx); s = zbc_program_call(code, &ip->idx);
break; goto read_updated_ip;
case BC_INST_INC_PRE: case BC_INST_INC_PRE:
case BC_INST_DEC_PRE: case BC_INST_DEC_PRE:
case BC_INST_INC_POST: case BC_INST_INC_POST:
@ -6398,7 +6407,7 @@ static BC_STATUS zbc_program_exec(void)
case BC_INST_RET0: case BC_INST_RET0:
dbg_exec("BC_INST_RET[0]:"); dbg_exec("BC_INST_RET[0]:");
s = zbc_program_return(inst); s = zbc_program_return(inst);
break; goto read_updated_ip;
case BC_INST_BOOL_OR: case BC_INST_BOOL_OR:
case BC_INST_BOOL_AND: case BC_INST_BOOL_AND:
#endif // ENABLE_BC #endif // ENABLE_BC
@ -6414,7 +6423,7 @@ static BC_STATUS zbc_program_exec(void)
case BC_INST_READ: case BC_INST_READ:
dbg_exec("BC_INST_READ:"); dbg_exec("BC_INST_READ:");
s = zbc_program_read(); s = zbc_program_read();
break; goto read_updated_ip;
case BC_INST_VAR: case BC_INST_VAR:
dbg_exec("BC_INST_VAR:"); dbg_exec("BC_INST_VAR:");
s = zbc_program_pushVar(code, &ip->idx, false, false); s = zbc_program_pushVar(code, &ip->idx, false, false);
@ -6454,7 +6463,7 @@ static BC_STATUS zbc_program_exec(void)
break; break;
case BC_INST_POP_EXEC: case BC_INST_POP_EXEC:
dbg_exec("BC_INST_POP_EXEC:"); dbg_exec("BC_INST_POP_EXEC:");
bc_vec_pop(&G.prog.stack); bc_vec_pop(&G.prog.exestack);
break; break;
case BC_INST_PRINT: case BC_INST_PRINT:
case BC_INST_PRINT_POP: case BC_INST_PRINT_POP:
@ -6513,7 +6522,7 @@ static BC_STATUS zbc_program_exec(void)
case BC_INST_EXECUTE: case BC_INST_EXECUTE:
case BC_INST_EXEC_COND: case BC_INST_EXEC_COND:
s = zbc_program_execStr(code, &ip->idx, inst == BC_INST_EXEC_COND); s = zbc_program_execStr(code, &ip->idx, inst == BC_INST_EXEC_COND);
break; goto read_updated_ip;
case BC_INST_PRINT_STACK: { case BC_INST_PRINT_STACK: {
size_t idx; size_t idx;
for (idx = 0; idx < G.prog.results.len; ++idx) { for (idx = 0; idx < G.prog.results.len; ++idx) {
@ -6566,14 +6575,20 @@ static BC_STATUS zbc_program_exec(void)
} }
case BC_INST_QUIT: case BC_INST_QUIT:
dbg_exec("BC_INST_NEG:"); dbg_exec("BC_INST_NEG:");
if (G.prog.stack.len <= 2) if (G.prog.exestack.len <= 2)
QUIT_OR_RETURN_TO_MAIN; QUIT_OR_RETURN_TO_MAIN;
bc_vec_npop(&G.prog.stack, 2); bc_vec_npop(&G.prog.exestack, 2);
break; break;
case BC_INST_NQUIT: case BC_INST_NQUIT:
s = zbc_program_nquit(); s = zbc_program_nquit();
break; //goto read_updated_ip; - just fall through to it
#endif // ENABLE_DC #endif // ENABLE_DC
read_updated_ip:
// Instruction stack has changed, read new pointers
ip = bc_vec_top(&G.prog.exestack);
func = bc_program_func(ip->func);
code = func->code.v;
dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->idx);
} }
if (s || G_interrupt) { if (s || G_interrupt) {
@ -6583,10 +6598,6 @@ static BC_STATUS zbc_program_exec(void)
fflush_and_check(); fflush_and_check();
// If the stack has changed, pointers may be invalid.
ip = bc_vec_top(&G.prog.stack);
func = bc_program_func(ip->func);
code = func->code.v;
} }
RETURN_STATUS(BC_STATUS_SUCCESS); RETURN_STATUS(BC_STATUS_SUCCESS);
@ -6957,7 +6968,7 @@ static void bc_program_free(void)
bc_vec_free(&G.prog.strs); bc_vec_free(&G.prog.strs);
bc_vec_free(&G.prog.consts); bc_vec_free(&G.prog.consts);
bc_vec_free(&G.prog.results); bc_vec_free(&G.prog.results);
bc_vec_free(&G.prog.stack); bc_vec_free(&G.prog.exestack);
bc_num_free(&G.prog.last); bc_num_free(&G.prog.last);
bc_num_free(&G.prog.zero); bc_num_free(&G.prog.zero);
bc_num_free(&G.prog.one); bc_num_free(&G.prog.one);
@ -7009,8 +7020,8 @@ static void bc_program_init(void)
bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free); bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free);
bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free); bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free);
bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free); bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free);
bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL); bc_vec_init(&G.prog.exestack, sizeof(BcInstPtr), NULL);
bc_vec_push(&G.prog.stack, &ip); bc_vec_push(&G.prog.exestack, &ip);
bc_char_vec_init(&G.input_buffer); bc_char_vec_init(&G.input_buffer);
} }