1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15: #include "ruby/ruby.h"
16: #include "ruby/signal.h"
17: #include "ruby/st.h"
18: #include "ruby/node.h"
19: #include "ruby/re.h"
20: #include "ruby/io.h"
21: #include "vm_core.h"
22: #include "gc.h"
23: #include <stdio.h>
24: #include <setjmp.h>
25: #include <sys/types.h>
26:
27: #ifdef HAVE_SYS_TIME_H
28: #include <sys/time.h>
29: #endif
30:
31: #ifdef HAVE_SYS_RESOURCE_H
32: #include <sys/resource.h>
33: #endif
34:
35: #if defined _WIN32 || defined __CYGWIN__
36: #include <windows.h>
37: #endif
38:
39: #ifdef HAVE_VALGRIND_MEMCHECK_H
40: # include <valgrind/memcheck.h>
41: # ifndef VALGRIND_MAKE_MEM_DEFINED
42: # define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE(p, n)
43: # endif
44: # ifndef VALGRIND_MAKE_MEM_UNDEFINED
45: # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE(p, n)
46: # endif
47: #else
48: # define VALGRIND_MAKE_MEM_DEFINED(p, n)
49: # define VALGRIND_MAKE_MEM_UNDEFINED(p, n)
50: #endif
51:
52: int rb_io_fptr_finalize(struct rb_io_t*);
53:
54: #if !defined(setjmp) && defined(HAVE__SETJMP)
55: #define setjmp(env) _setjmp(env)
56: #endif
57:
58:
59: #ifdef __GNUC__
60: # ifndef atarist
61: # ifndef alloca
62: # define alloca __builtin_alloca
63: # endif
64: # endif
65: #else
66: # ifdef HAVE_ALLOCA_H
67: # include <alloca.h>
68: # else
69: # ifdef _AIX
70: #pragma alloca
71: # else
72: # ifndef alloca
73: void *alloca ();
74: # endif
75: # endif
76: # endif
77: #endif
78:
79: #ifndef GC_MALLOC_LIMIT
80: #if defined(MSDOS) || defined(__human68k__)
81: #define GC_MALLOC_LIMIT 200000
82: #else
83: #define GC_MALLOC_LIMIT 8000000
84: #endif
85: #endif
86:
87: static unsigned long malloc_increase = 0;
88: static unsigned long malloc_limit = GC_MALLOC_LIMIT;
89: static VALUE nomem_error;
90:
91: static int dont_gc;
92: static int during_gc;
93: static int need_call_final = 0;
94: static st_table *finalizer_table = 0;
95:
96: #define MARK_STACK_MAX 1024
97: static VALUE mark_stack[MARK_STACK_MAX];
98: static VALUE *mark_stack_ptr;
99: static int mark_stack_overflow;
100:
101: int ruby_gc_debug_indent = 0;
102:
103: #undef GC_DEBUG
104:
105: #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
106: #pragma pack(push, 1)
107: #endif
108:
109: typedef struct RVALUE {
110: union {
111: struct {
112: VALUE flags;
113: struct RVALUE *next;
114: } free;
115: struct RBasic basic;
116: struct RObject object;
117: struct RClass klass;
118: struct RFloat flonum;
119: struct RString string;
120: struct RArray array;
121: struct RRegexp regexp;
122: struct RHash hash;
123: struct RData data;
124: struct RStruct rstruct;
125: struct RBignum bignum;
126: struct RFile file;
127: struct RNode node;
128: struct RMatch match;
129: } as;
130: #ifdef GC_DEBUG
131: char *file;
132: int line;
133: #endif
134: } RVALUE;
135:
136: #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
137: #pragma pack(pop)
138: #endif
139:
140: static RVALUE *freelist = 0;
141: static RVALUE *deferred_final_list = 0;
142:
143: #define HEAPS_INCREMENT 10
144: static struct heaps_slot {
145: void *membase;
146: RVALUE *slot;
147: int limit;
148: } *heaps;
149: static int heaps_length = 0;
150: static int heaps_used = 0;
151:
152: #define HEAP_MIN_SLOTS 10000
153: static int heap_slots = HEAP_MIN_SLOTS;
154:
155: #define FREE_MIN 4096
156:
157: static RVALUE *himem, *lomem;
158:
159: extern st_table *rb_class_tbl;
160: VALUE *rb_gc_stack_start = 0;
161: #ifdef __ia64
162: VALUE *rb_gc_register_stack_start = 0;
163: #endif
164:
165: int ruby_gc_stress = 0;
166:
167:
168: #ifdef DJGPP
169:
170: unsigned int _stklen = 0x180000;
171: #endif
172:
173: #if defined(DJGPP) || defined(_WIN32_WCE)
174: size_t rb_gc_stack_maxsize = 65535*sizeof(VALUE);
175: #else
176: size_t rb_gc_stack_maxsize = 655300*sizeof(VALUE);
177: #endif
178:
179:
180:
181: static void run_final(VALUE obj);
182: static int garbage_collect(void);
183:
184: void
185: rb_global_variable(VALUE *var)
186: {
187: rb_gc_register_address(var);
188: }
189:
190: void
191: rb_memerror(void)
192: {
193: static int recurse = 0;
194: if (!nomem_error || (recurse > 0 && rb_safe_level() < 4)) {
195: fprintf(stderr, "[FATAL] failed to allocate memory\n");
196: exit(1);
197: }
198: recurse++;
199: rb_exc_raise(nomem_error);
200: }
201:
202:
203:
204:
205:
206:
207:
208:
209: static VALUE
210: gc_stress_get(VALUE self)
211: {
212: return ruby_gc_stress ? Qtrue : Qfalse;
213: }
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227: static VALUE
228: gc_stress_set(VALUE self, VALUE bool)
229: {
230: rb_secure(2);
231: ruby_gc_stress = RTEST(bool);
232: return bool;
233: }
234:
235: void *
236: ruby_xmalloc(size_t size)
237: {
238: void *mem;
239:
240: if (size < 0) {
241: rb_raise(rb_eNoMemError, "negative allocation size (or too big)");
242: }
243: if (size == 0) size = 1;
244: malloc_increase += size;
245:
246: if (ruby_gc_stress || malloc_increase > malloc_limit) {
247: garbage_collect();
248: }
249: RUBY_CRITICAL(mem = malloc(size));
250: if (!mem) {
251: if (garbage_collect()) {
252: RUBY_CRITICAL(mem = malloc(size));
253: }
254: if (!mem) {
255: rb_memerror();
256: }
257: }
258:
259: return mem;
260: }
261:
262: void *
263: ruby_xmalloc2(size_t n, size_t size)
264: {
265: long len = size * n;
266: if (n != 0 && size != len / n) {
267: rb_raise(rb_eArgError, "malloc: possible integer overflow");
268: }
269: return ruby_xmalloc(len);
270: }
271:
272: void *
273: ruby_xcalloc(size_t n, size_t size)
274: {
275: void *mem;
276:
277: mem = ruby_xmalloc2(n, size);
278: memset(mem, 0, n * size);
279:
280: return mem;
281: }
282:
283: void *
284: ruby_xrealloc(void *ptr, size_t size)
285: {
286: void *mem;
287:
288: if (size < 0) {
289: rb_raise(rb_eArgError, "negative re-allocation size");
290: }
291: if (!ptr) return ruby_xmalloc(size);
292: if (size == 0) size = 1;
293: malloc_increase += size;
294: if (ruby_gc_stress) garbage_collect();
295: RUBY_CRITICAL(mem = realloc(ptr, size));
296: if (!mem) {
297: if (garbage_collect()) {
298: RUBY_CRITICAL(mem = realloc(ptr, size));
299: }
300: if (!mem) {
301: rb_memerror();
302: }
303: }
304:
305: return mem;
306: }
307:
308: void *
309: ruby_xrealloc2(void *ptr, size_t n, size_t size)
310: {
311: size_t len = size * n;
312: if (n != 0 && size != len / n) {
313: rb_raise(rb_eArgError, "realloc: possible integer overflow");
314: }
315: return ruby_xrealloc(ptr, len);
316: }
317:
318: void
319: ruby_xfree(void *x)
320: {
321: if (x)
322: RUBY_CRITICAL(free(x));
323: }
324:
325:
326:
327:
328:
329:
330:
331:
332:
333:
334:
335:
336:
337:
338:
339: VALUE
340: rb_gc_enable(void)
341: {
342: int old = dont_gc;
343:
344: dont_gc = Qfalse;
345: return old;
346: }
347:
348:
349:
350:
351:
352:
353:
354:
355:
356:
357:
358:
359:
360: VALUE
361: rb_gc_disable(void)
362: {
363: int old = dont_gc;
364:
365: dont_gc = Qtrue;
366: return old;
367: }
368:
369: VALUE rb_mGC;
370:
371: static struct gc_list {
372: VALUE *varptr;
373: struct gc_list *next;
374: } *global_List = 0;
375:
376: void
377: rb_gc_register_address(VALUE *addr)
378: {
379: struct gc_list *tmp;
380:
381: tmp = ALLOC(struct gc_list);
382: tmp->next = global_List;
383: tmp->varptr = addr;
384: global_List = tmp;
385: }
386:
387: void
388: rb_register_mark_object(VALUE obj)
389: {
390: VALUE ary = GET_THREAD()->vm->mark_object_ary;
391: rb_ary_push(ary, obj);
392: }
393:
394: void
395: rb_gc_unregister_address(VALUE *addr)
396: {
397: struct gc_list *tmp = global_List;
398:
399: if (tmp->varptr == addr) {
400: global_List = tmp->next;
401: RUBY_CRITICAL(free(tmp));
402: return;
403: }
404: while (tmp->next) {
405: if (tmp->next->varptr == addr) {
406: struct gc_list *t = tmp->next;
407:
408: tmp->next = tmp->next->next;
409: RUBY_CRITICAL(free(t));
410: break;
411: }
412: tmp = tmp->next;
413: }
414: }
415:
416: static void
417: add_heap(void)
418: {
419: RVALUE *p, *pend;
420:
421: if (heaps_used == heaps_length) {
422:
423: struct heaps_slot *p;
424: int length;
425:
426: heaps_length += HEAPS_INCREMENT;
427: length = heaps_length*sizeof(struct heaps_slot);
428: RUBY_CRITICAL(
429: if (heaps_used > 0) {
430: p = (struct heaps_slot *)realloc(heaps, length);
431: if (p) heaps = p;
432: }
433: else {
434: p = heaps = (struct heaps_slot *)malloc(length);
435: });
436: if (p == 0) rb_memerror();
437: }
438:
439: for (;;) {
440: RUBY_CRITICAL(p = (RVALUE*)malloc(sizeof(RVALUE)*(heap_slots+1)));
441: if (p == 0) {
442: if (heap_slots == HEAP_MIN_SLOTS) {
443: rb_memerror();
444: }
445: heap_slots = HEAP_MIN_SLOTS;
446: continue;
447: }
448: heaps[heaps_used].membase = p;
449: if ((VALUE)p % sizeof(RVALUE) == 0)
450: heap_slots += 1;
451: else
452: p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE)));
453: heaps[heaps_used].slot = p;
454: heaps[heaps_used].limit = heap_slots;
455: break;
456: }
457: pend = p + heap_slots;
458: if (lomem == 0 || lomem > p) lomem = p;
459: if (himem < pend) himem = pend;
460: heaps_used++;
461: heap_slots *= 1.8;
462:
463: while (p < pend) {
464: p->as.free.flags = 0;
465: p->as.free.next = freelist;
466: freelist = p;
467: p++;
468: }
469: }
470: #define RANY(o) ((RVALUE*)(o))
471:
472: static VALUE
473: rb_newobj_from_heap(void)
474: {
475: VALUE obj;
476:
477: if (ruby_gc_stress || !freelist) {
478: if(!garbage_collect()) {
479: rb_memerror();
480: }
481: }
482:
483: obj = (VALUE)freelist;
484: freelist = freelist->as.free.next;
485:
486: MEMZERO((void*)obj, RVALUE, 1);
487: #ifdef GC_DEBUG
488: RANY(obj)->file = rb_sourcefile();
489: RANY(obj)->line = rb_sourceline();
490: #endif
491: return obj;
492: }
493:
494: #if USE_VALUE_CACHE
495: static VALUE
496: rb_fill_value_cache(rb_thread_t *th)
497: {
498: int i;
499: VALUE rv;
500:
501:
502: for (i=0; i<RUBY_VM_VALUE_CACHE_SIZE; i++) {
503: VALUE v = rb_newobj_from_heap();
504:
505: th->value_cache[i] = v;
506: RBASIC(v)->flags = FL_MARK;
507: }
508: th->value_cache_ptr = &th->value_cache[0];
509: rv = rb_newobj_from_heap();
510:
511: return rv;
512: }
513: #endif
514:
515: VALUE
516: rb_newobj(void)
517: {
518: #if USE_VALUE_CACHE
519: rb_thread_t *th = GET_THREAD();
520: VALUE v = *th->value_cache_ptr;
521:
522: if (v) {
523: RBASIC(v)->flags = 0;
524: th->value_cache_ptr++;
525: }
526: else {
527: v = rb_fill_value_cache(th);
528: }
529:
530: #if defined(GC_DEBUG)
531: printf("cache index: %d, v: %p, th: %p\n",
532: th->value_cache_ptr - th->value_cache, v, th);
533: #endif
534: return v;
535: #else
536: return rb_newobj_from_heap();
537: #endif
538: }
539:
540: NODE*
541: rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
542: {
543: NODE *n = (NODE*)rb_newobj();
544:
545: n->flags |= T_NODE;
546: nd_set_type(n, type);
547:
548: n->u1.value = a0;
549: n->u2.value = a1;
550: n->u3.value = a2;
551:
552: return n;
553: }
554:
555: VALUE
556: rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
557: {
558: NEWOBJ(data, struct RData);
559: if (klass) Check_Type(klass, T_CLASS);
560: OBJSETUP(data, klass, T_DATA);
561: data->data = datap;
562: data->dfree = dfree;
563: data->dmark = dmark;
564:
565: return (VALUE)data;
566: }
567:
568: #ifdef __ia64
569: #define SET_STACK_END (SET_MACHINE_STACK_END(&th->machine_stack_end), th->machine_register_stack_end = rb_ia64_bsp())
570: #else
571: #define SET_STACK_END SET_MACHINE_STACK_END(&th->machine_stack_end)
572: #endif
573:
574: #define STACK_START (th->machine_stack_start)
575: #define STACK_END (th->machine_stack_end)
576: #define STACK_LEVEL_MAX (th->machine_stack_maxsize/sizeof(VALUE))
577:
578: #if defined(sparc) || defined(__sparc__)
579: # define STACK_LENGTH (STACK_START - STACK_END + 0x80)
580: #elif STACK_GROW_DIRECTION < 0
581: # define STACK_LENGTH (STACK_START - STACK_END)
582: #elif STACK_GROW_DIRECTION > 0
583: # define STACK_LENGTH (STACK_END - STACK_START + 1)
584: #else
585: # define STACK_LENGTH ((STACK_END < STACK_START) ? STACK_START - STACK_END\
586: : STACK_END - STACK_START + 1)
587: #endif
588: #if STACK_GROW_DIRECTION > 0
589: # define STACK_UPPER(x, a, b) a
590: #elif STACK_GROW_DIRECTION < 0
591: # define STACK_UPPER(x, a, b) b
592: #else
593: static int grow_direction;
594: static int
595: stack_grow_direction(VALUE *addr)
596: {
597: rb_thread_t *th = GET_THREAD();
598: SET_STACK_END;
599:
600: if (STACK_END > addr) return grow_direction = 1;
601: return grow_direction = -1;
602: }
603: # define stack_growup_p(x) ((grow_direction ? grow_direction : stack_grow_direction(x)) > 0)
604: # define STACK_UPPER(x, a, b) (stack_growup_p(x) ? a : b)
605: #endif
606:
607: #define GC_WATER_MARK 512
608:
609: int
610: ruby_stack_length(VALUE **p)
611: {
612: rb_thread_t *th = GET_THREAD();
613: SET_STACK_END;