awk: free unused parsing structures after parse is done
function old new delta hash_clear - 90 +90 awk_main 827 849 +22 clear_array 90 - -90 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 1/0 up/down: 112/-90) Total: 22 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		| @@ -530,7 +530,8 @@ struct globals { | ||||
| 	xhash *ahash;  /* argument names, used only while parsing function bodies */ | ||||
| 	xhash *fnhash; /* function names, used only in parsing stage */ | ||||
| 	xhash *vhash;  /* variables and arrays */ | ||||
| 	xhash *fdhash; /* file objects, used only in execution stage */ | ||||
| 	//xhash *fdhash; /* file objects, used only in execution stage */ | ||||
| 	//we are reusing ahash as fdhash, via define (see later) | ||||
| 	const char *g_progname; | ||||
| 	int g_lineno; | ||||
| 	int nfields; | ||||
| @@ -592,10 +593,13 @@ struct globals2 { | ||||
| #define break_ptr    (G1.break_ptr   ) | ||||
| #define continue_ptr (G1.continue_ptr) | ||||
| #define iF           (G1.iF          ) | ||||
| #define vhash        (G1.vhash       ) | ||||
| #define ahash        (G1.ahash       ) | ||||
| #define fdhash       (G1.fdhash      ) | ||||
| #define fnhash       (G1.fnhash      ) | ||||
| #define vhash        (G1.vhash       ) | ||||
| #define fdhash       ahash | ||||
| //^^^^^^^^^^^^^^^^^^ ahash is cleared after every function parsing, | ||||
| // and ends up empty after parsing phase. Thus, we can simply reuse it | ||||
| // for fdhash in execution stage. | ||||
| #define g_progname   (G1.g_progname  ) | ||||
| #define g_lineno     (G1.g_lineno    ) | ||||
| #define nfields      (G1.nfields     ) | ||||
| @@ -682,6 +686,33 @@ static xhash *hash_init(void) | ||||
| 	return newhash; | ||||
| } | ||||
|  | ||||
| static void hash_clear(xhash *hash) | ||||
| { | ||||
| 	unsigned i; | ||||
| 	hash_item *hi, *thi; | ||||
|  | ||||
| 	for (i = 0; i < hash->csize; i++) { | ||||
| 		hi = hash->items[i]; | ||||
| 		while (hi) { | ||||
| 			thi = hi; | ||||
| 			hi = hi->next; | ||||
| 			free(thi->data.v.string); | ||||
| 			free(thi); | ||||
| 		} | ||||
| 		hash->items[i] = NULL; | ||||
| 	} | ||||
| 	hash->glen = hash->nel = 0; | ||||
| } | ||||
|  | ||||
| #if 0 //UNUSED | ||||
| static void hash_free(xhash *hash) | ||||
| { | ||||
| 	hash_clear(hash); | ||||
| 	free(hash->items); | ||||
| 	free(hash); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| /* find item in hash, return ptr to data, NULL if not found */ | ||||
| static void *hash_search(xhash *hash, const char *name) | ||||
| { | ||||
| @@ -869,23 +900,7 @@ static xhash *iamarray(var *v) | ||||
| 	return a->x.array; | ||||
| } | ||||
|  | ||||
| static void clear_array(xhash *array) | ||||
| { | ||||
| 	unsigned i; | ||||
| 	hash_item *hi, *thi; | ||||
|  | ||||
| 	for (i = 0; i < array->csize; i++) { | ||||
| 		hi = array->items[i]; | ||||
| 		while (hi) { | ||||
| 			thi = hi; | ||||
| 			hi = hi->next; | ||||
| 			free(thi->data.v.string); | ||||
| 			free(thi); | ||||
| 		} | ||||
| 		array->items[i] = NULL; | ||||
| 	} | ||||
| 	array->glen = array->nel = 0; | ||||
| } | ||||
| #define clear_array(array) hash_clear(array) | ||||
|  | ||||
| /* clear a variable */ | ||||
| static var *clrvar(var *v) | ||||
| @@ -1742,7 +1757,7 @@ static void parse_program(char *p) | ||||
| 			} | ||||
| 			seq = &f->body; | ||||
| 			chain_group(); | ||||
| 			clear_array(ahash); | ||||
| 			hash_clear(ahash); | ||||
| 		} else if (tclass & TS_OPSEQ) { | ||||
| 			debug_printf_parse("%s: TS_OPSEQ\n", __func__); | ||||
| 			rollback_token(); | ||||
| @@ -3471,11 +3486,16 @@ int awk_main(int argc UNUSED_PARAM, char **argv) | ||||
| 			bb_show_usage(); | ||||
| 		parse_program(*argv++); | ||||
| 	} | ||||
| 	//free_hash(ahash) // ~250 bytes, arg names, used only during parse of function bodies | ||||
| 	//ahash = NULL; // debug | ||||
| 	//free_hash(fnhash) // ~250 bytes, used only for function names | ||||
| 	//fnhash = NULL; // debug | ||||
| 	/* parsing done, on to executing */ | ||||
| 	/* Free unused parse structures */ | ||||
| 	//hash_free(fnhash); // ~250 bytes when empty, used only for function names | ||||
| 	//^^^^^^^^^^^^^^^^^ does not work, hash_clear() inside SEGVs | ||||
| 	// (IOW: hash_clear() assumes it's a hash of variables. fnhash is not). | ||||
| 	free(fnhash->items); | ||||
| 	free(fnhash); | ||||
| 	fnhash = NULL; // debug | ||||
| 	//hash_free(ahash); // empty after parsing, will reuse as fdhash instead of freeing | ||||
|  | ||||
| 	/* Parsing done, on to executing */ | ||||
|  | ||||
| 	/* fill in ARGV array */ | ||||
| 	setari_u(intvar[ARGV], 0, "awk"); | ||||
| @@ -3484,7 +3504,7 @@ int awk_main(int argc UNUSED_PARAM, char **argv) | ||||
| 		setari_u(intvar[ARGV], ++i, *argv++); | ||||
| 	setvar_i(intvar[ARGC], i + 1); | ||||
|  | ||||
| 	fdhash = hash_init(); | ||||
| 	//fdhash = ahash - done via define | ||||
| 	newfile("/dev/stdin")->F = stdin; | ||||
| 	newfile("/dev/stdout")->F = stdout; | ||||
| 	newfile("/dev/stderr")->F = stderr; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user