aboutsummaryrefslogtreecommitdiffstats
path: root/symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'symbol.c')
-rw-r--r--symbol.c166
1 files changed, 87 insertions, 79 deletions
diff --git a/symbol.c b/symbol.c
index fe7e3753..cbbd8ed2 100644
--- a/symbol.c
+++ b/symbol.c
@@ -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);
}