summaryrefslogtreecommitdiffstats
path: root/match.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2014-03-29 11:44:52 -0700
committerKaz Kylheku <kaz@kylheku.com>2014-03-29 22:55:55 -0700
commitc61ccd9769c9c83dcdf5f7693af2ca0a605b6e19 (patch)
tree6e9cfead5209cc2c591f472d8c884bf5fe9563ce /match.c
parentc20c994098c12f499fd24a89305ff37c7a2bcf76 (diff)
downloadtxr-c61ccd9769c9c83dcdf5f7693af2ca0a605b6e19.tar.gz
txr-c61ccd9769c9c83dcdf5f7693af2ca0a605b6e19.tar.bz2
txr-c61ccd9769c9c83dcdf5f7693af2ca0a605b6e19.zip
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,
Diffstat (limited to 'match.c')
-rw-r--r--match.c20
1 files changed, 10 insertions, 10 deletions
diff --git a/match.c b/match.c
index ae37a56d..25b7c4db 100644
--- a/match.c
+++ b/match.c
@@ -252,7 +252,7 @@ static val dest_set(val spec, val bindings, val pattern, val value)
sem_error(spec, lit("~s cannot be used as a variable"), pattern, nao);
if (!existing)
sem_error(spec, lit("cannot set unbound variable ~s"), pattern, nao);
- set(*cdr_l(existing), value);
+ set(cdr_l(existing), value);
} else if (consp(pattern)) {
if (first(pattern) == var_s) {
uw_throwf(query_error_s,
@@ -751,7 +751,7 @@ static val h_coll(match_line_ctx *c)
val maxtimes = txeval(elem, getplist(args, maxtimes_k), c->bindings);
val chars = txeval(elem, getplist(args, chars_k), c->bindings);
val have_vars;
- val vars = getplist_f(args, vars_k, &have_vars);
+ val vars = getplist_f(args, vars_k, mkcloc(have_vars));
cnum cmax = fixnump(gap) ? c_num(gap) : (fixnump(max) ? c_num(max) : 0);
cnum cmin = fixnump(gap) ? c_num(gap) : (fixnump(min) ? c_num(min) : 0);
cnum mincounter = cmin, maxcounter = 0;
@@ -2586,7 +2586,7 @@ static val v_gather(match_files_ctx *c)
match_files(mf_spec(*c, nested_spec)));
if (!success) {
- *cdr_l(iter) = nil;
+ deref(cdr_l(iter)) = nil;
ptail = list_collect_nconc(ptail, iter);
} else if (success == t) {
c->bindings = new_bindings;
@@ -2689,7 +2689,7 @@ static val v_collect(match_files_ctx *c)
val maxtimes = txeval(specline, getplist(args, maxtimes_k), c->bindings);
val lines = txeval(specline, getplist(args, lines_k), c->bindings);
val have_vars;
- volatile val vars = getplist_f(args, vars_k, &have_vars);
+ volatile val vars = getplist_f(args, vars_k, mkcloc(have_vars));
cnum cmax = fixnump(gap) ? c_num(gap) : (fixnump(max) ? c_num(max) : 0);
cnum cmin = fixnump(gap) ? c_num(gap) : (fixnump(min) ? c_num(min) : 0);
cnum mincounter = cmin, maxcounter = 0;
@@ -2816,7 +2816,7 @@ static val v_collect(match_files_ctx *c)
c->data = new_data;
c->data_lineno = new_line;
- *car_l(success) = nil;
+ deref(car_l(success)) = nil;
} else {
debuglf(specline, lit("collect consumed entire file"), nao);
c->data = nil;
@@ -2897,7 +2897,7 @@ static val v_flatten(match_files_ctx *c)
val existing = assoc(sym, c->bindings);
if (existing)
- set(*cdr_l(existing), flatten(cdr(existing)));
+ set(cdr_l(existing), flatten(cdr(existing)));
}
}
@@ -3056,7 +3056,7 @@ static val v_cat(match_files_ctx *c)
if (existing) {
val sep = if3(sep_form, txeval(specline, sep_form, c->bindings),
lit(" "));
- set(*cdr_l(existing), cat_str(flatten(cdr(existing)), sep));
+ set(cdr_l(existing), cat_str(flatten(cdr(existing)), sep));
} else {
sem_error(specline, lit("cat: unbound variable ~s"), sym, nao);
}
@@ -3145,9 +3145,9 @@ static val v_output(match_files_ctx *c)
if (existing) {
if (append) {
- set(*cdr_l(existing), append2(flatten(cdr(existing)), list_out));
+ set(cdr_l(existing), append2(flatten(cdr(existing)), list_out));
} else {
- set(*cdr_l(existing), list_out);
+ set(cdr_l(existing), list_out);
}
} else {
c->bindings = acons(into_var, list_out, c->bindings);
@@ -3462,7 +3462,7 @@ static val v_filter(match_files_ctx *c)
if (!existing)
sem_error(specline, lit("filter: variable ~a is unbound"), var, nao);
- set(*cdr_l(existing), filter_string_tree(filter, cdr(existing)));
+ set(cdr_l(existing), filter_string_tree(filter, cdr(existing)));
}
uw_env_end;