[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.1.1.1

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

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