diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-19 12:35:27 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-12-19 12:35:27 +0100 |
commit | b80d7aad1b001479942c314690e6979d8290bdfb (patch) | |
tree | 45e53f1aca73e38b6bfc42e803e310906a163065 | |
parent | d6e24bd795d5d1d00c2414efe2e5d9e1152c5f5b (diff) | |
download | busybox-w32-b80d7aad1b001479942c314690e6979d8290bdfb.tar.gz busybox-w32-b80d7aad1b001479942c314690e6979d8290bdfb.tar.bz2 busybox-w32-b80d7aad1b001479942c314690e6979d8290bdfb.zip |
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>
-rw-r--r-- | miscutils/bc.c | 77 |
1 files changed, 44 insertions, 33 deletions
diff --git a/miscutils/bc.c b/miscutils/bc.c index 7ddae341f..92bf1df57 100644 --- a/miscutils/bc.c +++ b/miscutils/bc.c | |||
@@ -167,8 +167,9 @@ | |||
167 | # include "dc.c" | 167 | # include "dc.c" |
168 | #else | 168 | #else |
169 | 169 | ||
170 | #define DEBUG_LEXER 0 | 170 | #define DEBUG_LEXER 0 |
171 | #define DEBUG_EXEC 0 | 171 | #define DEBUG_COMPILE 0 |
172 | #define DEBUG_EXEC 0 | ||
172 | 173 | ||
173 | #if DEBUG_LEXER | 174 | #if DEBUG_LEXER |
174 | static uint8_t lex_indent; | 175 | static uint8_t lex_indent; |
@@ -193,6 +194,12 @@ static uint8_t lex_indent; | |||
193 | # define dbg_lex_done(...) ((void)0) | 194 | # define dbg_lex_done(...) ((void)0) |
194 | #endif | 195 | #endif |
195 | 196 | ||
197 | #if DEBUG_COMPILE | ||
198 | # define dbg_compile(...) bb_error_msg(__VA_ARGS__) | ||
199 | #else | ||
200 | # define dbg_compile(...) ((void)0) | ||
201 | #endif | ||
202 | |||
196 | #if DEBUG_EXEC | 203 | #if DEBUG_EXEC |
197 | # define dbg_exec(...) bb_error_msg(__VA_ARGS__) | 204 | # define dbg_exec(...) bb_error_msg(__VA_ARGS__) |
198 | #else | 205 | #else |
@@ -683,7 +690,7 @@ typedef struct BcProgram { | |||
683 | #endif | 690 | #endif |
684 | 691 | ||
685 | BcVec results; | 692 | BcVec results; |
686 | BcVec stack; | 693 | BcVec exestack; |
687 | 694 | ||
688 | BcVec fns; | 695 | BcVec fns; |
689 | BcVec fn_map; | 696 | BcVec fn_map; |
@@ -3448,7 +3455,7 @@ static void bc_parse_addFunc(BcParse *p, char *name, size_t *idx) | |||
3448 | 3455 | ||
3449 | static void bc_parse_push(BcParse *p, char i) | 3456 | static void bc_parse_push(BcParse *p, char i) |
3450 | { | 3457 | { |
3451 | dbg_lex("%s:%d pushing opcode %d", __func__, __LINE__, i); | 3458 | dbg_compile("%s:%d pushing bytecode %zd:%d", __func__, __LINE__, p->func->code.len, i); |
3452 | bc_vec_pushByte(&p->func->code, i); | 3459 | bc_vec_pushByte(&p->func->code, i); |
3453 | } | 3460 | } |
3454 | 3461 | ||
@@ -3537,11 +3544,11 @@ static void bc_program_reset(void) | |||
3537 | BcFunc *f; | 3544 | BcFunc *f; |
3538 | BcInstPtr *ip; | 3545 | BcInstPtr *ip; |
3539 | 3546 | ||
3540 | bc_vec_npop(&G.prog.stack, G.prog.stack.len - 1); | 3547 | bc_vec_npop(&G.prog.exestack, G.prog.exestack.len - 1); |
3541 | bc_vec_pop_all(&G.prog.results); | 3548 | bc_vec_pop_all(&G.prog.results); |
3542 | 3549 | ||
3543 | f = bc_program_func(0); | 3550 | f = bc_program_func(0); |
3544 | ip = bc_vec_top(&G.prog.stack); | 3551 | ip = bc_vec_top(&G.prog.exestack); |
3545 | ip->idx = f->code.len; | 3552 | ip->idx = f->code.len; |
3546 | } | 3553 | } |
3547 | 3554 | ||
@@ -5145,7 +5152,7 @@ static BC_STATUS zbc_program_read(void) | |||
5145 | f = bc_program_func(BC_PROG_READ); | 5152 | f = bc_program_func(BC_PROG_READ); |
5146 | 5153 | ||
5147 | bc_vec_pushByte(&f->code, BC_INST_POP_EXEC); | 5154 | bc_vec_pushByte(&f->code, BC_INST_POP_EXEC); |
5148 | bc_vec_push(&G.prog.stack, &ip); | 5155 | bc_vec_push(&G.prog.exestack, &ip); |
5149 | exec_err: | 5156 | exec_err: |
5150 | bc_parse_free(&parse); | 5157 | bc_parse_free(&parse); |
5151 | G.in_read = 0; | 5158 | G.in_read = 0; |
@@ -5824,12 +5831,13 @@ static BC_STATUS zbc_program_incdec(char inst) | |||
5824 | static BC_STATUS zbc_program_call(char *code, size_t *idx) | 5831 | static BC_STATUS zbc_program_call(char *code, size_t *idx) |
5825 | { | 5832 | { |
5826 | BcInstPtr ip; | 5833 | BcInstPtr ip; |
5827 | size_t i, nparams = bc_program_index(code, idx); | 5834 | size_t i, nparams; |
5828 | BcFunc *func; | 5835 | BcFunc *func; |
5829 | BcId *a; | 5836 | BcId *a; |
5830 | BcResultData param; | 5837 | BcResultData param; |
5831 | BcResult *arg; | 5838 | BcResult *arg; |
5832 | 5839 | ||
5840 | nparams = bc_program_index(code, idx); | ||
5833 | ip.idx = 0; | 5841 | ip.idx = 0; |
5834 | ip.func = bc_program_index(code, idx); | 5842 | ip.func = bc_program_index(code, idx); |
5835 | func = bc_program_func(ip.func); | 5843 | func = bc_program_func(ip.func); |
@@ -5870,7 +5878,7 @@ static BC_STATUS zbc_program_call(char *code, size_t *idx) | |||
5870 | } | 5878 | } |
5871 | } | 5879 | } |
5872 | 5880 | ||
5873 | bc_vec_push(&G.prog.stack, &ip); | 5881 | bc_vec_push(&G.prog.exestack, &ip); |
5874 | 5882 | ||
5875 | RETURN_STATUS(BC_STATUS_SUCCESS); | 5883 | RETURN_STATUS(BC_STATUS_SUCCESS); |
5876 | } | 5884 | } |
@@ -5881,7 +5889,7 @@ static BC_STATUS zbc_program_return(char inst) | |||
5881 | BcResult res; | 5889 | BcResult res; |
5882 | BcFunc *f; | 5890 | BcFunc *f; |
5883 | size_t i; | 5891 | size_t i; |
5884 | BcInstPtr *ip = bc_vec_top(&G.prog.stack); | 5892 | BcInstPtr *ip = bc_vec_top(&G.prog.exestack); |
5885 | 5893 | ||
5886 | if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) | 5894 | if (!BC_PROG_STACK(&G.prog.results, ip->len + inst == BC_INST_RET)) |
5887 | RETURN_STATUS(bc_error_stack_has_too_few_elements()); | 5895 | RETURN_STATUS(bc_error_stack_has_too_few_elements()); |
@@ -5914,7 +5922,7 @@ static BC_STATUS zbc_program_return(char inst) | |||
5914 | 5922 | ||
5915 | bc_vec_npop(&G.prog.results, G.prog.results.len - ip->len); | 5923 | bc_vec_npop(&G.prog.results, G.prog.results.len - ip->len); |
5916 | bc_vec_push(&G.prog.results, &res); | 5924 | bc_vec_push(&G.prog.results, &res); |
5917 | bc_vec_pop(&G.prog.stack); | 5925 | bc_vec_pop(&G.prog.exestack); |
5918 | 5926 | ||
5919 | RETURN_STATUS(BC_STATUS_SUCCESS); | 5927 | RETURN_STATUS(BC_STATUS_SUCCESS); |
5920 | } | 5928 | } |
@@ -6184,13 +6192,13 @@ static BC_STATUS zbc_program_nquit(void) | |||
6184 | 6192 | ||
6185 | bc_vec_pop(&G.prog.results); | 6193 | bc_vec_pop(&G.prog.results); |
6186 | 6194 | ||
6187 | if (G.prog.stack.len < val) | 6195 | if (G.prog.exestack.len < val) |
6188 | RETURN_STATUS(bc_error_stack_has_too_few_elements()); | 6196 | RETURN_STATUS(bc_error_stack_has_too_few_elements()); |
6189 | if (G.prog.stack.len == val) { | 6197 | if (G.prog.exestack.len == val) { |
6190 | QUIT_OR_RETURN_TO_MAIN; | 6198 | QUIT_OR_RETURN_TO_MAIN; |
6191 | } | 6199 | } |
6192 | 6200 | ||
6193 | bc_vec_npop(&G.prog.stack, val); | 6201 | bc_vec_npop(&G.prog.exestack, val); |
6194 | 6202 | ||
6195 | RETURN_STATUS(s); | 6203 | RETURN_STATUS(s); |
6196 | } | 6204 | } |
@@ -6283,7 +6291,7 @@ static BC_STATUS zbc_program_execStr(char *code, size_t *bgn, bool cond) | |||
6283 | ip.func = fidx; | 6291 | ip.func = fidx; |
6284 | 6292 | ||
6285 | bc_vec_pop(&G.prog.results); | 6293 | bc_vec_pop(&G.prog.results); |
6286 | bc_vec_push(&G.prog.stack, &ip); | 6294 | bc_vec_push(&G.prog.exestack, &ip); |
6287 | 6295 | ||
6288 | RETURN_STATUS(BC_STATUS_SUCCESS); | 6296 | RETURN_STATUS(BC_STATUS_SUCCESS); |
6289 | err: | 6297 | err: |
@@ -6348,15 +6356,16 @@ static BC_STATUS zbc_program_exec(void) | |||
6348 | { | 6356 | { |
6349 | BcResult r, *ptr; | 6357 | BcResult r, *ptr; |
6350 | BcNum *num; | 6358 | BcNum *num; |
6351 | BcInstPtr *ip = bc_vec_top(&G.prog.stack); | 6359 | BcInstPtr *ip = bc_vec_top(&G.prog.exestack); |
6352 | BcFunc *func = bc_program_func(ip->func); | 6360 | BcFunc *func = bc_program_func(ip->func); |
6353 | char *code = func->code.v; | 6361 | char *code = func->code.v; |
6354 | 6362 | ||
6363 | dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->idx); | ||
6355 | while (ip->idx < func->code.len) { | 6364 | while (ip->idx < func->code.len) { |
6356 | BcStatus s = BC_STATUS_SUCCESS; | 6365 | BcStatus s = BC_STATUS_SUCCESS; |
6357 | char inst = code[(ip->idx)++]; | 6366 | char inst = code[ip->idx++]; |
6358 | 6367 | ||
6359 | dbg_exec("inst:%d", inst); | 6368 | dbg_exec("inst at %zd:%d", ip->idx - 1, inst); |
6360 | switch (inst) { | 6369 | switch (inst) { |
6361 | #if ENABLE_BC | 6370 | #if ENABLE_BC |
6362 | case BC_INST_JUMP_ZERO: { | 6371 | case BC_INST_JUMP_ZERO: { |
@@ -6382,7 +6391,7 @@ static BC_STATUS zbc_program_exec(void) | |||
6382 | case BC_INST_CALL: | 6391 | case BC_INST_CALL: |
6383 | dbg_exec("BC_INST_CALL:"); | 6392 | dbg_exec("BC_INST_CALL:"); |
6384 | s = zbc_program_call(code, &ip->idx); | 6393 | s = zbc_program_call(code, &ip->idx); |
6385 | break; | 6394 | goto read_updated_ip; |
6386 | case BC_INST_INC_PRE: | 6395 | case BC_INST_INC_PRE: |
6387 | case BC_INST_DEC_PRE: | 6396 | case BC_INST_DEC_PRE: |
6388 | case BC_INST_INC_POST: | 6397 | case BC_INST_INC_POST: |
@@ -6398,7 +6407,7 @@ static BC_STATUS zbc_program_exec(void) | |||
6398 | case BC_INST_RET0: | 6407 | case BC_INST_RET0: |
6399 | dbg_exec("BC_INST_RET[0]:"); | 6408 | dbg_exec("BC_INST_RET[0]:"); |
6400 | s = zbc_program_return(inst); | 6409 | s = zbc_program_return(inst); |
6401 | break; | 6410 | goto read_updated_ip; |
6402 | case BC_INST_BOOL_OR: | 6411 | case BC_INST_BOOL_OR: |
6403 | case BC_INST_BOOL_AND: | 6412 | case BC_INST_BOOL_AND: |
6404 | #endif // ENABLE_BC | 6413 | #endif // ENABLE_BC |
@@ -6414,7 +6423,7 @@ static BC_STATUS zbc_program_exec(void) | |||
6414 | case BC_INST_READ: | 6423 | case BC_INST_READ: |
6415 | dbg_exec("BC_INST_READ:"); | 6424 | dbg_exec("BC_INST_READ:"); |
6416 | s = zbc_program_read(); | 6425 | s = zbc_program_read(); |
6417 | break; | 6426 | goto read_updated_ip; |
6418 | case BC_INST_VAR: | 6427 | case BC_INST_VAR: |
6419 | dbg_exec("BC_INST_VAR:"); | 6428 | dbg_exec("BC_INST_VAR:"); |
6420 | s = zbc_program_pushVar(code, &ip->idx, false, false); | 6429 | s = zbc_program_pushVar(code, &ip->idx, false, false); |
@@ -6454,7 +6463,7 @@ static BC_STATUS zbc_program_exec(void) | |||
6454 | break; | 6463 | break; |
6455 | case BC_INST_POP_EXEC: | 6464 | case BC_INST_POP_EXEC: |
6456 | dbg_exec("BC_INST_POP_EXEC:"); | 6465 | dbg_exec("BC_INST_POP_EXEC:"); |
6457 | bc_vec_pop(&G.prog.stack); | 6466 | bc_vec_pop(&G.prog.exestack); |
6458 | break; | 6467 | break; |
6459 | case BC_INST_PRINT: | 6468 | case BC_INST_PRINT: |
6460 | case BC_INST_PRINT_POP: | 6469 | case BC_INST_PRINT_POP: |
@@ -6513,7 +6522,7 @@ static BC_STATUS zbc_program_exec(void) | |||
6513 | case BC_INST_EXECUTE: | 6522 | case BC_INST_EXECUTE: |
6514 | case BC_INST_EXEC_COND: | 6523 | case BC_INST_EXEC_COND: |
6515 | s = zbc_program_execStr(code, &ip->idx, inst == BC_INST_EXEC_COND); | 6524 | s = zbc_program_execStr(code, &ip->idx, inst == BC_INST_EXEC_COND); |
6516 | break; | 6525 | goto read_updated_ip; |
6517 | case BC_INST_PRINT_STACK: { | 6526 | case BC_INST_PRINT_STACK: { |
6518 | size_t idx; | 6527 | size_t idx; |
6519 | for (idx = 0; idx < G.prog.results.len; ++idx) { | 6528 | for (idx = 0; idx < G.prog.results.len; ++idx) { |
@@ -6566,14 +6575,20 @@ static BC_STATUS zbc_program_exec(void) | |||
6566 | } | 6575 | } |
6567 | case BC_INST_QUIT: | 6576 | case BC_INST_QUIT: |
6568 | dbg_exec("BC_INST_NEG:"); | 6577 | dbg_exec("BC_INST_NEG:"); |
6569 | if (G.prog.stack.len <= 2) | 6578 | if (G.prog.exestack.len <= 2) |
6570 | QUIT_OR_RETURN_TO_MAIN; | 6579 | QUIT_OR_RETURN_TO_MAIN; |
6571 | bc_vec_npop(&G.prog.stack, 2); | 6580 | bc_vec_npop(&G.prog.exestack, 2); |
6572 | break; | 6581 | break; |
6573 | case BC_INST_NQUIT: | 6582 | case BC_INST_NQUIT: |
6574 | s = zbc_program_nquit(); | 6583 | s = zbc_program_nquit(); |
6575 | break; | 6584 | //goto read_updated_ip; - just fall through to it |
6576 | #endif // ENABLE_DC | 6585 | #endif // ENABLE_DC |
6586 | read_updated_ip: | ||
6587 | // Instruction stack has changed, read new pointers | ||
6588 | ip = bc_vec_top(&G.prog.exestack); | ||
6589 | func = bc_program_func(ip->func); | ||
6590 | code = func->code.v; | ||
6591 | dbg_exec("func:%zd bytes:%zd ip:%zd", ip->func, func->code.len, ip->idx); | ||
6577 | } | 6592 | } |
6578 | 6593 | ||
6579 | if (s || G_interrupt) { | 6594 | if (s || G_interrupt) { |
@@ -6583,10 +6598,6 @@ static BC_STATUS zbc_program_exec(void) | |||
6583 | 6598 | ||
6584 | fflush_and_check(); | 6599 | fflush_and_check(); |
6585 | 6600 | ||
6586 | // If the stack has changed, pointers may be invalid. | ||
6587 | ip = bc_vec_top(&G.prog.stack); | ||
6588 | func = bc_program_func(ip->func); | ||
6589 | code = func->code.v; | ||
6590 | } | 6601 | } |
6591 | 6602 | ||
6592 | RETURN_STATUS(BC_STATUS_SUCCESS); | 6603 | RETURN_STATUS(BC_STATUS_SUCCESS); |
@@ -6957,7 +6968,7 @@ static void bc_program_free(void) | |||
6957 | bc_vec_free(&G.prog.strs); | 6968 | bc_vec_free(&G.prog.strs); |
6958 | bc_vec_free(&G.prog.consts); | 6969 | bc_vec_free(&G.prog.consts); |
6959 | bc_vec_free(&G.prog.results); | 6970 | bc_vec_free(&G.prog.results); |
6960 | bc_vec_free(&G.prog.stack); | 6971 | bc_vec_free(&G.prog.exestack); |
6961 | bc_num_free(&G.prog.last); | 6972 | bc_num_free(&G.prog.last); |
6962 | bc_num_free(&G.prog.zero); | 6973 | bc_num_free(&G.prog.zero); |
6963 | bc_num_free(&G.prog.one); | 6974 | bc_num_free(&G.prog.one); |
@@ -7009,8 +7020,8 @@ static void bc_program_init(void) | |||
7009 | bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free); | 7020 | bc_vec_init(&G.prog.strs, sizeof(char *), bc_string_free); |
7010 | bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free); | 7021 | bc_vec_init(&G.prog.consts, sizeof(char *), bc_string_free); |
7011 | bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free); | 7022 | bc_vec_init(&G.prog.results, sizeof(BcResult), bc_result_free); |
7012 | bc_vec_init(&G.prog.stack, sizeof(BcInstPtr), NULL); | 7023 | bc_vec_init(&G.prog.exestack, sizeof(BcInstPtr), NULL); |
7013 | bc_vec_push(&G.prog.stack, &ip); | 7024 | bc_vec_push(&G.prog.exestack, &ip); |
7014 | 7025 | ||
7015 | bc_char_vec_init(&G.input_buffer); | 7026 | bc_char_vec_init(&G.input_buffer); |
7016 | } | 7027 | } |