From c61ccd9769c9c83dcdf5f7693af2ca0a605b6e19 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Sat, 29 Mar 2014 11:44:52 -0700 Subject: Change to how locations are passed around, for the sake of generational GC. The issue being solved here is the accuracy of the gc_set function. The existing impelmentation is too conservative. It has no generation information about the memory location being stored, and so it assumes the worst: that it is a location in the middle of a gen 1 object. This is sub-optimal, creating unacceptable pressure against the checkobj array and, worse, as a consequence causing unreachable gen 0 objects to be tenured into gen 1. To solve this problem, we replace "val *" pointers with a structure of type "loc" which keeps track of the object too, which lets us discover the generation. I tried another approach: using just a pointer with a bitfield indicating the generation. This turned out to have a serious issue: such a bitfield goes stale when the object is moved to a different generation. The object holding the memory location is in gen 1, but the annotated pointer still indicates gen 0. The gc_set function then makes the wrong decision, and premature reclamation takes place. * combi.c (perm_init_common, comb_gen_fun_common, rcomb_gen_fun_common, rcomb_list_gen_fun): Update to new interfaces for managing mutation. * debug.c (debug): Update to new interfaces for managing mutation. Avoid loc variable name. * eval.c (env_fbind, env_fbind): Update to new interfaces for managing mutation. (lookup_var_l, dwim_loc): Return loc type and update to new interfaces. (apply_frob_args, op_modplace, op_dohash, transform_op, mapcarv, mappendv, repeat_infinite_func, repeat_times_func): Update to new interfaces for managing mutation. * eval.h (lookup_var_l): Declaration updated. * filter.c (trie_add, trie_compress, trie_compress_intrinsic, * build_filter, built_filter_from_list, filter_init): Update to new * interfaces. * gc.c (gc_set): Rewritten to use loc type which provides the exact generation. We do not need the in_malloc_range hack any more, since we have the backpointer to the object. (gc_push): Take loc rather than raw pointer. * gc.h (gc_set, gc_push): Declarations updated. * hash.c (struct hash): The acons* functions use loc instead of val * now. (hash_equal_op, copy_hash, gethash_c, inhash, gethash_n, pushhash, Change to how locations are passed around, for the sake of generational GC. The issue being solved here is the accuracy of the gc_set function. The existing impelmentation is too conservative. It has no generation information about the memory location being stored, and so it assumes the worst: that it is a location in the middle of a gen 1 object. This is sub-optimal, creating unacceptable pressure against the checkobj array and, worse, as a consequence causing unreachable gen 0 objects to be tenured into gen 1. To solve this problem, we replace "val *" pointers with a structure of type "loc" which keeps track of the object too, which lets us discover the generation. I tried another approach: using just a pointer with a bitfield indicating the generation. This turned out to have a serious issue: such a bitfield goes stale when the object is moved to a different generation. The object holding the memory location is in gen 1, but the annotated pointer still indicates gen 0. The gc_set function then makes the wrong decision, and premature reclamation takes place. * combi.c (perm_init_common, comb_gen_fun_common, rcomb_gen_fun_common, rcomb_list_gen_fun): Update to new interfaces for managing mutation. * debug.c (debug): Update to new interfaces for managing mutation. Avoid loc variable name. * eval.c (env_fbind, env_fbind): Update to new interfaces for managing mutation. (lookup_var_l, dwim_loc): Return loc type and update to new interfaces. (apply_frob_args, op_modplace, op_dohash, transform_op, mapcarv, mappendv, repeat_infinite_func, repeat_times_func): Update to new interfaces for managing mutation. * eval.h (lookup_var_l): Declaration updated. * filter.c (trie_add, trie_compress, trie_compress_intrinsic, * build_filter, built_filter_from_list, filter_init): Update to new * interfaces. * gc.c (gc_set): Rewritten to use loc type which provides the exact generation. We do not need the in_malloc_range hack any more, since we have the backpointer to the object. (gc_push): Take loc rather than raw pointer. * gc.h (gc_set, gc_push): Declarations updated. * hash.c (struct hash): The acons* functions use loc instead of val * now. (hash_equal_op, copy_hash, gethash_c, inhash, gethash_n, pushhash, --- stream.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'stream.c') diff --git a/stream.c b/stream.c index 64ac01d3..7122b6ff 100644 --- a/stream.c +++ b/stream.c @@ -744,7 +744,7 @@ static val string_in_get_line(val stream) if (lt(pos, length_str(string))) { val nlpos = find_char(string, pos, chr('\n')); val result = sub_str(string, pos, nlpos); - set(*cdr_l(pair), nlpos ? plus(nlpos, one) : length_str(string)); + set(cdr_l(pair), nlpos ? plus(nlpos, one) : length_str(string)); return result; } @@ -758,7 +758,7 @@ static val string_in_get_char(val stream) val pos = cdr(pair); if (lt(pos, length_str(string))) { - set(*cdr_l(pair), plus(pos, one)); + set(cdr_l(pair), plus(pos, one)); return chr_str(string, pos); } @@ -782,7 +782,7 @@ static val string_in_unget_char(val stream, val ch) lit("unget-char: ~s doesn't match the character that was read"), nao); - set(*cdr_l(pair), plus(pos, one)); + set(cdr_l(pair), plus(pos, one)); return ch; } @@ -1033,8 +1033,8 @@ static val strlist_out_put_string(val stream, val str) strstream = make_string_output_stream(); } - set(*car_l(cell), lines); - set(*cdr_l(cell), strstream); + set(car_l(cell), lines); + set(cdr_l(cell), strstream); return t; } @@ -1051,8 +1051,8 @@ static val strlist_out_put_char(val stream, val ch) put_char(ch, strstream); } - set(*car_l(cell), lines); - set(*cdr_l(cell), strstream); + set(car_l(cell), lines); + set(cdr_l(cell), strstream); return t; } -- cgit v1.2.3