summaryrefslogtreecommitdiffstats
path: root/gc.h
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2018-11-06 06:55:16 -0800
committerKaz Kylheku <kaz@kylheku.com>2018-11-06 06:55:16 -0800
commite1b237fde9327eceab3ef1640ccab6c2b37fb9f1 (patch)
treebf813b0f2618340ef7002b4dde71dcdedc061742 /gc.h
parent27ced6b531c120a3e77105659bb1b7aef39b961b (diff)
downloadtxr-e1b237fde9327eceab3ef1640ccab6c2b37fb9f1.tar.gz
txr-e1b237fde9327eceab3ef1640ccab6c2b37fb9f1.tar.bz2
txr-e1b237fde9327eceab3ef1640ccab6c2b37fb9f1.zip
gc: eliminate most uses of gc_mutated.
The code is using gc_mutated in situations that resemble assignment: a value is stored into a slot in some object. These situations should be handled using the same logic as embodied in the gc_set function. This is because gc_set will consider both objects, and in many cases will not have to do anything special. E.g. if an immature object is stored into another immature object, or mature into immature, or mature into mature. Whereas gc_mutated is a "just in case" function which forces the garbage collector to traverse the indicated object, if that object is mature. In this patch we refactor gc_set to expose its underlying logic with a somewhat more flexible function called gc_assign_check. We put that behind a conditionally defined macro called setcheck, and then use that to replace invocations of the mut macro in various places. The only uses of gc_mutated that remain are in the bulk vector assignment and copy_struct: operations in which potentially many element values are migrated from one aggregate object to another, making it potentially expensive to do individual assignment checks. * gc.c (gc_assign_check): New function, formed from guts of gc_set. (gc_set): Now a trivial function, implemented via call to gc_assign_check. * gc.h (gc_assign_check): Declared. * lib.c (cons): Use setcheck instead of gc_mutated, since we are storing only two values into the existing cons: the car and the cdr. * struct.c (clear_struct): Use setcheck instead of gc_mutated, since we are just storing one value into the structure, the clear_val. The fact that we are storing it into multiple slots is irrelevant. * vm.c (vm_make_closure): Use setcheck instead of mut, using the new heap_vector as the child object with regard to the closure. Rationale: the only threat here is that when we allocate the heap vector, a GC is triggered which pushes the closure into the mature generation. Then the store of the heap vector into the closure is a wrong-way reference, with regard to generational GC. The elements in the vector are immaterial; they are older than both the closure and the vector, therefore their relationship to either object is a right-way reference. (vm_set, vm_sm_set): Replace mut by a setcheck between the vector from the display and the new value being stored in it. (vm_stab): Replace the gc_mutated check, which should have been a mut macro call, with a setcheck between the vm, and the binding being stored into the table. The gc_mutated should have been wrapped with an #if CONFIG_GEN_GC so we are fixing a build bug here: the code would have prevented TXR from being built with the generational GC disabled.
Diffstat (limited to 'gc.h')
-rw-r--r--gc.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/gc.h b/gc.h
index 4c3bc042..7025fa59 100644
--- a/gc.h
+++ b/gc.h
@@ -43,6 +43,7 @@ val gc_call_finalizers(val obj);
#if CONFIG_GEN_GC
val gc_set(loc, val);
val gc_push(val, loc);
+void gc_assign_check(val p, val c);
val gc_mutated(val);
extern int full_gc;
#endif