]> gitweb.factorcode.org Git - factor.git/blob - vm/collector.hpp
Merge branch 'master' of git://factorcode.org/git/factor
[factor.git] / vm / collector.hpp
1 namespace factor
2 {
3
4 template<typename TargetGeneration, typename Policy> struct collector {
5         factor_vm *parent;
6         data_heap *data;
7         code_heap *code;
8         gc_state *current_gc;
9         generation_statistics *stats;
10         TargetGeneration *target;
11         Policy policy;
12
13         explicit collector(factor_vm *parent_, generation_statistics *stats_, TargetGeneration *target_, Policy policy_) :
14                 parent(parent_),
15                 data(parent_->data),
16                 code(parent_->code),
17                 current_gc(parent_->current_gc),
18                 stats(stats_),
19                 target(target_),
20                 policy(policy_) {}
21
22         object *resolve_forwarding(object *untagged)
23         {
24                 parent->check_data_pointer(untagged);
25
26                 /* is there another forwarding pointer? */
27                 while(untagged->h.forwarding_pointer_p())
28                         untagged = untagged->h.forwarding_pointer();
29
30                 /* we've found the destination */
31                 untagged->h.check_header();
32                 return untagged;
33         }
34
35         void trace_handle(cell *handle)
36         {
37                 cell pointer = *handle;
38
39                 if(immediate_p(pointer)) return;
40
41                 object *untagged = parent->untag<object>(pointer);
42                 if(!policy.should_copy_p(untagged))
43                         return;
44
45                 object *forwarding = resolve_forwarding(untagged);
46
47                 if(forwarding == untagged)
48                         untagged = promote_object(untagged);
49                 else if(policy.should_copy_p(forwarding))
50                         untagged = promote_object(forwarding);
51                 else
52                         untagged = forwarding;
53
54                 *handle = RETAG(untagged,TAG(pointer));
55         }
56
57         void trace_slots(object *ptr)
58         {
59                 cell *slot = (cell *)ptr;
60                 cell *end = (cell *)((cell)ptr + parent->binary_payload_start(ptr));
61
62                 if(slot != end)
63                 {
64                         slot++;
65                         for(; slot < end; slot++) trace_handle(slot);
66                 }
67         }
68
69         object *promote_object(object *untagged)
70         {
71                 cell size = parent->untagged_object_size(untagged);
72                 object *newpointer = target->allot(size);
73                 /* XXX not exception-safe */
74                 if(!newpointer) longjmp(current_gc->gc_unwind,1);
75
76                 memcpy(newpointer,untagged,size);
77                 untagged->h.forward_to(newpointer);
78
79                 stats->object_count++;
80                 stats->bytes_copied += size;
81
82                 return newpointer;
83         }
84
85         void trace_stack_elements(segment *region, cell *top)
86         {
87                 for(cell *ptr = (cell *)region->start; ptr <= top; ptr++)
88                         trace_handle(ptr);
89         }
90
91         void trace_registered_locals()
92         {
93                 std::vector<cell>::const_iterator iter = parent->gc_locals.begin();
94                 std::vector<cell>::const_iterator end = parent->gc_locals.end();
95
96                 for(; iter < end; iter++)
97                         trace_handle((cell *)(*iter));
98         }
99
100         void trace_registered_bignums()
101         {
102                 std::vector<cell>::const_iterator iter = parent->gc_bignums.begin();
103                 std::vector<cell>::const_iterator end = parent->gc_bignums.end();
104
105                 for(; iter < end; iter++)
106                 {
107                         cell *handle = (cell *)(*iter);
108
109                         if(*handle)
110                         {
111                                 *handle |= BIGNUM_TYPE;
112                                 trace_handle(handle);
113                                 *handle &= ~BIGNUM_TYPE;
114                         }
115                 }
116         }
117
118         /* Copy roots over at the start of GC, namely various constants, stacks,
119         the user environment and extra roots registered by local_roots.hpp */
120         void trace_roots()
121         {
122                 trace_handle(&parent->true_object);
123                 trace_handle(&parent->bignum_zero);
124                 trace_handle(&parent->bignum_pos_one);
125                 trace_handle(&parent->bignum_neg_one);
126
127                 trace_registered_locals();
128                 trace_registered_bignums();
129
130                 for(int i = 0; i < USER_ENV; i++) trace_handle(&parent->userenv[i]);
131         }
132
133         void trace_contexts()
134         {
135                 context *ctx = parent->ctx;
136
137                 while(ctx)
138                 {
139                         trace_stack_elements(ctx->datastack_region,(cell *)ctx->datastack);
140                         trace_stack_elements(ctx->retainstack_region,(cell *)ctx->retainstack);
141
142                         trace_handle(&ctx->catchstack_save);
143                         trace_handle(&ctx->current_callback_save);
144
145                         ctx = ctx->next;
146                 }
147         }
148 };
149
150 }