(linenum→info "unix/slp.c:2238")

ruby/1.9.0/gc.c

    1: /**********************************************************************
    2: 
    3:   gc.c -
    4: 
    5:   $Author: akr $
    6:   $Date: 2007-12-21 15:16:56 +0900 (Fri, 21 Dec 2007) $
    7:   created at: Tue Oct  5 09:44:46 JST 1993
    8: 
    9:   Copyright (C) 1993-2007 Yukihiro Matsumoto
   10:   Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
   11:   Copyright (C) 2000  Information-technology Promotion Agency, Japan
   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) /* empty */
   49: # define VALGRIND_MAKE_MEM_UNDEFINED(p, n) /* empty */
   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: /* Make alloca work the best possible way.  */
   59: #ifdef __GNUC__
   60: # ifndef atarist
   61: #  ifndef alloca
   62: #   define alloca __builtin_alloca
   63: #  endif
   64: # endif /* atarist */
   65: #else
   66: # ifdef HAVE_ALLOCA_H
   67: #  include <alloca.h>
   68: # else
   69: #  ifdef _AIX
   70:  #pragma alloca
   71: #  else
   72: #   ifndef alloca /* predefined by HP cc +Olibcalls */
   73: void *alloca ();
   74: #   endif
   75: #  endif /* AIX */
   76: # endif /* HAVE_ALLOCA_H */
   77: #endif /* __GNUC__ */
   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) /* magic for reducing sizeof(RVALUE): 24 -> 20 */
  107: #endif
  108: 
  109: typedef struct RVALUE {
  110:     union {
  111:         struct {
  112:             VALUE flags;               /* always 0 for freed obj */
  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: /* set stack size (http://www.delorie.com/djgpp/v2faq/faq15_9.html) */
  170: unsigned int _stklen = 0x180000; /* 1.5 kB */
  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:  *  call-seq:
  204:  *    GC.stress                 => true or false
  205:  *
  206:  *  returns current status of GC stress mode.
  207:  */
  208: 
  209: static VALUE
  210: gc_stress_get(VALUE self)
  211: {
  212:     return ruby_gc_stress ? Qtrue : Qfalse;
  213: }
  214: 
  215: /*
  216:  *  call-seq:
  217:  *    GC.stress = bool          => bool
  218:  *
  219:  *  updates GC stress mode.
  220:  *
  221:  *  When GC.stress = true, GC is invoked for all GC opportunity:
  222:  *  all memory and object allocation.
  223:  *
  224:  *  Since it makes Ruby very slow, it is only for debugging.
  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:  *  call-seq:
  328:  *     GC.enable    => true or false
  329:  *
  330:  *  Enables garbage collection, returning <code>true</code> if garbage
  331:  *  collection was previously disabled.
  332:  *
  333:  *     GC.disable   #=> false
  334:  *     GC.enable    #=> true
  335:  *     GC.enable    #=> false
  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:  *  call-seq:
  350:  *     GC.disable    => true or false
  351:  *
  352:  *  Disables garbage collection, returning <code>true</code> if garbage
  353:  *  collection was already disabled.
  354:  *
  355:  *     GC.disable   #=> false
  356:  *     GC.disable   #=> true
  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:         /* Realloc heaps */
  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:     /* LOCK */
  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:     /* UNLOCK */
  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;