bc: make long-running dc drop data it does not need (when it can)
function old new delta zbc_vm_process 765 824 +59 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
		| @@ -3437,11 +3437,11 @@ static BC_STATUS zdc_lex_token(BcLex *l) | ||||
| //			break; | ||||
| 		case '\n': | ||||
| 			// '\n' is BC_LEX_NLINE, not BC_LEX_WHITESPACE | ||||
| 			// (and "case '\n'" is not just empty here) | ||||
| 			// (and "case '\n':" is not just empty here) | ||||
| 			// only to allow interactive dc have a way to exit | ||||
| 			// "parse" stage of "parse,execute" loop | ||||
| 			// on '\n', not on _next_ token (which would mean | ||||
| 			// command are not executed on pressing <enter>). | ||||
| 			// on <enter>, not on _next_ token (which would mean | ||||
| 			// commands are not executed on pressing <enter>). | ||||
| 			// IOW: typing "1p<enter>" should print "1" _at once_, | ||||
| 			// not after some more input. | ||||
| 			l->t.t = BC_LEX_NLINE; | ||||
| @@ -6673,6 +6673,9 @@ static BC_STATUS zbc_vm_process(const char *text) | ||||
| 	if (s) RETURN_STATUS(s); | ||||
|  | ||||
| 	while (G.prs.l.t.t != BC_LEX_EOF) { | ||||
| 		BcInstPtr *ip; | ||||
| 		BcFunc *f; | ||||
|  | ||||
| 		dbg_lex("%s:%d G.prs.l.t.t:%d, parsing...", __func__, __LINE__, G.prs.l.t.t); | ||||
| 		if (IS_BC) { | ||||
| // FIXME: "eating" of stmt delimiters is coded inconsistently | ||||
| @@ -6695,6 +6698,15 @@ static BC_STATUS zbc_vm_process(const char *text) | ||||
| 			bc_program_reset(); | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		ip = (void*)G.prog.exestack.v; | ||||
| #if SANITY_CHECKS | ||||
| 		if (G.prog.exestack.len != 1) // should have only main's IP | ||||
| 			bb_error_msg_and_die("BUG:call stack"); | ||||
| 		if (ip->func != BC_PROG_MAIN) | ||||
| 			bb_error_msg_and_die("BUG:not MAIN"); | ||||
| #endif | ||||
| 		f = bc_program_func_BC_PROG_MAIN(); | ||||
| 		// bc discards strings, constants and code after each | ||||
| 		// top-level statement in the "main program". | ||||
| 		// This prevents "yes 1 | bc" from growing its memory | ||||
| @@ -6706,22 +6718,10 @@ static BC_STATUS zbc_vm_process(const char *text) | ||||
| 		// but bc stores function strings/constants in per-function | ||||
| 		// storage. | ||||
| 		if (IS_BC) { | ||||
| 			BcFunc *f; | ||||
| 			BcInstPtr *ip = (void*)G.prog.exestack.v; | ||||
|  | ||||
| #if SANITY_CHECKS | ||||
| 			if (G.prog.results.len != 0) // should be empty | ||||
| 				bb_error_msg_and_die("BUG:data stack"); | ||||
| 			if (G.prog.exestack.len != 1) // should have only main's IP | ||||
| 				bb_error_msg_and_die("BUG:call stack"); | ||||
| 			if (ip->func != BC_PROG_MAIN) | ||||
| 				bb_error_msg_and_die("BUG:not MAIN"); | ||||
| #endif | ||||
| //bb_error_msg("ip->func:%d >idx:%d >len:%d", ip->func, ip->inst_idx, ip->len); | ||||
| 			f = bc_program_func_BC_PROG_MAIN(); | ||||
| //bb_error_msg("MAIN->code.len:%d >strs.len:%d >consts.len:%d", f->code.len, f->strs.len, f->consts.len); // labels, autos, nparams | ||||
| 			bc_vec_pop_all(&f->code); | ||||
| 			ip->inst_idx = 0; | ||||
| 			IF_BC(bc_vec_pop_all(&f->strs);) | ||||
| 			IF_BC(bc_vec_pop_all(&f->consts);) | ||||
| 		} else { | ||||
| @@ -6731,7 +6731,26 @@ static BC_STATUS zbc_vm_process(const char *text) | ||||
| 				s = zbc_lex_next(&G.prs.l); | ||||
| 				if (s) RETURN_STATUS(s); | ||||
| 			} | ||||
|  | ||||
| 			if (G.prog.results.len == 0 | ||||
| 			 && G.prog.vars.len == 0 | ||||
| 			) { | ||||
| 				// If stack is empty and no registers exist (TODO: or they are all empty), | ||||
| 				// we can get rid of accumulated strings and constants. | ||||
| 				// In this example dc process should not grow | ||||
| 				// its memory consumption with time: | ||||
| 				// yes 1pc | dc | ||||
| 				IF_DC(bc_vec_pop_all(&G.prog.strs);) | ||||
| 				IF_DC(bc_vec_pop_all(&G.prog.consts);) | ||||
| 			} | ||||
| 			// The code is discarded always (below), thus this example | ||||
| 			// should also not grow its memory consumption with time, | ||||
| 			// even though its data stack is not empty: | ||||
| 			// { echo 1; yes dk; } | dc | ||||
| 		} | ||||
| 		// We drop generated and executed code for both bc and dc: | ||||
| 		bc_vec_pop_all(&f->code); | ||||
| 		ip->inst_idx = 0; | ||||
| 	} | ||||
|  | ||||
| 	dbg_lex_done("%s:%d done", __func__, __LINE__); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user