bc: rewrite "block flag stack" using simple realloc'ed byte array

Each access to current top flag took a function call + fetch of three data items
+ multiplication and some additions + and then following the resulting pointer.

After the change, it is: fetch pointer value + one byte access via this pointer.

function                                             old     new   delta
bc_parse_startBody                                    45      49      +4
bc_parse_free                                         46      47      +1
zbc_parse_auto                                       188     185      -3
bc_parse_push                                         14      11      -3
bc_vm_run                                            398     394      -4
zbc_vm_process                                        63      58      -5
zdc_parse_expr                                       638     632      -6
zbc_parse_body                                       101      95      -6
bc_parse_addFunc                                      31      25      -6
bc_parse_noElse                                       56      48      -8
zcommon_parse                                        341     331     -10
zbc_parse_else                                       134     123     -11
bc_parse_create                                      124     108     -16
zbc_parse_text_init                                  123     104     -19
zbc_parse_endBody                                    292     252     -40
zbc_parse_stmt                                      1479    1420     -59
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/14 up/down: 5/-196)          Total: -191 bytes
   text	   data	    bss	    dec	    hex	filename
 979880	    485	   7296	 987661	  f120d	busybox_old
 979689	    485	   7296	 987470	  f114e	busybox_unstripped

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2018-12-15 00:39:17 +01:00
parent f10f17f8d3
commit 7db384338a

View File

@ -574,8 +574,9 @@ typedef struct BcLex {
#define BC_PARSE_NOREAD (1 << 3) #define BC_PARSE_NOREAD (1 << 3)
#define BC_PARSE_ARRAY (1 << 4) #define BC_PARSE_ARRAY (1 << 4)
#define BC_PARSE_TOP_FLAG_PTR(parse) ((uint8_t *) bc_vec_top(&(parse)->flags)) #define BC_PARSE_TOP_FLAG_PTR(parse) ((parse)->bf_top)
#define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse))) #define BC_PARSE_TOP_FLAG(parse) (*(BC_PARSE_TOP_FLAG_PTR(parse)))
#define BC_PARSE_FLAG_STACK_EMPTY(p) ((p)->bf_top == (p)->bf_base)
#define BC_PARSE_FLAG_FUNC_INNER (1 << 0) #define BC_PARSE_FLAG_FUNC_INNER (1 << 0)
#define BC_PARSE_FLAG_FUNC (1 << 1) #define BC_PARSE_FLAG_FUNC (1 << 1)
@ -598,15 +599,11 @@ typedef struct BcLex {
#define BC_PARSE_ELSE(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_ELSE) #define BC_PARSE_ELSE(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_ELSE)
#define BC_PARSE_IF_END(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF_END) #define BC_PARSE_IF_END(parse) (BC_PARSE_TOP_FLAG(parse) & BC_PARSE_FLAG_IF_END)
struct BcParse;
struct BcProgram;
typedef struct BcParse { typedef struct BcParse {
BcLex l; BcLex l;
BcVec flags; uint8_t *bf_base;
uint8_t *bf_top;
BcVec exits; BcVec exits;
BcVec conds; BcVec conds;
@ -618,7 +615,6 @@ typedef struct BcParse {
size_t nbraces; size_t nbraces;
bool auto_part; bool auto_part;
} BcParse; } BcParse;
typedef struct BcProgram { typedef struct BcProgram {
@ -3558,7 +3554,7 @@ static void bc_parse_reset(BcParse *p)
p->l.t.t = BC_LEX_EOF; p->l.t.t = BC_LEX_EOF;
p->auto_part = (p->nbraces = 0); p->auto_part = (p->nbraces = 0);
bc_vec_npop(&p->flags, p->flags.len - 1); p->bf_top = p->bf_base; // pop all flags
bc_vec_pop_all(&p->exits); bc_vec_pop_all(&p->exits);
bc_vec_pop_all(&p->conds); bc_vec_pop_all(&p->conds);
bc_vec_pop_all(&p->ops); bc_vec_pop_all(&p->ops);
@ -3568,7 +3564,7 @@ static void bc_parse_reset(BcParse *p)
static void bc_parse_free(BcParse *p) static void bc_parse_free(BcParse *p)
{ {
bc_vec_free(&p->flags); free(p->bf_base);
bc_vec_free(&p->exits); bc_vec_free(&p->exits);
bc_vec_free(&p->conds); bc_vec_free(&p->conds);
bc_vec_free(&p->ops); bc_vec_free(&p->ops);
@ -3580,10 +3576,9 @@ static void bc_parse_create(BcParse *p, size_t func)
memset(p, 0, sizeof(BcParse)); memset(p, 0, sizeof(BcParse));
bc_lex_init(&p->l); bc_lex_init(&p->l);
bc_vec_init(&p->flags, sizeof(uint8_t), NULL); p->bf_top = p->bf_base = xzalloc(1);
bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL); bc_vec_init(&p->exits, sizeof(BcInstPtr), NULL);
bc_vec_init(&p->conds, sizeof(size_t), NULL); bc_vec_init(&p->conds, sizeof(size_t), NULL);
bc_vec_pushZeroByte(&p->flags);
bc_vec_init(&p->ops, sizeof(BcLexType), NULL); bc_vec_init(&p->ops, sizeof(BcLexType), NULL);
// p->auto_part = p->nbraces = 0; - already is // p->auto_part = p->nbraces = 0; - already is
@ -4050,7 +4045,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p)
{ {
BcStatus s = BC_STATUS_SUCCESS; BcStatus s = BC_STATUS_SUCCESS;
if (p->flags.len <= 1) if (BC_PARSE_FLAG_STACK_EMPTY(p))
RETURN_STATUS(bc_error_bad_token()); RETURN_STATUS(bc_error_bad_token());
if (BC_PARSE_IF(p)) { if (BC_PARSE_IF(p)) {
@ -4061,7 +4056,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p)
if (s) RETURN_STATUS(s); if (s) RETURN_STATUS(s);
} }
bc_vec_pop(&p->flags); p->bf_top--;
flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
dbg_lex("%s:%d setting BC_PARSE_FLAG_IF_END bit", __func__, __LINE__); dbg_lex("%s:%d setting BC_PARSE_FLAG_IF_END bit", __func__, __LINE__);
@ -4074,7 +4069,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p)
BcInstPtr *ip; BcInstPtr *ip;
size_t *label; size_t *label;
bc_vec_pop(&p->flags); p->bf_top--;
ip = bc_vec_top(&p->exits); ip = bc_vec_top(&p->exits);
label = bc_vec_item(&p->func->labels, ip->idx); label = bc_vec_item(&p->func->labels, ip->idx);
@ -4085,7 +4080,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p)
else if (BC_PARSE_FUNC_INNER(p)) { else if (BC_PARSE_FUNC_INNER(p)) {
bc_parse_push(p, BC_INST_RET0); bc_parse_push(p, BC_INST_RET0);
bc_parse_updateFunc(p, BC_PROG_MAIN); bc_parse_updateFunc(p, BC_PROG_MAIN);
bc_vec_pop(&p->flags); p->bf_top--;
} }
else { else {
BcInstPtr *ip = bc_vec_top(&p->exits); BcInstPtr *ip = bc_vec_top(&p->exits);
@ -4097,7 +4092,7 @@ static BC_STATUS zbc_parse_endBody(BcParse *p)
label = bc_vec_item(&p->func->labels, ip->idx); label = bc_vec_item(&p->func->labels, ip->idx);
*label = p->func->code.len; *label = p->func->code.len;
bc_vec_pop(&p->flags); p->bf_top--;
bc_vec_pop(&p->exits); bc_vec_pop(&p->exits);
bc_vec_pop(&p->conds); bc_vec_pop(&p->conds);
} }
@ -4110,10 +4105,15 @@ static BC_STATUS zbc_parse_endBody(BcParse *p)
static void bc_parse_startBody(BcParse *p, uint8_t flags) static void bc_parse_startBody(BcParse *p, uint8_t flags)
{ {
size_t size;
uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p); uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
flags |= (*flag_ptr & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP)); flags |= (*flag_ptr & (BC_PARSE_FLAG_FUNC | BC_PARSE_FLAG_LOOP));
flags |= BC_PARSE_FLAG_BODY; flags |= BC_PARSE_FLAG_BODY;
bc_vec_push(&p->flags, &flags);
size = p->bf_top - p->bf_base;
p->bf_base = xrealloc(p->bf_base, size + 2);
p->bf_top = p->bf_base + size + 1;
*p->bf_top = flags;
} }
static void bc_parse_noElse(BcParse *p) static void bc_parse_noElse(BcParse *p)
@ -4492,7 +4492,7 @@ err:
static BC_STATUS zbc_parse_body(BcParse *p, bool brace) static BC_STATUS zbc_parse_body(BcParse *p, bool brace)
{ {
BcStatus s = BC_STATUS_SUCCESS; BcStatus s = BC_STATUS_SUCCESS;
uint8_t *flag_ptr = bc_vec_top(&p->flags); uint8_t *flag_ptr = BC_PARSE_TOP_FLAG_PTR(p);
dbg_lex_enter("%s:%d entered", __func__, __LINE__); dbg_lex_enter("%s:%d entered", __func__, __LINE__);
*flag_ptr &= ~(BC_PARSE_FLAG_BODY); *flag_ptr &= ~(BC_PARSE_FLAG_BODY);
@ -4535,10 +4535,12 @@ static BC_STATUS zbc_parse_stmt(BcParse *p)
RETURN_STATUS(zbc_lex_next(&p->l)); RETURN_STATUS(zbc_lex_next(&p->l));
case BC_LEX_KEY_ELSE: case BC_LEX_KEY_ELSE:
dbg_lex("%s:%d BC_LEX_KEY_ELSE:", __func__, __LINE__);
p->auto_part = false; p->auto_part = false;
break; break;
case BC_LEX_LBRACE: case BC_LEX_LBRACE:
dbg_lex("%s:%d BC_LEX_LBRACE:", __func__, __LINE__);
if (!BC_PARSE_BODY(p)) RETURN_STATUS(bc_error_bad_token()); if (!BC_PARSE_BODY(p)) RETURN_STATUS(bc_error_bad_token());
++p->nbraces; ++p->nbraces;
s = zbc_lex_next(&p->l); s = zbc_lex_next(&p->l);
@ -4547,6 +4549,7 @@ static BC_STATUS zbc_parse_stmt(BcParse *p)
RETURN_STATUS(zbc_parse_body(p, true)); RETURN_STATUS(zbc_parse_body(p, true));
case BC_LEX_KEY_AUTO: case BC_LEX_KEY_AUTO:
dbg_lex("%s:%d BC_LEX_KEY_AUTO:", __func__, __LINE__);
RETURN_STATUS(zbc_parse_auto(p)); RETURN_STATUS(zbc_parse_auto(p));
default: default:
@ -4660,7 +4663,7 @@ static BC_STATUS zbc_parse_parse(BcParse *p)
dbg_lex_enter("%s:%d entered", __func__, __LINE__); dbg_lex_enter("%s:%d entered", __func__, __LINE__);
if (p->l.t.t == BC_LEX_EOF) if (p->l.t.t == BC_LEX_EOF)
s = p->flags.len > 0 ? bc_error("block end could not be found") : bc_error("end of file"); s = BC_PARSE_FLAG_STACK_EMPTY(p) ? bc_error("end of file") : bc_error("block end could not be found");
else if (p->l.t.t == BC_LEX_KEY_DEFINE) { else if (p->l.t.t == BC_LEX_KEY_DEFINE) {
dbg_lex("%s:%d p->l.t.t:BC_LEX_KEY_DEFINE", __func__, __LINE__); dbg_lex("%s:%d p->l.t.t:BC_LEX_KEY_DEFINE", __func__, __LINE__);
if (!BC_PARSE_CAN_EXEC(p)) if (!BC_PARSE_CAN_EXEC(p))