Updated MSpec submodule to 528e64de
[rbx.git] / shotgun / lib / state.c
blobe07492b236c1ae11683ff67f6742879d00808469
1 #include <stdlib.h>
2 #include <string.h>
3 #include <sys/time.h>
5 #include "shotgun/lib/shotgun.h"
6 #include "shotgun/lib/cpu.h"
7 #include "shotgun/lib/cleanup_hash.h"
8 #include "shotgun/lib/config_hash.h"
9 #include "shotgun/lib/machine.h"
11 #ifdef TIME_LOOKUP
12 #include <mach/mach_time.h>
13 #endif
15 static size_t _gc_current_limit = 0;
16 #define GC_EXTERNAL_LIMIT 10000000
18 static void inc_mem(size_t n) {
19 _gc_current_limit += n;
21 if(_gc_current_limit > GC_EXTERNAL_LIMIT) {
22 _gc_current_limit = 0;
23 current_machine->s->om->collect_now = OMCollectYoung;
27 void *XMALLOC(size_t n) {
28 inc_mem(n);
29 return malloc(n);
32 void *XREALLOC(void *p, size_t n) {
33 inc_mem(n);
34 return realloc(p, n);
37 void *XCALLOC(size_t n, size_t s) {
38 inc_mem(n * s);
39 return calloc(n, s);
42 void XFREE(void *p) {
43 free(p);
46 rstate rubinius_state_new() {
47 rstate st;
48 st = (rstate)calloc(1, sizeof(struct rubinius_state));
49 st->om = object_memory_new();
50 st->global = (struct rubinius_globals*)calloc(1, sizeof(struct rubinius_globals));
51 st->cleanup = ht_cleanup_create(11);
52 st->config = ht_config_create(11);
53 #ifdef TIME_LOOKUP
54 st->system_start = mach_absolute_time();
55 st->lookup_time = 0;
56 #endif
57 return st;
60 void state_destroy(STATE) {
61 object_memory_destroy(state->om);
62 free(state->global);
64 ht_cleanup_destroy(state->cleanup);
65 ht_config_destroy(state->config);
67 free(state);
70 static ptr_array _gather_roots(STATE, cpu c) {
71 ptr_array roots;
72 roots = ptr_array_new(NUM_OF_GLOBALS + 100);
74 memcpy(roots->array, state->global, sizeof(struct rubinius_globals));
75 roots->length = NUM_OF_GLOBALS;
77 cpu_add_roots(state, c, roots);
78 /* truncate the free_context list since we don't care about them
79 after we've collected anyway */
80 return roots;
83 void cpu_sampler_suspend(STATE);
84 void cpu_sampler_resume(STATE);
85 void cpu_hard_cache(STATE, cpu c);
87 void state_collect(STATE, cpu c) {
88 ptr_array roots;
89 int stats = state->gc_stats;
90 struct timeval start, fin;
92 cpu_task_flush(state, c);
94 if(stats) {
95 gettimeofday(&start, NULL);
98 cpu_flush_ip(c);
99 cpu_flush_sp(c);
101 state->current_stack = c->stack_top;
102 state->current_sp = c->sp_ptr;
104 /* HACK: external_ivars needs to be moved out of being a generic
105 global and being a special case one so that it's references
106 can't keep objects alive. */
108 cpu_sampler_suspend(state);
109 object_memory_formalize_contexts(state, state->om);
110 roots = _gather_roots(state, c);
111 object_memory_collect(state, state->om, roots);
112 memcpy(state->global, roots->array, sizeof(struct rubinius_globals));
113 cpu_update_roots(state, c, roots, NUM_OF_GLOBALS);
115 object_memory_reset_contexts(state, state->om);
117 ptr_array_free(roots);
119 baker_gc_find_lost_souls(state, state->om->gc);
120 cpu_sampler_resume(state);
122 if(stats) {
123 double elapse;
124 gettimeofday(&fin, NULL);
125 elapse = (fin.tv_sec - start.tv_sec);
126 elapse += (((double)fin.tv_usec - start.tv_usec) / 1000000);
127 printf("[GC Y %f secs, %ldK total, %3dK used, %4d tenured, %d]\n",
128 elapse,
129 (long int)(state->om->gc->current->size / 1024),
130 (unsigned int)(((uintptr_t)state->om->gc->current->current - (uintptr_t)state->om->gc->current->address) / 1024),
131 state->om->last_tenured,
132 state->om->gc->num_collection
136 cpu_task_flush(state, c);
137 cpu_hard_cache(state, c);
138 cpu_cache_sp(c);
142 void state_major_collect(STATE, cpu c) {
143 ptr_array roots;
144 int stats = state->gc_stats;
145 struct timeval start, fin;
147 cpu_task_flush(state, c);
149 state_collect(state, c);
151 if(stats) {
152 gettimeofday(&start, NULL);
155 cpu_flush_ip(c);
156 cpu_flush_sp(c);
158 /* HACK: external_ivars needs to be moved out of being a generic
159 global and being a special case one so that it's references
160 can't keep objects alive. */
162 state->current_stack = c->stack_top;
163 state->current_sp = c->sp_ptr;
165 cpu_sampler_suspend(state);
166 roots = _gather_roots(state, c);
167 object_memory_major_collect(state, state->om, roots);
168 memcpy(state->global, roots->array, sizeof(struct rubinius_globals));
169 cpu_update_roots(state, c, roots, NUM_OF_GLOBALS);
171 ptr_array_free(roots);
172 cpu_sampler_suspend(state);
174 if(stats) {
175 double elapse;
176 gettimeofday(&fin, NULL);
177 elapse = (fin.tv_sec - start.tv_sec);
178 elapse += (((double)fin.tv_usec - start.tv_usec) / 1000000);
180 printf("[GC M %f secs, %d freed, %d total, %d segments, %6dK total]\n",
181 elapse,
182 state->om->ms->last_freed, state->om->ms->last_marked,
183 state->om->ms->num_chunks,
184 state->om->ms->allocated_bytes / 1024
188 cpu_task_flush(state, c);
189 cpu_hard_cache(state, c);
190 cpu_cache_sp(c);
193 void state_object_become(STATE, cpu c, OBJECT from, OBJECT to) {
194 ptr_array roots;
196 state->current_stack = c->stack_top;
197 state->current_sp = c->sp_ptr;
199 roots = _gather_roots(state, c);
201 object_memory_setup_become(state, state->om, from, to);
203 /* If from is young, then all the refs are from other young objects
204 or the remember set, so we just need to mutate in the young space. */
205 if(from->gc_zone == YoungObjectZone) {
206 object_memory_collect(state, state->om, roots);
207 } else {
208 object_memory_major_collect(state, state->om, roots);
211 object_memory_clear_become(state, state->om);
213 memcpy(state->global, roots->array, sizeof(struct rubinius_globals));
214 cpu_update_roots(state, c, roots, NUM_OF_GLOBALS);
216 ptr_array_free(roots);
220 void state_add_cleanup(STATE, OBJECT cls, state_cleanup_func func) {
221 int type = N2I(class_get_object_type(cls));
223 state->type_info[type].cleanup = func;
224 // printf("Registered cleanup for %p\n", module_get_name(cls));
225 class_set_needs_cleanup(cls, Qtrue);
228 void state_run_cleanup(STATE, OBJECT obj) {
229 state_cleanup_func func;
231 func = state->type_info[obj->obj_type].cleanup;
233 if(func) func(state, obj);
236 void state_setup_type(STATE, int type, struct type_info *info) {
237 state->type_info[type] = *info;