~ubuntu-branches/ubuntu/intrepid/ruby1.9/intrepid-updates

« back to all changes in this revision

Viewing changes to gc.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-09-04 16:01:17 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20070904160117-i15zckg2nhxe9fyw
Tags: 1.9.0+20070830-2ubuntu1
* Sync from Debian; remaining changes:
  - Add -g to CFLAGS.
* Fixes build failure on ia64.
* Fixes build failure with gcc-4.2 on lpia.
* Robustify check for target_os, fixing build failure on lpia.
* Set Ubuntu maintainer address.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
  gc.c -
4
4
 
5
 
  $Author: nobu $
6
 
  $Date: 2007-05-30 00:49:30 +0900 (水, 30  5月 2007) $
 
5
  $Author: akr $
 
6
  $Date: 2007-08-30 08:12:21 +0900 (木, 30  8月 2007) $
7
7
  created at: Tue Oct  5 09:44:46 JST 1993
8
8
 
9
 
  Copyright (C) 1993-2003 Yukihiro Matsumoto
 
9
  Copyright (C) 1993-2007 Yukihiro Matsumoto
10
10
  Copyright (C) 2000  Network Applied Communication Laboratory, Inc.
11
11
  Copyright (C) 2000  Information-technology Promotion Agency, Japan
12
12
 
13
13
**********************************************************************/
14
14
 
15
 
#include "ruby.h"
16
 
#include "rubysig.h"
17
 
#include "st.h"
18
 
#include "node.h"
19
 
#include "re.h"
20
 
#include "yarvcore.h"
 
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 "vm_core.h"
21
21
#include "gc.h"
22
22
#include <stdio.h>
23
23
#include <setjmp.h>
35
35
#include <windows.h>
36
36
#endif
37
37
 
 
38
#ifdef HAVE_VALGRIND_MEMCHECK_H
 
39
# include <valgrind/memcheck.h>
 
40
# ifndef VALGRIND_MAKE_MEM_DEFINED
 
41
#  define VALGRIND_MAKE_MEM_DEFINED(p, n) VALGRIND_MAKE_READABLE(p, n)
 
42
# endif
 
43
# ifndef VALGRIND_MAKE_MEM_UNDEFINED
 
44
#  define VALGRIND_MAKE_MEM_UNDEFINED(p, n) VALGRIND_MAKE_WRITABLE(p, n)
 
45
# endif
 
46
#else
 
47
# define VALGRIND_MAKE_MEM_DEFINED(p, n) /* empty */
 
48
# define VALGRIND_MAKE_MEM_UNDEFINED(p, n) /* empty */
 
49
#endif
 
50
 
38
51
int rb_io_fptr_finalize(struct rb_io_t*);
39
52
 
40
53
#if !defined(setjmp) && defined(HAVE__SETJMP)
84
97
static VALUE *mark_stack_ptr;
85
98
static int mark_stack_overflow;
86
99
 
 
100
int ruby_gc_debug_indent = 0;
 
101
 
87
102
#undef GC_DEBUG
88
103
 
89
104
#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CYGWIN__)
93
108
typedef struct RVALUE {
94
109
    union {
95
110
        struct {
96
 
            unsigned long flags;        /* always 0 for freed obj */
 
111
            VALUE flags;                /* always 0 for freed obj */
97
112
            struct RVALUE *next;
98
113
        } free;
99
114
        struct RBasic  basic;
146
161
VALUE *rb_gc_register_stack_start = 0;
147
162
#endif
148
163
 
149
 
int gc_stress = 0;
 
164
int ruby_gc_stress = 0;
150
165
 
151
166
 
152
167
#ifdef DJGPP
199
214
static VALUE
200
215
gc_stress_get(VALUE self)
201
216
{
202
 
    return gc_stress ? Qtrue : Qfalse;
 
217
    return ruby_gc_stress ? Qtrue : Qfalse;
203
218
}
204
219
 
205
220
/*
218
233
gc_stress_set(VALUE self, VALUE bool)
219
234
{
220
235
    rb_secure(2);
221
 
    gc_stress = RTEST(bool);
 
236
    ruby_gc_stress = RTEST(bool);
222
237
    return bool;
223
238
}
224
239
 
233
248
    if (size == 0) size = 1;
234
249
    malloc_increase += size;
235
250
 
236
 
    if (gc_stress || malloc_increase > malloc_limit) {
 
251
    if (ruby_gc_stress || malloc_increase > malloc_limit) {
237
252
        garbage_collect();
238
253
    }
239
254
    RUBY_CRITICAL(mem = malloc(size));
281
296
    if (!ptr) return ruby_xmalloc(size);
282
297
    if (size == 0) size = 1;
283
298
    malloc_increase += size;
284
 
    if (gc_stress) garbage_collect();
 
299
    if (ruby_gc_stress) garbage_collect();
285
300
    RUBY_CRITICAL(mem = realloc(ptr, size));
286
301
    if (!mem) {
287
302
        if (garbage_collect()) {
437
452
        }
438
453
        heaps[heaps_used].membase = p;
439
454
        if ((VALUE)p % sizeof(RVALUE) == 0)
440
 
          heap_slots += 1;
 
455
            heap_slots += 1;
441
456
        else
442
 
          p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE)));
 
457
            p = (RVALUE*)((VALUE)p + sizeof(RVALUE) - ((VALUE)p % sizeof(RVALUE)));
443
458
        heaps[heaps_used].slot = p;
444
459
        heaps[heaps_used].limit = heap_slots;
445
460
        break;
464
479
{
465
480
    VALUE obj;
466
481
 
467
 
    if (gc_stress || !freelist) {
 
482
    if (ruby_gc_stress || !freelist) {
468
483
        if(!garbage_collect()) {
469
484
            rb_memerror();
470
485
        }
475
490
 
476
491
    MEMZERO((void*)obj, RVALUE, 1);
477
492
#ifdef GC_DEBUG
478
 
    RANY(obj)->file = ruby_sourcefile;
479
 
    RANY(obj)->line = ruby_sourceline;
 
493
    RANY(obj)->file = rb_sourcefile();
 
494
    RANY(obj)->line = rb_sourceline();
480
495
#endif
481
496
    return obj;
482
497
}
527
542
#endif
528
543
}
529
544
 
 
545
NODE*
 
546
rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
 
547
{
 
548
    NODE *n = (NODE*)rb_newobj();
 
549
 
 
550
    n->flags |= T_NODE;
 
551
    nd_set_type(n, type);
 
552
 
 
553
    n->u1.value = a0;
 
554
    n->u2.value = a1;
 
555
    n->u3.value = a2;
 
556
 
 
557
    return n;
 
558
}
 
559
 
530
560
VALUE
531
561
rb_data_object_alloc(VALUE klass, void *datap, RUBY_DATA_FUNC dmark, RUBY_DATA_FUNC dfree)
532
562
{
540
570
    return (VALUE)data;
541
571
}
542
572
 
543
 
#define SET_STACK_END rb_gc_set_stack_end(&th->machine_stack_end)
 
573
#ifdef __ia64
 
574
#define SET_STACK_END (SET_MACHINE_STACK_END(&th->machine_stack_end), th->machine_register_stack_end = rb_ia64_bsp())
 
575
#else
 
576
#define SET_STACK_END SET_MACHINE_STACK_END(&th->machine_stack_end)
 
577
#endif
 
578
 
544
579
#define STACK_START (th->machine_stack_start)
545
580
#define STACK_END (th->machine_stack_end)
546
581
 
627
662
    return (char *)name + 1;
628
663
}
629
664
 
630
 
static void
631
 
mark_source_filename(char *f)
 
665
void
 
666
rb_mark_source_filename(char *f)
632
667
{
633
668
    if (f) {
634
669
        f[-1] = 1;
700
735
    for (i=0; i < heaps_used; i++) {
701
736
        heap_org = heaps[i].slot;
702
737
        if (heap_org <= p && p < heap_org + heaps[i].limit)
703
 
          return Qtrue;
 
738
            return Qtrue;
704
739
    }
705
740
    return Qfalse;
706
741
}
711
746
    VALUE v;
712
747
    while (n--) {
713
748
        v = *x;
 
749
        VALGRIND_MAKE_MEM_DEFINED(&v, sizeof(v));
714
750
        if (is_pointer_to_heap((void *)v)) {
715
751
            gc_mark(v, 0);
716
752
        }
836
872
        break;
837
873
 
838
874
      case T_NODE:
839
 
        mark_source_filename(obj->as.node.nd_file);
 
875
        rb_mark_source_filename(obj->as.node.nd_file);
840
876
        switch (nd_type(obj)) {
841
877
          case NODE_IF:         /* 1,2,3 */
842
878
          case NODE_FOR:
843
879
          case NODE_ITER:
844
 
          case NODE_CREF:
845
880
          case NODE_WHEN:
846
881
          case NODE_MASGN:
847
882
          case NODE_RESCUE:
997
1032
        break;
998
1033
 
999
1034
      case T_HASH:
1000
 
        mark_hash(obj->as.hash.tbl, lev);
 
1035
        mark_hash(obj->as.hash.ntbl, lev);
1001
1036
        ptr = obj->as.hash.ifnone;
1002
1037
        goto again;
1003
1038
 
1068
1103
        RVALUE *tmp = p->as.free.next;
1069
1104
        run_final((VALUE)p);
1070
1105
        if (!FL_TEST(p, FL_SINGLETON)) { /* not freeing page */
 
1106
            VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
1071
1107
            p->as.free.flags = 0;
1072
1108
            p->as.free.next = freelist;
1073
1109
            freelist = p;
1104
1140
    int freed = 0;
1105
1141
    int i;
1106
1142
    unsigned long live = 0;
1107
 
 
1108
 
    mark_source_filename(ruby_sourcefile);
 
1143
    unsigned long free_min = 0;
 
1144
 
 
1145
    for (i = 0; i < heaps_used; i++) {
 
1146
        free_min += heaps[i].limit;
 
1147
    }
 
1148
    free_min = free_min * 0.2;
 
1149
    if (free_min < FREE_MIN)
 
1150
        free_min = FREE_MIN;
 
1151
 
1109
1152
    if (source_filenames) {
1110
1153
        st_foreach(source_filenames, sweep_source_filename, 0);
1111
1154
    }
1130
1173
                    final_list = p;
1131
1174
                }
1132
1175
                else {
 
1176
                    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
1133
1177
                    p->as.free.flags = 0;
1134
1178
                    p->as.free.next = freelist;
1135
1179
                    freelist = p;
1146
1190
            }
1147
1191
            p++;
1148
1192
        }
1149
 
        if (n == heaps[i].limit && freed > FREE_MIN) {
 
1193
        if (n == heaps[i].limit && freed > free_min) {
1150
1194
            RVALUE *pp;
1151
1195
 
1152
1196
            heaps[i].limit = 0;
1164
1208
        if (malloc_limit < GC_MALLOC_LIMIT) malloc_limit = GC_MALLOC_LIMIT;
1165
1209
    }
1166
1210
    malloc_increase = 0;
1167
 
    if (freed < FREE_MIN) {
 
1211
    if (freed < free_min) {
1168
1212
        add_heap();
1169
1213
    }
1170
1214
    during_gc = 0;
1180
1224
void
1181
1225
rb_gc_force_recycle(VALUE p)
1182
1226
{
 
1227
    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
1183
1228
    RANY(p)->as.free.flags = 0;
1184
1229
    RANY(p)->as.free.next = freelist;
1185
1230
    freelist = RANY(p);
1222
1267
        rb_ary_free(obj);
1223
1268
        break;
1224
1269
      case T_HASH:
1225
 
        if (RANY(obj)->as.hash.tbl) {
1226
 
            st_free_table(RANY(obj)->as.hash.tbl);
 
1270
        if (RANY(obj)->as.hash.ntbl) {
 
1271
            st_free_table(RANY(obj)->as.hash.ntbl);
1227
1272
        }
1228
1273
        break;
1229
1274
      case T_REGEXP:
1338
1383
 
1339
1384
void rb_vm_mark(void *ptr);
1340
1385
 
 
1386
static void
 
1387
mark_current_machine_context(rb_thread_t *th)
 
1388
{
 
1389
    jmp_buf save_regs_gc_mark;
 
1390
    VALUE *stack_start, *stack_end;
 
1391
 
 
1392
    SET_STACK_END;
 
1393
#if STACK_GROW_DIRECTION < 0
 
1394
    stack_start = th->machine_stack_end;
 
1395
    stack_end = th->machine_stack_start;
 
1396
#elif STACK_GROW_DIRECTION > 0
 
1397
    stack_start = th->machine_stack_start;
 
1398
    stack_end = th->machine_stack_end + 1;
 
1399
#else
 
1400
    if (th->machine_stack_end < th->machine_stack_start) {
 
1401
        stack_start = th->machine_stack_end;
 
1402
        stack_end = th->machine_stack_start;
 
1403
    }
 
1404
    else {
 
1405
        stack_start = th->machine_stack_start;
 
1406
        stack_end = th->machine_stack_end + 1;
 
1407
    }
 
1408
#endif
 
1409
 
 
1410
    FLUSH_REGISTER_WINDOWS;
 
1411
    /* This assumes that all registers are saved into the jmp_buf (and stack) */
 
1412
    setjmp(save_regs_gc_mark);
 
1413
    mark_locations_array((VALUE*)save_regs_gc_mark,
 
1414
                         sizeof(save_regs_gc_mark) / sizeof(VALUE));
 
1415
 
 
1416
    mark_locations_array(stack_start, stack_end - stack_start);
 
1417
#ifdef __ia64
 
1418
    mark_locations_array(th->machine_register_stack_start,
 
1419
                         th->machine_register_stack_end - th->machine_register_stack_start);
 
1420
#endif
 
1421
#if defined(__human68k__) || defined(__mc68000__)
 
1422
    mark_locations_array((VALUE*)((char*)STACK_END + 2),
 
1423
                         (STACK_START - STACK_END));
 
1424
#endif
 
1425
}
 
1426
 
1341
1427
static int
1342
1428
garbage_collect(void)
1343
1429
{
1344
1430
    struct gc_list *list;
1345
 
    jmp_buf save_regs_gc_mark;
1346
1431
    rb_thread_t *th = GET_THREAD();
1347
1432
 
1348
1433
    if (GC_NOTIFY) printf("start garbage_collect()\n");
1369
1454
        mark_tbl(finalizer_table, 0);
1370
1455
    }
1371
1456
 
1372
 
    FLUSH_REGISTER_WINDOWS;
1373
 
    /* This assumes that all registers are saved into the jmp_buf (and stack) */
1374
 
    setjmp(save_regs_gc_mark);
1375
 
    mark_locations_array((VALUE*)save_regs_gc_mark, sizeof(save_regs_gc_mark) / sizeof(VALUE *));
1376
 
 
1377
 
#if STACK_GROW_DIRECTION < 0
1378
 
    rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
1379
 
#elif STACK_GROW_DIRECTION > 0
1380
 
    rb_gc_mark_locations(th->machine_stack_start, th->machine_stack_end + 1);
1381
 
#else
1382
 
    if (th->machine_stack_end < th->machine_stack_start)
1383
 
      rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
1384
 
    else
1385
 
      rb_gc_mark_locations(th->machine_stack_start, th->machine_stack_end + 1);
1386
 
#endif
1387
 
#ifdef __ia64__
1388
 
    /* mark backing store (flushed register window on the stack) */
1389
 
    /* the basic idea from guile GC code                         */
1390
 
    {
1391
 
        ucontext_t ctx;
1392
 
        VALUE *top, *bot;
1393
 
#if defined(HAVE_UNWIND_H) && defined(HAVE__UNW_CREATECONTEXTFORSELF)
1394
 
        _Unwind_Context *unwctx = _UNW_createContextForSelf();
1395
 
#endif
1396
 
 
1397
 
        getcontext(&ctx);
1398
 
        mark_locations_array((VALUE*)&ctx.uc_mcontext,
1399
 
                             ((size_t)(sizeof(VALUE)-1 + sizeof ctx.uc_mcontext)/sizeof(VALUE)));
1400
 
#if defined(HAVE_UNWIND_H) && defined(HAVE__UNW_CREATECONTEXTFORSELF)
1401
 
        _UNW_currentContext(unwctx);
1402
 
        bot = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSP);
1403
 
        top = (VALUE*)(long)_UNW_getAR(unwctx, _UNW_AR_BSPSTORE);
1404
 
        _UNW_destroyContext(unwctx);
1405
 
#else
1406
 
        bot = (VALUE*)__libc_ia64_register_backing_store_base;
1407
 
        top = (VALUE*)ctx.uc_mcontext.IA64_BSPSTORE;
1408
 
#endif
1409
 
        rb_gc_mark_locations(bot, top);
1410
 
    }
1411
 
#endif
1412
 
#if defined(__human68k__) || defined(__mc68000__)
1413
 
    rb_gc_mark_locations((VALUE*)((char*)STACK_END + 2),
1414
 
                         (VALUE*)((char*)STACK_START + 2));
1415
 
#endif
 
1457
    mark_current_machine_context(th);
 
1458
 
1416
1459
    rb_gc_mark_threads();
1417
1460
    rb_gc_mark_symbols();
1418
1461
 
1432
1475
    rb_gc_mark_parser();
1433
1476
 
1434
1477
    /* gc_mark objects whose marking are not completed*/
1435
 
    while (!MARK_STACK_EMPTY){
1436
 
        if (mark_stack_overflow){
 
1478
    while (!MARK_STACK_EMPTY) {
 
1479
        if (mark_stack_overflow) {
1437
1480
            gc_mark_all();
1438
1481
        }
1439
1482
        else {
1447
1490
}
1448
1491
 
1449
1492
void
1450
 
yarv_machine_stack_mark(rb_thread_t *th)
 
1493
rb_gc_mark_machine_stack(rb_thread_t *th)
1451
1494
{
1452
1495
#if STACK_GROW_DIRECTION < 0
1453
1496
    rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
1461
1504
        rb_gc_mark_locations(th->machine_stack_end, th->machine_stack_start);
1462
1505
    }
1463
1506
#endif
 
1507
#ifdef __ia64
 
1508
    rb_gc_mark_locations(th->machine_register_stack_start, th->machine_register_stack_end);
 
1509
#endif
1464
1510
}
1465
1511
 
1466
1512
 
1659
1705
                switch (TYPE(p)) {
1660
1706
                  case T_ICLASS:
1661
1707
                  case T_NODE:
 
1708
                  case T_VALUES:
1662
1709
                    continue;
1663
1710
                  case T_CLASS:
1664
1711
                    if (FL_TEST(p, FL_SINGLETON)) continue;
1961
2008
                else if (RANY(p)->as.data.dfree) {
1962
2009
                    (*RANY(p)->as.data.dfree)(DATA_PTR(p));
1963
2010
                }
 
2011
                VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
1964
2012
            }
1965
2013
            else if (BUILTIN_TYPE(p) == T_FILE) {
1966
2014
                if (rb_io_fptr_finalize(RANY(p)->as.file.fptr)) {
1967
2015
                    p->as.free.flags = 0;
 
2016
                    VALGRIND_MAKE_MEM_UNDEFINED((void*)p, sizeof(RVALUE));
1968
2017
                }
1969
2018
            }
1970
2019
            p++;
2010
2059
    if ((ptr % sizeof(RVALUE)) == (4 << 2)) {
2011
2060
        ID symid = ptr / sizeof(RVALUE);
2012
2061
        if (rb_id2name(symid) == 0)
2013
 
          rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
 
2062
            rb_raise(rb_eRangeError, "%p is not symbol id value", p0);
2014
2063
        return ID2SYM(symid);
2015
2064
    }
2016
2065
 
2061
2110
     *  nil     00000000000000000000000000000100
2062
2111
     *  undef   00000000000000000000000000000110
2063
2112
     *  symbol  ssssssssssssssssssssssss00001110
2064
 
     *  object  oooooooooooooooooooooooooooooo00        = 0 (mod sizeof(RVALUE)
 
2113
     *  object  oooooooooooooooooooooooooooooo00        = 0 (mod sizeof(RVALUE))
2065
2114
     *  fixnum  fffffffffffffffffffffffffffffff1
2066
2115
     *
2067
2116
     *                    object_id space
2070
2119
     *  true    00000000000000000000000000000010
2071
2120
     *  nil     00000000000000000000000000000100
2072
2121
     *  undef   00000000000000000000000000000110
2073
 
     *  symbol   000SSSSSSSSSSSSSSSSSSSSSSSSSSS0        S...S % A = 4 (S...S = 
 
2122
     *  symbol   000SSSSSSSSSSSSSSSSSSSSSSSSSSS0        S...S % A = 4 (S...S = s...s * A + 4)
2074
2123
     *  object   oooooooooooooooooooooooooooooo0        o...o % A = 0
2075
2124
     *  fixnum  fffffffffffffffffffffffffffffff1        bignum if required
2076
2125
     *
2085
2134
        return (SYM2ID(obj) * sizeof(RVALUE) + (4 << 2)) | FIXNUM_FLAG;
2086
2135
    }
2087
2136
    if (SPECIAL_CONST_P(obj)) {
2088
 
        return LONG2NUM((long)obj);
 
2137
        return LONG2NUM((SIGNED_VALUE)obj);
2089
2138
    }
2090
 
    return (VALUE)((long)obj|FIXNUM_FLAG);
 
2139
    return (VALUE)((SIGNED_VALUE)obj|FIXNUM_FLAG);
2091
2140
}
2092
2141
 
2093
2142
/*