bc: in execution loop, reload stack only after insts which can change it
authorDenys Vlasenko <vda.linux@googlemail.com>
Wed, 19 Dec 2018 11:35:27 +0000 (12:35 +0100)
committerDenys Vlasenko <vda.linux@googlemail.com>
Wed, 19 Dec 2018 11:35:27 +0000 (12:35 +0100)
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>
miscutils/bc.c

index 7ddae341ffe3698107ceed9664321f7388970960..92bf1df57ef24a586a9730c3f8a575033d165097 100644 (file)
 # include "dc.c"
 #else
 
-#define DEBUG_LEXER 0
-#define DEBUG_EXEC  0
+#define DEBUG_LEXER   0
+#define DEBUG_COMPILE 0
+#define DEBUG_EXEC    0
 
 #if DEBUG_LEXER
 static uint8_t lex_indent;
@@ -193,6 +194,12 @@ static uint8_t lex_indent;
 # define dbg_lex_done(...)  ((void)0)
 #endif
 
+#if DEBUG_COMPILE
+# define dbg_compile(...) bb_error_msg(__VA_ARGS__)
+#else
+# define dbg_compile(...) ((void)0)
+#endif
+
 #if DEBUG_EXEC
 # define dbg_exec(...) bb_error_msg(__VA_ARGS__)
 #else
@@ -683,7 +690,7 @@ typedef struct BcProgram {
 #endif
 
        BcVec results;
-       BcVec stack;
+       BcVec exestack;
 
        BcVec fns;
        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)
 {
-       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);
 }
 
@@ -3537,11 +3544,11 @@ static void bc_program_reset(void)
        BcFunc *f;
        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);
 
        f = bc_program_func(0);
-       ip = bc_vec_top(&G.prog.stack);
+       ip = bc_vec_top(&G.prog.exestack);
        ip->idx = f->code.len;
 }
 
@@ -5145,7 +5152,7 @@ static BC_STATUS zbc_program_read(void)
        f = bc_program_func(BC_PROG_READ);
 
        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:
        bc_parse_free(&parse);
        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)
 {
        BcInstPtr ip;
-       size_t i, nparams = bc_program_index(code, idx);
+       size_t i, nparams;
        BcFunc *func;
        BcId *a;
        BcResultData param;
        BcResult *arg;
 
+       nparams = bc_program_index(code, idx);
        ip.idx = 0;
        ip.func = bc_program_index(code, idx);
        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);
 }
@@ -5881,7 +5889,7 @@ static BC_STATUS zbc_program_return(char inst)
        BcResult res;
        BcFunc *f;
        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))
                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_push(&G.prog.results, &res);
-       bc_vec_pop(&G.prog.stack);
+       bc_vec_pop(&G.prog.exestack);
 
        RETURN_STATUS(BC_STATUS_SUCCESS);
 }
@@ -6184,13 +6192,13 @@ static BC_STATUS zbc_program_nquit(void)
 
        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());
-       if (G.prog.stack.len == val) {
+       if (G.prog.exestack.len == val) {
                QUIT_OR_RETURN_TO_MAIN;
        }
 
-       bc_vec_npop(&G.prog.stack, val);
+       bc_vec_npop(&G.prog.exestack, val);
 
        RETURN_STATUS(s);
 }
@@ -6283,7 +6291,7 @@ static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond)
        ip.func = fidx;
 
        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);
  err:
@@ -6348,15 +6356,16 @@ static BC_STATUS zbc_program_exec(void)
 {
        BcResult r, *ptr;
        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);
        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) {
                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) {
 #if ENABLE_BC
                        case BC_INST_JUMP_ZERO: {
@@ -6382,7 +6391,7 @@ static BC_STATUS zbc_program_exec(void)
                        case BC_INST_CALL:
                                dbg_exec("BC_INST_CALL:");
                                s = zbc_program_call(code, &ip->idx);
-                               break;
+                               goto read_updated_ip;
                        case BC_INST_INC_PRE:
                        case BC_INST_DEC_PRE:
                        case BC_INST_INC_POST:
@@ -6398,7 +6407,7 @@ static BC_STATUS zbc_program_exec(void)
                        case BC_INST_RET0:
                                dbg_exec("BC_INST_RET[0]:");
                                s = zbc_program_return(inst);
-                               break;
+                               goto read_updated_ip;
                        case BC_INST_BOOL_OR:
                        case BC_INST_BOOL_AND:
 #endif // ENABLE_BC
@@ -6414,7 +6423,7 @@ static BC_STATUS zbc_program_exec(void)
                        case BC_INST_READ:
                                dbg_exec("BC_INST_READ:");
                                s = zbc_program_read();
-                               break;
+                               goto read_updated_ip;
                        case BC_INST_VAR:
                                dbg_exec("BC_INST_VAR:");
                                s = zbc_program_pushVar(code, &ip->idx, false, false);
@@ -6454,7 +6463,7 @@ static BC_STATUS zbc_program_exec(void)
                                break;
                        case BC_INST_POP_EXEC:
                                dbg_exec("BC_INST_POP_EXEC:");
-                               bc_vec_pop(&G.prog.stack);
+                               bc_vec_pop(&G.prog.exestack);
                                break;
                        case BC_INST_PRINT:
                        case BC_INST_PRINT_POP:
@@ -6513,7 +6522,7 @@ static BC_STATUS zbc_program_exec(void)
                        case BC_INST_EXECUTE:
                        case 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: {
                                size_t 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:
                                dbg_exec("BC_INST_NEG:");
-                               if (G.prog.stack.len <= 2)
+                               if (G.prog.exestack.len <= 2)
                                        QUIT_OR_RETURN_TO_MAIN;
-                               bc_vec_npop(&G.prog.stack, 2);
+                               bc_vec_npop(&G.prog.exestack, 2);
                                break;
                        case BC_INST_NQUIT:
                                s = zbc_program_nquit();
-                               break;
+                               //goto read_updated_ip; - just fall through to it
 #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) {
@@ -6583,10 +6598,6 @@ static BC_STATUS zbc_program_exec(void)
 
                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);
@@ -6957,7 +6968,7 @@ static void bc_program_free(void)
        bc_vec_free(&G.prog.strs);
        bc_vec_free(&G.prog.consts);
        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.zero);
        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.consts, sizeof(char *), bc_string_free);
        bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free);
-       bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL);
-       bc_vec_push(&G.prog.stack, &ip);
+       bc_vec_init(&G.prog.exestack, sizeof(BcInstPtr), NULL);
+       bc_vec_push(&G.prog.exestack, &ip);
 
        bc_char_vec_init(&G.input_buffer);
 }