diff options
Diffstat (limited to 'symbol.c')
-rw-r--r-- | symbol.c | 166 |
1 files changed, 87 insertions, 79 deletions
@@ -2,22 +2,22 @@ * symbol.c - routines for symbol table management and code allocation */ -/* +/* * Copyright (C) 1986, 1988, 1989, 1991-2015 the Free Software Foundation, Inc. - * + * * This file is part of GAWK, the GNU implementation of the * AWK Programming Language. - * + * * GAWK is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. - * + * * GAWK is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA @@ -37,7 +37,7 @@ static NODE *symbol_list; static void (*install_func)(NODE *) = NULL; static NODE *make_symbol(const char *name, NODETYPE type); static NODE *install(const char *name, NODE *parm, NODETYPE type); -static void free_bcpool(INSTRUCTION *pl); +static void free_bcpool(INSTRUCTION_POOL *pl); static AWK_CONTEXT *curr_ctxt = NULL; static int ctxt_level; @@ -71,7 +71,7 @@ init_symbol_table() /* * install_symbol: * Install a global name in the symbol table, even if it is already there. - * Caller must check against redefinition if that is desired. + * Caller must check against redefinition if that is desired. */ NODE * @@ -129,12 +129,11 @@ make_params(char **pnames, int pcount) { NODE *p, *parms; int i; - + if (pcount <= 0 || pnames == NULL) return NULL; - emalloc(parms, NODE *, pcount * sizeof(NODE), "make_params"); - memset(parms, '\0', pcount * sizeof(NODE)); + ezalloc(parms, NODE *, pcount * sizeof(NODE), "make_params"); for (i = 0, p = parms; i < pcount; i++, p++) { p->type = Node_param_list; @@ -242,12 +241,12 @@ destroy_symbol(NODE *r) NODE *n; int i; int pcount = r->param_cnt; - - /* function parameters of type Node_param_list */ + + /* function parameters of type Node_param_list */ for (i = 0; i < pcount; i++) { n = r->fparms + i; efree(n->param); - } + } efree(r->fparms); } break; @@ -260,7 +259,7 @@ destroy_symbol(NODE *r) assoc_clear(r); break; - case Node_var: + case Node_var: unref(r->var_value); break; @@ -369,7 +368,7 @@ comp_symbol(const void *v1, const void *v2) typedef enum { FUNCTION = 1, VARIABLE } SYMBOL_TYPE; /* get_symbols --- return a list of optionally sorted symbols */ - + static NODE ** get_symbols(SYMBOL_TYPE what, bool sort) { @@ -448,7 +447,7 @@ function_list(bool sort) return get_symbols(FUNCTION, sort); } -/* print_vars --- print names and values of global variables */ +/* print_vars --- print names and values of global variables */ void print_vars(NODE **table, int (*print_func)(FILE *, const char *, ...), FILE *fp) @@ -652,7 +651,7 @@ check_param_names(void) memset(& n, 0, sizeof n); n.type = Node_val; n.flags = STRING|STRCUR; - n.stfmt = -1; + n.stfmt = STFMT_UNUSED; /* * assoc_list() returns an array with two elements per awk array @@ -693,22 +692,31 @@ check_param_names(void) return result; } -#define pool_size d.dl -#define freei x.xi -static INSTRUCTION *pool_list; +static INSTRUCTION_POOL *pools; + +/* + * For best performance, the INSTR_CHUNK value should be divisible by all + * possible sizes, i.e. 1 through MAX_INSTRUCTION_ALLOC. Otherwise, there + * will be wasted space at the end of the block. + */ +#define INSTR_CHUNK (2*3*21) -/* INSTR_CHUNK must be > largest code size (3) */ -#define INSTR_CHUNK 127 +struct instruction_block { + struct instruction_block *next; + INSTRUCTION i[INSTR_CHUNK]; +}; /* bcfree --- deallocate instruction */ void bcfree(INSTRUCTION *cp) { - cp->opcode = 0; - cp->nexti = pool_list->freei; - pool_list->freei = cp; -} + assert(cp->pool_size >= 1 && cp->pool_size <= MAX_INSTRUCTION_ALLOC); + + cp->opcode = Op_illegal; + cp->nexti = pools->pool[cp->pool_size - 1].free_list; + pools->pool[cp->pool_size - 1].free_list = cp; +} /* bcalloc --- allocate a new instruction */ @@ -716,38 +724,28 @@ INSTRUCTION * bcalloc(OPCODE op, int size, int srcline) { INSTRUCTION *cp; + struct instruction_mem_pool *pool; - if (size > 1) { - /* wide instructions Op_rule, Op_func_call .. */ - emalloc(cp, INSTRUCTION *, (size + 1) * sizeof(INSTRUCTION), "bcalloc"); - cp->pool_size = size; - cp->nexti = pool_list->nexti; - pool_list->nexti = cp++; + assert(size >= 1 && size <= MAX_INSTRUCTION_ALLOC); + pool = &pools->pool[size - 1]; + + if (pool->free_list != NULL) { + cp = pool->free_list; + pool->free_list = cp->nexti; + } else if (pool->free_space && pool->free_space + size <= & pool->block_list->i[INSTR_CHUNK]) { + cp = pool->free_space; + pool->free_space += size; } else { - INSTRUCTION *pool; - - pool = pool_list->freei; - if (pool == NULL) { - INSTRUCTION *last; - emalloc(cp, INSTRUCTION *, (INSTR_CHUNK + 1) * sizeof(INSTRUCTION), "bcalloc"); - - cp->pool_size = INSTR_CHUNK; - cp->nexti = pool_list->nexti; - pool_list->nexti = cp; - pool = ++cp; - last = &pool[INSTR_CHUNK - 1]; - for (; cp <= last; cp++) { - cp->opcode = 0; - cp->nexti = cp + 1; - } - --cp; - cp->nexti = NULL; - } - cp = pool; - pool_list->freei = cp->nexti; + struct instruction_block *block; + emalloc(block, struct instruction_block *, sizeof(struct instruction_block), "bcalloc"); + block->next = pool->block_list; + pool->block_list = block; + cp = &block->i[0]; + pool->free_space = &block->i[size]; } memset(cp, 0, size * sizeof(INSTRUCTION)); + cp->pool_size = size; cp->opcode = op; cp->source_line = srcline; return cp; @@ -760,8 +758,7 @@ new_context() { AWK_CONTEXT *ctxt; - emalloc(ctxt, AWK_CONTEXT *, sizeof(AWK_CONTEXT), "new_context"); - memset(ctxt, 0, sizeof(AWK_CONTEXT)); + ezalloc(ctxt, AWK_CONTEXT *, sizeof(AWK_CONTEXT), "new_context"); ctxt->srcfiles.next = ctxt->srcfiles.prev = & ctxt->srcfiles; ctxt->rule_list.opcode = Op_list; ctxt->rule_list.lasti = & ctxt->rule_list; @@ -773,7 +770,7 @@ new_context() static void set_context(AWK_CONTEXT *ctxt) { - pool_list = & ctxt->pools; + pools = & ctxt->pools; symbol_list = & ctxt->symbols; srcfiles = & ctxt->srcfiles; rule_list = & ctxt->rule_list; @@ -804,7 +801,7 @@ push_context(AWK_CONTEXT *ctxt) ctxt_level++; } -/* pop_context --- switch to previous execution context. */ +/* pop_context --- switch to previous execution context. */ void pop_context() @@ -831,7 +828,7 @@ in_main_context() return (ctxt_level == 1); } -/* free_context --- free context structure and related data. */ +/* free_context --- free context structure and related data. */ void free_context(AWK_CONTEXT *ctxt, bool keep_globals) @@ -864,7 +861,7 @@ free_context(AWK_CONTEXT *ctxt, bool keep_globals) efree(ctxt); } -/* free_bc_internal --- free internal memory of an instruction. */ +/* free_bc_internal --- free internal memory of an instruction. */ static void free_bc_internal(INSTRUCTION *cp) @@ -881,14 +878,16 @@ free_bc_internal(INSTRUCTION *cp) case Op_match: case Op_nomatch: m = cp->memory; - if (m->re_reg != NULL) - refree(m->re_reg); + if (m->re_reg[0] != NULL) + refree(m->re_reg[0]); + if (m->re_reg[1] != NULL) + refree(m->re_reg[1]); if (m->re_exp != NULL) unref(m->re_exp); if (m->re_text != NULL) unref(m->re_text); freenode(m); - break; + break; case Op_token: /* token lost during error recovery in yyparse */ if (cp->lextok != NULL) @@ -906,31 +905,40 @@ free_bc_internal(INSTRUCTION *cp) case Op_illegal: cant_happen(); default: - break; + break; } } -/* free_bcpool --- free list of instruction memory pools */ +/* free_bc_mempool --- free a single pool */ static void -free_bcpool(INSTRUCTION *pl) +free_bc_mempool(struct instruction_mem_pool *pool, int size) { - INSTRUCTION *pool, *tmp; + bool first = true; + struct instruction_block *block, *next; - for (pool = pl->nexti; pool != NULL; pool = tmp) { - INSTRUCTION *cp, *last; - long psiz; - psiz = pool->pool_size; - if (psiz == INSTR_CHUNK) - last = pool + psiz; - else - last = pool + 1; - for (cp = pool + 1; cp <= last ; cp++) { - if (cp->opcode != 0) + for (block = pool->block_list; block; block = next) { + INSTRUCTION *cp, *end; + + end = (first ? pool->free_space : & block->i[INSTR_CHUNK]); + for (cp = & block->i[0]; cp + size <= end; cp += size) { + if (cp->opcode != Op_illegal) free_bc_internal(cp); } - tmp = pool->nexti; - efree(pool); + next = block->next; + efree(block); + first = false; } - memset(pl, 0, sizeof(INSTRUCTION)); +} + + +/* free_bcpool --- free list of instruction memory pools */ + +static void +free_bcpool(INSTRUCTION_POOL *pl) +{ + int i; + + for (i = 0; i < MAX_INSTRUCTION_ALLOC; i++) + free_bc_mempool(& pl->pool[i], i + 1); } |