[BACK]Return to dbg_mlc.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / gc

Annotation of OpenXM_contrib2/asir2000/gc/dbg_mlc.c, Revision 1.3

1.1       noro        1: /*
                      2:  * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
                      3:  * Copyright (c) 1991-1995 by Xerox Corporation.  All rights reserved.
                      4:  * Copyright (c) 1997 by Silicon Graphics.  All rights reserved.
1.3     ! noro        5:  * Copyright (c) 1999 by Hewlett-Packard Company.  All rights reserved.
1.1       noro        6:  *
                      7:  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
                      8:  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
                      9:  *
                     10:  * Permission is hereby granted to use or copy this program
                     11:  * for any purpose,  provided the above notices are retained on all copies.
                     12:  * Permission to modify the code and to distribute modified code is granted,
                     13:  * provided the above notices are retained, and a notice that the code was
                     14:  * modified is included with the above copyright notice.
                     15:  */
1.3     ! noro       16:
        !            17: #include "dbg_mlc.h"
1.1       noro       18:
                     19: void GC_default_print_heap_obj_proc();
                     20: GC_API void GC_register_finalizer_no_order
                     21:        GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
                     22:                  GC_finalization_proc *ofn, GC_PTR *ocd));
                     23:
                     24:
                     25: /* Check whether object with base pointer p has debugging info */
                     26: /* p is assumed to point to a legitimate object in our part    */
                     27: /* of the heap.                                                        */
                     28: GC_bool GC_has_debug_info(p)
                     29: ptr_t p;
                     30: {
                     31:     register oh * ohdr = (oh *)p;
                     32:     register ptr_t body = (ptr_t)(ohdr + 1);
                     33:     register word sz = GC_size((ptr_t) ohdr);
                     34:
                     35:     if (HBLKPTR((ptr_t)ohdr) != HBLKPTR((ptr_t)body)
                     36:         || sz < sizeof (oh)) {
                     37:         return(FALSE);
                     38:     }
                     39:     if (ohdr -> oh_sz == sz) {
                     40:        /* Object may have had debug info, but has been deallocated     */
                     41:        return(FALSE);
                     42:     }
                     43:     if (ohdr -> oh_sf == (START_FLAG ^ (word)body)) return(TRUE);
                     44:     if (((word *)ohdr)[BYTES_TO_WORDS(sz)-1] == (END_FLAG ^ (word)body)) {
                     45:         return(TRUE);
                     46:     }
                     47:     return(FALSE);
                     48: }
                     49:
                     50: #ifdef KEEP_BACK_PTRS
                     51:   /* Store back pointer to source in dest, if that appears to be possible. */
                     52:   /* This is not completely safe, since we may mistakenly conclude that           */
                     53:   /* dest has a debugging wrapper.  But the error probability is very     */
                     54:   /* small, and this shouldn't be used in production code.                */
                     55:   /* We assume that dest is the real base pointer.  Source will usually    */
                     56:   /* be a pointer to the interior of an object.                                   */
                     57:   void GC_store_back_pointer(ptr_t source, ptr_t dest)
                     58:   {
                     59:     if (GC_has_debug_info(dest)) {
                     60:       ((oh *)dest) -> oh_back_ptr = (ptr_t)HIDE_POINTER(source);
                     61:     }
                     62:   }
                     63:
                     64:   void GC_marked_for_finalization(ptr_t dest) {
                     65:     GC_store_back_pointer(MARKED_FOR_FINALIZATION, dest);
                     66:   }
                     67:
                     68:   /* Store information about the object referencing dest in *base_p    */
                     69:   /* and *offset_p.                                                    */
1.3     ! noro       70:   /*   source is root ==> *base_p = address, *offset_p = 0             */
1.1       noro       71:   /*   source is heap object ==> *base_p != 0, *offset_p = offset      */
                     72:   /*   Returns 1 on success, 0 if source couldn't be determined.       */
                     73:   /* Dest can be any address within a heap object.                     */
                     74:   GC_ref_kind GC_get_back_ptr_info(void *dest, void **base_p, size_t *offset_p)
                     75:   {
                     76:     oh * hdr = (oh *)GC_base(dest);
                     77:     ptr_t bp;
                     78:     ptr_t bp_base;
                     79:     if (!GC_has_debug_info((ptr_t) hdr)) return GC_NO_SPACE;
                     80:     bp = hdr -> oh_back_ptr;
                     81:     if (MARKED_FOR_FINALIZATION == bp) return GC_FINALIZER_REFD;
1.3     ! noro       82:     if (MARKED_FROM_REGISTER == bp) return GC_REFD_FROM_REG;
1.1       noro       83:     if (0 == bp) return GC_UNREFERENCED;
                     84:     bp = REVEAL_POINTER(bp);
                     85:     bp_base = GC_base(bp);
                     86:     if (0 == bp_base) {
                     87:       *base_p = bp;
                     88:       *offset_p = 0;
                     89:       return GC_REFD_FROM_ROOT;
                     90:     } else {
                     91:       if (GC_has_debug_info(bp_base)) bp_base += sizeof(oh);
                     92:       *base_p = bp_base;
                     93:       *offset_p = bp - bp_base;
                     94:       return GC_REFD_FROM_HEAP;
                     95:     }
                     96:   }
                     97:
                     98:   /* Generate a random heap address.           */
                     99:   /* The resulting address is in the heap, but */
                    100:   /* not necessarily inside a valid object.    */
                    101:   void *GC_generate_random_heap_address(void)
                    102:   {
                    103:     int i;
                    104:     int heap_offset = random() % GC_heapsize;
                    105:     for (i = 0; i < GC_n_heap_sects; ++ i) {
                    106:        int size = GC_heap_sects[i].hs_bytes;
                    107:        if (heap_offset < size) {
                    108:            return GC_heap_sects[i].hs_start + heap_offset;
                    109:        } else {
                    110:            heap_offset -= size;
                    111:        }
                    112:     }
                    113:     ABORT("GC_generate_random_heap_address: size inconsistency");
                    114:     /*NOTREACHED*/
                    115:     return 0;
                    116:   }
                    117:
                    118:   /* Generate a random address inside a valid marked heap object. */
                    119:   void *GC_generate_random_valid_address(void)
                    120:   {
                    121:     ptr_t result;
                    122:     ptr_t base;
                    123:     for (;;) {
                    124:        result = GC_generate_random_heap_address();
                    125:        base = GC_base(result);
                    126:        if (0 == base) continue;
                    127:        if (!GC_is_marked(base)) continue;
                    128:        return result;
                    129:     }
                    130:   }
                    131:
1.3     ! noro      132:   /* Print back trace for p */
        !           133:   void GC_print_backtrace(void *p)
1.1       noro      134:   {
1.3     ! noro      135:     void *current = p;
1.1       noro      136:     int i;
1.3     ! noro      137:     GC_ref_kind source;
1.1       noro      138:     size_t offset;
1.3     ! noro      139:     void *base;
        !           140:
1.1       noro      141:     GC_print_heap_obj(GC_base(current));
                    142:     GC_err_printf0("\n");
                    143:     for (i = 0; ; ++i) {
                    144:       source = GC_get_back_ptr_info(current, &base, &offset);
                    145:       if (GC_UNREFERENCED == source) {
                    146:        GC_err_printf0("Reference could not be found\n");
                    147:        goto out;
                    148:       }
                    149:       if (GC_NO_SPACE == source) {
                    150:        GC_err_printf0("No debug info in object: Can't find reference\n");
                    151:        goto out;
                    152:       }
                    153:       GC_err_printf1("Reachable via %d levels of pointers from ",
                    154:                 (unsigned long)i);
                    155:       switch(source) {
                    156:        case GC_REFD_FROM_ROOT:
                    157:          GC_err_printf1("root at 0x%lx\n", (unsigned long)base);
                    158:          goto out;
1.3     ! noro      159:        case GC_REFD_FROM_REG:
        !           160:          GC_err_printf0("root in register\n");
        !           161:          goto out;
1.1       noro      162:        case GC_FINALIZER_REFD:
                    163:          GC_err_printf0("list of finalizable objects\n");
                    164:          goto out;
                    165:        case GC_REFD_FROM_HEAP:
                    166:          GC_err_printf1("offset %ld in object:\n", (unsigned long)offset);
                    167:          /* Take GC_base(base) to get real base, i.e. header. */
                    168:          GC_print_heap_obj(GC_base(base));
                    169:          GC_err_printf0("\n");
                    170:          break;
                    171:       }
                    172:       current = base;
                    173:     }
                    174:     out:;
                    175:   }
1.3     ! noro      176:
        !           177:   /* Force a garbage collection and generate a backtrace from a        */
        !           178:   /* random heap address.                                      */
        !           179:   void GC_generate_random_backtrace(void)
        !           180:   {
        !           181:     void * current;
        !           182:     GC_gcollect();
        !           183:     current = GC_generate_random_valid_address();
        !           184:     GC_printf1("Chose address 0x%lx in object\n", (unsigned long)current);
        !           185:     GC_print_backtrace(current);
        !           186:   }
1.1       noro      187:
                    188: #endif /* KEEP_BACK_PTRS */
                    189:
                    190: /* Store debugging info into p.  Return displaced pointer. */
                    191: /* Assumes we don't hold allocation lock.                 */
                    192: ptr_t GC_store_debug_info(p, sz, string, integer)
                    193: register ptr_t p;      /* base pointer */
                    194: word sz;       /* bytes */
                    195: char * string;
                    196: word integer;
                    197: {
                    198:     register word * result = (word *)((oh *)p + 1);
                    199:     DCL_LOCK_STATE;
                    200:
                    201:     /* There is some argument that we should dissble signals here.     */
                    202:     /* But that's expensive.  And this way things should only appear   */
                    203:     /* inconsistent while we're in the handler.                                */
                    204:     LOCK();
                    205: #   ifdef KEEP_BACK_PTRS
                    206:       ((oh *)p) -> oh_back_ptr = 0;
                    207: #   endif
                    208:     ((oh *)p) -> oh_string = string;
                    209:     ((oh *)p) -> oh_int = integer;
                    210:     ((oh *)p) -> oh_sz = sz;
                    211:     ((oh *)p) -> oh_sf = START_FLAG ^ (word)result;
                    212:     ((word *)p)[BYTES_TO_WORDS(GC_size(p))-1] =
                    213:          result[ROUNDED_UP_WORDS(sz)] = END_FLAG ^ (word)result;
                    214:     UNLOCK();
                    215:     return((ptr_t)result);
                    216: }
                    217:
                    218: /* Check the object with debugging info at ohdr                */
                    219: /* return NIL if it's OK.  Else return clobbered       */
                    220: /* address.                                            */
                    221: ptr_t GC_check_annotated_obj(ohdr)
                    222: register oh * ohdr;
                    223: {
                    224:     register ptr_t body = (ptr_t)(ohdr + 1);
                    225:     register word gc_sz = GC_size((ptr_t)ohdr);
                    226:     if (ohdr -> oh_sz + DEBUG_BYTES > gc_sz) {
                    227:         return((ptr_t)(&(ohdr -> oh_sz)));
                    228:     }
                    229:     if (ohdr -> oh_sf != (START_FLAG ^ (word)body)) {
                    230:         return((ptr_t)(&(ohdr -> oh_sf)));
                    231:     }
                    232:     if (((word *)ohdr)[BYTES_TO_WORDS(gc_sz)-1] != (END_FLAG ^ (word)body)) {
                    233:         return((ptr_t)((word *)ohdr + BYTES_TO_WORDS(gc_sz)-1));
                    234:     }
                    235:     if (((word *)body)[ROUNDED_UP_WORDS(ohdr -> oh_sz)]
                    236:         != (END_FLAG ^ (word)body)) {
                    237:         return((ptr_t)((word *)body + ROUNDED_UP_WORDS(ohdr -> oh_sz)));
                    238:     }
                    239:     return(0);
                    240: }
                    241:
                    242: void GC_print_obj(p)
                    243: ptr_t p;
                    244: {
                    245:     register oh * ohdr = (oh *)GC_base(p);
                    246:
                    247:     GC_err_printf1("0x%lx (", ((unsigned long)ohdr + sizeof(oh)));
                    248:     GC_err_puts(ohdr -> oh_string);
                    249:     GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
                    250:                                      (unsigned long)(ohdr -> oh_sz));
                    251:     PRINT_CALL_CHAIN(ohdr);
                    252: }
                    253:
                    254: void GC_debug_print_heap_obj_proc(p)
                    255: ptr_t p;
                    256: {
                    257:     if (GC_has_debug_info(p)) {
                    258:        GC_print_obj(p);
                    259:     } else {
                    260:        GC_default_print_heap_obj_proc(p);
                    261:     }
                    262: }
                    263:
                    264: void GC_print_smashed_obj(p, clobbered_addr)
                    265: ptr_t p, clobbered_addr;
                    266: {
                    267:     register oh * ohdr = (oh *)GC_base(p);
                    268:
                    269:     GC_err_printf2("0x%lx in object at 0x%lx(", (unsigned long)clobbered_addr,
                    270:                                                (unsigned long)p);
                    271:     if (clobbered_addr <= (ptr_t)(&(ohdr -> oh_sz))
                    272:         || ohdr -> oh_string == 0) {
                    273:         GC_err_printf1("<smashed>, appr. sz = %ld)\n",
                    274:                       (GC_size((ptr_t)ohdr) - DEBUG_BYTES));
                    275:     } else {
                    276:         if (ohdr -> oh_string[0] == '\0') {
                    277:             GC_err_puts("EMPTY(smashed?)");
                    278:         } else {
                    279:             GC_err_puts(ohdr -> oh_string);
                    280:         }
                    281:         GC_err_printf2(":%ld, sz=%ld)\n", (unsigned long)(ohdr -> oh_int),
                    282:                                          (unsigned long)(ohdr -> oh_sz));
                    283:         PRINT_CALL_CHAIN(ohdr);
                    284:     }
                    285: }
                    286:
                    287: void GC_check_heap_proc();
                    288:
                    289: void GC_start_debugging()
                    290: {
                    291:     GC_check_heap = GC_check_heap_proc;
                    292:     GC_print_heap_obj = GC_debug_print_heap_obj_proc;
                    293:     GC_debugging_started = TRUE;
                    294:     GC_register_displacement((word)sizeof(oh));
                    295: }
                    296:
                    297: # if defined(__STDC__) || defined(__cplusplus)
                    298:     void GC_debug_register_displacement(GC_word offset)
                    299: # else
                    300:     void GC_debug_register_displacement(offset)
                    301:     GC_word offset;
                    302: # endif
                    303: {
                    304:     GC_register_displacement(offset);
                    305:     GC_register_displacement((word)sizeof(oh) + offset);
                    306: }
                    307:
                    308: # ifdef __STDC__
1.3     ! noro      309:     GC_PTR GC_debug_malloc(size_t lb, GC_EXTRA_PARAMS)
1.1       noro      310: # else
                    311:     GC_PTR GC_debug_malloc(lb, s, i)
                    312:     size_t lb;
                    313:     char * s;
                    314:     int i;
                    315: #   ifdef GC_ADD_CALLER
                    316:        --> GC_ADD_CALLER not implemented for K&R C
                    317: #   endif
                    318: # endif
                    319: {
                    320:     GC_PTR result = GC_malloc(lb + DEBUG_BYTES);
                    321:
                    322:     if (result == 0) {
                    323:         GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
                    324:                       (unsigned long) lb);
                    325:         GC_err_puts(s);
                    326:         GC_err_printf1(":%ld)\n", (unsigned long)i);
                    327:         return(0);
                    328:     }
                    329:     if (!GC_debugging_started) {
                    330:        GC_start_debugging();
                    331:     }
                    332:     ADD_CALL_CHAIN(result, ra);
                    333:     return (GC_store_debug_info(result, (word)lb, s, (word)i));
                    334: }
                    335:
                    336: #ifdef STUBBORN_ALLOC
                    337: # ifdef __STDC__
1.3     ! noro      338:     GC_PTR GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
1.1       noro      339: # else
                    340:     GC_PTR GC_debug_malloc_stubborn(lb, s, i)
                    341:     size_t lb;
                    342:     char * s;
                    343:     int i;
                    344: # endif
                    345: {
                    346:     GC_PTR result = GC_malloc_stubborn(lb + DEBUG_BYTES);
                    347:
                    348:     if (result == 0) {
                    349:         GC_err_printf1("GC_debug_malloc(%ld) returning NIL (",
                    350:                       (unsigned long) lb);
                    351:         GC_err_puts(s);
                    352:         GC_err_printf1(":%ld)\n", (unsigned long)i);
                    353:         return(0);
                    354:     }
                    355:     if (!GC_debugging_started) {
                    356:        GC_start_debugging();
                    357:     }
                    358:     ADD_CALL_CHAIN(result, ra);
                    359:     return (GC_store_debug_info(result, (word)lb, s, (word)i));
                    360: }
                    361:
                    362: void GC_debug_change_stubborn(p)
                    363: GC_PTR p;
                    364: {
                    365:     register GC_PTR q = GC_base(p);
                    366:     register hdr * hhdr;
                    367:
                    368:     if (q == 0) {
                    369:         GC_err_printf1("Bad argument: 0x%lx to GC_debug_change_stubborn\n",
                    370:                       (unsigned long) p);
                    371:         ABORT("GC_debug_change_stubborn: bad arg");
                    372:     }
                    373:     hhdr = HDR(q);
                    374:     if (hhdr -> hb_obj_kind != STUBBORN) {
                    375:         GC_err_printf1("GC_debug_change_stubborn arg not stubborn: 0x%lx\n",
                    376:                       (unsigned long) p);
                    377:         ABORT("GC_debug_change_stubborn: arg not stubborn");
                    378:     }
                    379:     GC_change_stubborn(q);
                    380: }
                    381:
                    382: void GC_debug_end_stubborn_change(p)
                    383: GC_PTR p;
                    384: {
                    385:     register GC_PTR q = GC_base(p);
                    386:     register hdr * hhdr;
                    387:
                    388:     if (q == 0) {
                    389:         GC_err_printf1("Bad argument: 0x%lx to GC_debug_end_stubborn_change\n",
                    390:                       (unsigned long) p);
                    391:         ABORT("GC_debug_end_stubborn_change: bad arg");
                    392:     }
                    393:     hhdr = HDR(q);
                    394:     if (hhdr -> hb_obj_kind != STUBBORN) {
                    395:         GC_err_printf1("debug_end_stubborn_change arg not stubborn: 0x%lx\n",
                    396:                       (unsigned long) p);
                    397:         ABORT("GC_debug_end_stubborn_change: arg not stubborn");
                    398:     }
                    399:     GC_end_stubborn_change(q);
                    400: }
                    401:
1.3     ! noro      402: #else /* !STUBBORN_ALLOC */
        !           403:
        !           404: # ifdef __STDC__
        !           405:     GC_PTR GC_debug_malloc_stubborn(size_t lb, GC_EXTRA_PARAMS)
        !           406: # else
        !           407:     GC_PTR GC_debug_malloc_stubborn(lb, s, i)
        !           408:     size_t lb;
        !           409:     char * s;
        !           410:     int i;
        !           411: # endif
        !           412: {
        !           413:     return GC_debug_malloc(lb, OPT_RA s, i);
        !           414: }
        !           415:
        !           416: void GC_debug_change_stubborn(p)
        !           417: GC_PTR p;
        !           418: {
        !           419: }
        !           420:
        !           421: void GC_debug_end_stubborn_change(p)
        !           422: GC_PTR p;
        !           423: {
        !           424: }
        !           425:
        !           426: #endif /* !STUBBORN_ALLOC */
1.1       noro      427:
                    428: # ifdef __STDC__
1.3     ! noro      429:     GC_PTR GC_debug_malloc_atomic(size_t lb, GC_EXTRA_PARAMS)
1.1       noro      430: # else
                    431:     GC_PTR GC_debug_malloc_atomic(lb, s, i)
                    432:     size_t lb;
                    433:     char * s;
                    434:     int i;
                    435: # endif
                    436: {
                    437:     GC_PTR result = GC_malloc_atomic(lb + DEBUG_BYTES);
                    438:
                    439:     if (result == 0) {
                    440:         GC_err_printf1("GC_debug_malloc_atomic(%ld) returning NIL (",
                    441:                      (unsigned long) lb);
                    442:         GC_err_puts(s);
                    443:         GC_err_printf1(":%ld)\n", (unsigned long)i);
                    444:         return(0);
                    445:     }
                    446:     if (!GC_debugging_started) {
                    447:         GC_start_debugging();
                    448:     }
                    449:     ADD_CALL_CHAIN(result, ra);
                    450:     return (GC_store_debug_info(result, (word)lb, s, (word)i));
                    451: }
                    452:
                    453: # ifdef __STDC__
1.3     ! noro      454:     GC_PTR GC_debug_malloc_uncollectable(size_t lb, GC_EXTRA_PARAMS)
1.1       noro      455: # else
                    456:     GC_PTR GC_debug_malloc_uncollectable(lb, s, i)
                    457:     size_t lb;
                    458:     char * s;
                    459:     int i;
                    460: # endif
                    461: {
                    462:     GC_PTR result = GC_malloc_uncollectable(lb + DEBUG_BYTES);
                    463:
                    464:     if (result == 0) {
                    465:         GC_err_printf1("GC_debug_malloc_uncollectable(%ld) returning NIL (",
                    466:                      (unsigned long) lb);
                    467:         GC_err_puts(s);
                    468:         GC_err_printf1(":%ld)\n", (unsigned long)i);
                    469:         return(0);
                    470:     }
                    471:     if (!GC_debugging_started) {
                    472:         GC_start_debugging();
                    473:     }
                    474:     ADD_CALL_CHAIN(result, ra);
                    475:     return (GC_store_debug_info(result, (word)lb, s, (word)i));
                    476: }
                    477:
                    478: #ifdef ATOMIC_UNCOLLECTABLE
                    479: # ifdef __STDC__
1.3     ! noro      480:     GC_PTR GC_debug_malloc_atomic_uncollectable(size_t lb, GC_EXTRA_PARAMS)
1.1       noro      481: # else
                    482:     GC_PTR GC_debug_malloc_atomic_uncollectable(lb, s, i)
                    483:     size_t lb;
                    484:     char * s;
                    485:     int i;
                    486: # endif
                    487: {
                    488:     GC_PTR result = GC_malloc_atomic_uncollectable(lb + DEBUG_BYTES);
                    489:
                    490:     if (result == 0) {
                    491:         GC_err_printf1(
                    492:                "GC_debug_malloc_atomic_uncollectable(%ld) returning NIL (",
                    493:                 (unsigned long) lb);
                    494:         GC_err_puts(s);
                    495:         GC_err_printf1(":%ld)\n", (unsigned long)i);
                    496:         return(0);
                    497:     }
                    498:     if (!GC_debugging_started) {
                    499:         GC_start_debugging();
                    500:     }
                    501:     ADD_CALL_CHAIN(result, ra);
                    502:     return (GC_store_debug_info(result, (word)lb, s, (word)i));
                    503: }
                    504: #endif /* ATOMIC_UNCOLLECTABLE */
                    505:
                    506: # ifdef __STDC__
                    507:     void GC_debug_free(GC_PTR p)
                    508: # else
                    509:     void GC_debug_free(p)
                    510:     GC_PTR p;
                    511: # endif
                    512: {
1.2       noro      513:     register GC_PTR base;
1.1       noro      514:     register ptr_t clobbered;
                    515:
1.2       noro      516:     if (0 == p) return;
                    517:     base = GC_base(p);
1.1       noro      518:     if (base == 0) {
                    519:         GC_err_printf1("Attempt to free invalid pointer %lx\n",
                    520:                       (unsigned long)p);
1.2       noro      521:         ABORT("free(invalid pointer)");
1.1       noro      522:     }
                    523:     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
                    524:         GC_err_printf1(
                    525:                  "GC_debug_free called on pointer %lx wo debugging info\n",
                    526:                  (unsigned long)p);
                    527:     } else {
                    528:       clobbered = GC_check_annotated_obj((oh *)base);
                    529:       if (clobbered != 0) {
                    530:         if (((oh *)base) -> oh_sz == GC_size(base)) {
                    531:             GC_err_printf0(
                    532:                   "GC_debug_free: found previously deallocated (?) object at ");
                    533:         } else {
                    534:             GC_err_printf0("GC_debug_free: found smashed location at ");
                    535:         }
                    536:         GC_print_smashed_obj(p, clobbered);
                    537:       }
                    538:       /* Invalidate size */
                    539:       ((oh *)base) -> oh_sz = GC_size(base);
                    540:     }
1.2       noro      541:     if (GC_find_leak) {
1.1       noro      542:         GC_free(base);
1.2       noro      543:     } else {
                    544:        register hdr * hhdr = HDR(p);
                    545:        GC_bool uncollectable = FALSE;
1.1       noro      546:
1.2       noro      547:         if (hhdr ->  hb_obj_kind == UNCOLLECTABLE) {
                    548:            uncollectable = TRUE;
                    549:        }
                    550: #      ifdef ATOMIC_UNCOLLECTABLE
                    551:            if (hhdr ->  hb_obj_kind == AUNCOLLECTABLE) {
                    552:                    uncollectable = TRUE;
1.1       noro      553:            }
1.2       noro      554: #      endif
                    555:        if (uncollectable) GC_free(base);
                    556:     } /* !GC_find_leak */
1.1       noro      557: }
                    558:
                    559: # ifdef __STDC__
1.3     ! noro      560:     GC_PTR GC_debug_realloc(GC_PTR p, size_t lb, GC_EXTRA_PARAMS)
1.1       noro      561: # else
                    562:     GC_PTR GC_debug_realloc(p, lb, s, i)
                    563:     GC_PTR p;
                    564:     size_t lb;
                    565:     char *s;
                    566:     int i;
                    567: # endif
                    568: {
                    569:     register GC_PTR base = GC_base(p);
                    570:     register ptr_t clobbered;
                    571:     register GC_PTR result;
                    572:     register size_t copy_sz = lb;
                    573:     register size_t old_sz;
                    574:     register hdr * hhdr;
                    575:
                    576:     if (p == 0) return(GC_debug_malloc(lb, OPT_RA s, i));
                    577:     if (base == 0) {
                    578:         GC_err_printf1(
                    579:               "Attempt to reallocate invalid pointer %lx\n", (unsigned long)p);
                    580:         ABORT("realloc(invalid pointer)");
                    581:     }
                    582:     if ((ptr_t)p - (ptr_t)base != sizeof(oh)) {
                    583:         GC_err_printf1(
                    584:                "GC_debug_realloc called on pointer %lx wo debugging info\n",
                    585:                (unsigned long)p);
                    586:         return(GC_realloc(p, lb));
                    587:     }
                    588:     hhdr = HDR(base);
                    589:     switch (hhdr -> hb_obj_kind) {
                    590: #    ifdef STUBBORN_ALLOC
                    591:       case STUBBORN:
                    592:         result = GC_debug_malloc_stubborn(lb, OPT_RA s, i);
                    593:         break;
                    594: #    endif
                    595:       case NORMAL:
                    596:         result = GC_debug_malloc(lb, OPT_RA s, i);
                    597:         break;
                    598:       case PTRFREE:
                    599:         result = GC_debug_malloc_atomic(lb, OPT_RA s, i);
                    600:         break;
                    601:       case UNCOLLECTABLE:
                    602:        result = GC_debug_malloc_uncollectable(lb, OPT_RA s, i);
                    603:        break;
                    604: #    ifdef ATOMIC_UNCOLLECTABLE
                    605:       case AUNCOLLECTABLE:
                    606:        result = GC_debug_malloc_atomic_uncollectable(lb, OPT_RA s, i);
                    607:        break;
                    608: #    endif
                    609:       default:
                    610:         GC_err_printf0("GC_debug_realloc: encountered bad kind\n");
                    611:         ABORT("bad kind");
                    612:     }
                    613:     clobbered = GC_check_annotated_obj((oh *)base);
                    614:     if (clobbered != 0) {
                    615:         GC_err_printf0("GC_debug_realloc: found smashed location at ");
                    616:         GC_print_smashed_obj(p, clobbered);
                    617:     }
                    618:     old_sz = ((oh *)base) -> oh_sz;
                    619:     if (old_sz < copy_sz) copy_sz = old_sz;
                    620:     if (result == 0) return(0);
                    621:     BCOPY(p, result,  copy_sz);
                    622:     GC_debug_free(p);
                    623:     return(result);
                    624: }
                    625:
                    626: /* Check all marked objects in the given block for validity */
                    627: /*ARGSUSED*/
                    628: void GC_check_heap_block(hbp, dummy)
                    629: register struct hblk *hbp;     /* ptr to current heap block            */
                    630: word dummy;
                    631: {
                    632:     register struct hblkhdr * hhdr = HDR(hbp);
                    633:     register word sz = hhdr -> hb_sz;
                    634:     register int word_no;
                    635:     register word *p, *plim;
                    636:
                    637:     p = (word *)(hbp->hb_body);
                    638:     word_no = HDR_WORDS;
                    639:     if (sz > MAXOBJSZ) {
                    640:        plim = p;
                    641:     } else {
                    642:        plim = (word *)((((word)hbp) + HBLKSIZE) - WORDS_TO_BYTES(sz));
                    643:     }
                    644:     /* go through all words in block */
                    645:        while( p <= plim ) {
                    646:            if( mark_bit_from_hdr(hhdr, word_no)
                    647:                && GC_has_debug_info((ptr_t)p)) {
                    648:                ptr_t clobbered = GC_check_annotated_obj((oh *)p);
                    649:
                    650:                if (clobbered != 0) {
                    651:                    GC_err_printf0(
                    652:                        "GC_check_heap_block: found smashed location at ");
                    653:                    GC_print_smashed_obj((ptr_t)p, clobbered);
                    654:                }
                    655:            }
                    656:            word_no += sz;
                    657:            p += sz;
                    658:        }
                    659: }
                    660:
                    661:
                    662: /* This assumes that all accessible objects are marked, and that       */
                    663: /* I hold the allocation lock. Normally called by collector.           */
                    664: void GC_check_heap_proc()
                    665: {
                    666: #   ifndef SMALL_CONFIG
                    667:        if (sizeof(oh) & (2 * sizeof(word) - 1) != 0) {
                    668:            ABORT("Alignment problem: object header has inappropriate size\n");
                    669:        }
                    670: #   endif
                    671:     GC_apply_to_all_blocks(GC_check_heap_block, (word)0);
                    672: }
                    673:
                    674: struct closure {
                    675:     GC_finalization_proc cl_fn;
                    676:     GC_PTR cl_data;
                    677: };
                    678:
                    679: # ifdef __STDC__
                    680:     void * GC_make_closure(GC_finalization_proc fn, void * data)
                    681: # else
                    682:     GC_PTR GC_make_closure(fn, data)
                    683:     GC_finalization_proc fn;
                    684:     GC_PTR data;
                    685: # endif
                    686: {
                    687:     struct closure * result =
                    688:                (struct closure *) GC_malloc(sizeof (struct closure));
                    689:
                    690:     result -> cl_fn = fn;
                    691:     result -> cl_data = data;
                    692:     return((GC_PTR)result);
                    693: }
                    694:
                    695: # ifdef __STDC__
                    696:     void GC_debug_invoke_finalizer(void * obj, void * data)
                    697: # else
                    698:     void GC_debug_invoke_finalizer(obj, data)
                    699:     char * obj;
                    700:     char * data;
                    701: # endif
                    702: {
                    703:     register struct closure * cl = (struct closure *) data;
                    704:
                    705:     (*(cl -> cl_fn))((GC_PTR)((char *)obj + sizeof(oh)), cl -> cl_data);
                    706: }
                    707:
                    708:
                    709: # ifdef __STDC__
                    710:     void GC_debug_register_finalizer(GC_PTR obj, GC_finalization_proc fn,
                    711:                                     GC_PTR cd, GC_finalization_proc *ofn,
                    712:                                     GC_PTR *ocd)
                    713: # else
                    714:     void GC_debug_register_finalizer(obj, fn, cd, ofn, ocd)
                    715:     GC_PTR obj;
                    716:     GC_finalization_proc fn;
                    717:     GC_PTR cd;
                    718:     GC_finalization_proc *ofn;
                    719:     GC_PTR *ocd;
                    720: # endif
                    721: {
                    722:     ptr_t base = GC_base(obj);
                    723:     if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
                    724:         GC_err_printf1(
                    725:            "GC_register_finalizer called with non-base-pointer 0x%lx\n",
                    726:            obj);
                    727:     }
                    728:     GC_register_finalizer(base, GC_debug_invoke_finalizer,
                    729:                          GC_make_closure(fn,cd), ofn, ocd);
                    730: }
                    731:
                    732: # ifdef __STDC__
                    733:     void GC_debug_register_finalizer_no_order
                    734:                                    (GC_PTR obj, GC_finalization_proc fn,
                    735:                                     GC_PTR cd, GC_finalization_proc *ofn,
                    736:                                     GC_PTR *ocd)
                    737: # else
                    738:     void GC_debug_register_finalizer_no_order
                    739:                                    (obj, fn, cd, ofn, ocd)
                    740:     GC_PTR obj;
                    741:     GC_finalization_proc fn;
                    742:     GC_PTR cd;
                    743:     GC_finalization_proc *ofn;
                    744:     GC_PTR *ocd;
                    745: # endif
                    746: {
                    747:     ptr_t base = GC_base(obj);
                    748:     if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
                    749:         GC_err_printf1(
                    750:          "GC_register_finalizer_no_order called with non-base-pointer 0x%lx\n",
                    751:          obj);
                    752:     }
                    753:     GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer,
                    754:                                      GC_make_closure(fn,cd), ofn, ocd);
                    755:  }
                    756:
                    757: # ifdef __STDC__
                    758:     void GC_debug_register_finalizer_ignore_self
                    759:                                    (GC_PTR obj, GC_finalization_proc fn,
                    760:                                     GC_PTR cd, GC_finalization_proc *ofn,
                    761:                                     GC_PTR *ocd)
                    762: # else
                    763:     void GC_debug_register_finalizer_ignore_self
                    764:                                    (obj, fn, cd, ofn, ocd)
                    765:     GC_PTR obj;
                    766:     GC_finalization_proc fn;
                    767:     GC_PTR cd;
                    768:     GC_finalization_proc *ofn;
                    769:     GC_PTR *ocd;
                    770: # endif
                    771: {
                    772:     ptr_t base = GC_base(obj);
                    773:     if (0 == base || (ptr_t)obj - base != sizeof(oh)) {
                    774:         GC_err_printf1(
                    775:            "GC_register_finalizer_ignore_self called with non-base-pointer 0x%lx\n",
                    776:            obj);
                    777:     }
                    778:     GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer,
                    779:                                      GC_make_closure(fn,cd), ofn, ocd);
                    780: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>