Back to index

lightning-sunbird  0.9+nobinonly
ptr_chck.c
Go to the documentation of this file.
00001 /* 
00002  * Copyright (c) 1991-1994 by Xerox Corporation.  All rights reserved.
00003  *
00004  * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
00005  * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
00006  *
00007  * Permission is hereby granted to use or copy this program
00008  * for any purpose,  provided the above notices are retained on all copies.
00009  * Permission to modify the code and to distribute modified code is granted,
00010  * provided the above notices are retained, and a notice that the code was
00011  * modified is included with the above copyright notice.
00012  */
00013 /* Boehm, September 19, 1995 1:26 pm PDT */
00014 
00015 #include "gc_priv.h"
00016 #include "gc_mark.h"
00017 
00018 #ifdef __STDC__
00019 void GC_default_same_obj_print_proc(GC_PTR p, GC_PTR q)
00020 #else
00021 void GC_default_same_obj_print_proc (p, q)
00022 GC_PTR p, q;
00023 #endif
00024 {
00025     GC_err_printf2("0x%lx and 0x%lx are not in the same object\n",
00026                  (unsigned long)p, (unsigned long)q);
00027     ABORT("GC_same_obj test failed");
00028 }
00029 
00030 void (*GC_same_obj_print_proc) GC_PROTO((GC_PTR, GC_PTR))
00031               = GC_default_same_obj_print_proc;
00032 
00033 /* Check that p and q point to the same object.  Call          */
00034 /* *GC_same_obj_print_proc if they don't.               */
00035 /* Returns the first argument.  (Return value may be hard      */
00036 /* to use,due to typing issues.  But if we had a suitable      */
00037 /* preprocessor ...)                                    */
00038 /* Succeeds if neither p nor q points to the heap.             */
00039 /* We assume this is performance critical.  (It shouldn't      */
00040 /* be called by production code, but this can easily make      */
00041 /* debugging intolerably slow.)                                */
00042 #ifdef __STDC__
00043   GC_PTR GC_same_obj(register void *p, register void *q)
00044 #else
00045   GC_PTR GC_same_obj(p, q)
00046   register char *p, *q;
00047 #endif
00048 {
00049     register struct hblk *h;
00050     register hdr *hhdr;
00051     register ptr_t base, limit;
00052     register word sz;
00053     
00054     if (!GC_is_initialized) GC_init();
00055     hhdr = HDR((word)p);
00056     if (hhdr == 0) {
00057        if (divHBLKSZ((word)p) != divHBLKSZ((word)q)
00058            && HDR((word)q) != 0) {
00059            goto fail;
00060        }
00061        return(p);
00062     }
00063     /* If it's a pointer to the middle of a large object, move it     */
00064     /* to the beginning.                                       */
00065     if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
00066        h = HBLKPTR(p) - (word)hhdr;
00067        hhdr = HDR(h);
00068        while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
00069           h = FORWARDED_ADDR(h, hhdr);
00070           hhdr = HDR(h);
00071        }
00072        limit = (ptr_t)((word *)h + HDR_WORDS + hhdr -> hb_sz);
00073        if ((ptr_t)p >= limit || (ptr_t)q >= limit || (ptr_t)q < (ptr_t)h ) {
00074            goto fail;
00075        }
00076        return(p);
00077     }
00078     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
00079     if (sz > WORDS_TO_BYTES(MAXOBJSZ)) {
00080       base = (ptr_t)HBLKPTR(p);
00081       limit = base + sz;
00082       if ((ptr_t)p >= limit) {
00083         goto fail;
00084       }
00085     } else {
00086 #     ifdef ALL_INTERIOR_POINTERS
00087        register map_entry_type map_entry;
00088        register int pdispl;
00089        
00090        pdispl = HBLKDISPL(p);
00091        map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
00092        if (map_entry == OBJ_INVALID) {
00093             goto fail;
00094         } else {
00095             base = (char *)((word)p & ~(WORDS_TO_BYTES(1) - 1));
00096             base -= WORDS_TO_BYTES(map_entry);
00097        }
00098 #     else
00099        register int offset = HBLKDISPL(p) - HDR_BYTES;
00100        register word correction = offset % sz;
00101        
00102        if (HBLKPTR(p) != HBLKPTR(q)) {
00103            /* The following computation otherwise fails in this case */
00104            goto fail;
00105        }
00106        base = (ptr_t)p - correction;
00107 #     endif
00108       limit = base + sz;
00109     }
00110     /* [base, limit) delimits the object containing p, if any. */
00111     /* If p is not inside a valid object, then either q is     */
00112     /* also outside any valid object, or it is outside         */
00113     /* [base, limit).                                          */
00114     if ((ptr_t)q >= limit || (ptr_t)q < base) {
00115        goto fail;
00116     }
00117     return(p);
00118 fail:
00119     (*GC_same_obj_print_proc)((ptr_t)p, (ptr_t)q);
00120     return(p);
00121 }
00122 
00123 #ifdef __STDC__
00124 void GC_default_is_valid_displacement_print_proc (GC_PTR p)
00125 #else
00126 void GC_default_is_valid_displacement_print_proc (p)
00127 GC_PTR p;
00128 #endif
00129 {
00130     GC_err_printf1("0x%lx does not point to valid object displacement\n",
00131                  (unsigned long)p);
00132     ABORT("GC_is_valid_displacement test failed");
00133 }
00134 
00135 void (*GC_is_valid_displacement_print_proc) GC_PROTO((GC_PTR)) = 
00136        GC_default_is_valid_displacement_print_proc;
00137 
00138 /* Check that if p is a pointer to a heap page, then it points to     */
00139 /* a valid displacement within a heap object.                         */
00140 /* Uninteresting with ALL_INTERIOR_POINTERS.                          */
00141 /* Always returns its argument.                                       */
00142 /* Note that we don't lock, since nothing relevant about the header   */
00143 /* should change while we have a valid object pointer to the block.   */
00144 #ifdef __STDC__
00145   void * GC_is_valid_displacement(void *p)
00146 #else
00147   char *GC_is_valid_displacement(p)
00148   char *p;
00149 #endif
00150 {
00151     register hdr *hhdr;
00152     register word pdispl;
00153     register struct hblk *h;
00154     register map_entry_type map_entry;
00155     register word sz;
00156     
00157     if (!GC_is_initialized) GC_init();
00158     hhdr = HDR((word)p);
00159     if (hhdr == 0) return(p);
00160     h = HBLKPTR(p);
00161 #   ifdef ALL_INTERIOR_POINTERS
00162        while (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
00163           h = FORWARDED_ADDR(h, hhdr);
00164           hhdr = HDR(h);
00165        }
00166 #   endif
00167     if (IS_FORWARDING_ADDR_OR_NIL(hhdr)) {
00168        goto fail;
00169     }
00170     sz = WORDS_TO_BYTES(hhdr -> hb_sz);
00171     pdispl = HBLKDISPL(p);
00172     map_entry = MAP_ENTRY((hhdr -> hb_map), pdispl);
00173     if (map_entry == OBJ_INVALID
00174        || sz > MAXOBJSZ && (ptr_t)p >= (ptr_t)h + sz) {
00175        goto fail;
00176     }
00177     return(p);
00178 fail:
00179     (*GC_is_valid_displacement_print_proc)((ptr_t)p);
00180     return(p);
00181 }
00182 
00183 #ifdef __STDC__
00184 void GC_default_is_visible_print_proc(GC_PTR p)
00185 #else
00186 void GC_default_is_visible_print_proc(p)
00187 GC_PTR p;
00188 #endif
00189 {
00190     GC_err_printf1("0x%lx is not a GC visible pointer location\n",
00191                  (unsigned long)p);
00192     ABORT("GC_is_visible test failed");
00193 }
00194 
00195 void (*GC_is_visible_print_proc) GC_PROTO((GC_PTR p)) = 
00196        GC_default_is_visible_print_proc;
00197 
00198 /* Could p be a stack address? */
00199 GC_bool GC_on_stack(p)
00200 ptr_t p;
00201 {
00202 #   ifdef THREADS
00203        return(TRUE);
00204 #   else
00205        int dummy;
00206 #      ifdef STACK_GROWS_DOWN
00207            if ((ptr_t)p >= (ptr_t)(&dummy) && (ptr_t)p < GC_stackbottom ) {
00208               return(TRUE);
00209            }
00210 #      else
00211            if ((ptr_t)p <= (ptr_t)(&dummy) && (ptr_t)p > GC_stackbottom ) {
00212               return(TRUE);
00213            }
00214 #      endif
00215        return(FALSE);
00216 #   endif
00217 }
00218 
00219 /* Check that p is visible                                     */
00220 /* to the collector as a possibly pointer containing location.        */
00221 /* If it isn't invoke *GC_is_visible_print_proc.               */
00222 /* Returns the argument in all cases.  May erroneously succeed        */
00223 /* in hard cases.  (This is intended for debugging use with           */
00224 /* untyped allocations.  The idea is that it should be possible, though      */
00225 /* slow, to add such a call to all indirect pointer stores.)          */
00226 /* Currently useless for multithreaded worlds.                        */
00227 #ifdef __STDC__
00228   void * GC_is_visible(void *p)
00229 #else
00230   char *GC_is_visible(p)
00231   char *p;
00232 #endif
00233 {
00234     register hdr *hhdr;
00235     
00236     if ((word)p & (ALIGNMENT - 1)) goto fail;
00237     if (!GC_is_initialized) GC_init();
00238 #   ifdef THREADS
00239        hhdr = HDR((word)p);
00240         if (hhdr != 0 && GC_base(p) == 0) {
00241             goto fail;
00242         } else {
00243             /* May be inside thread stack.  We can't do much. */
00244             return(p);
00245         }
00246 #   else
00247        /* Check stack first: */
00248          if (GC_on_stack(p)) return(p);
00249        hhdr = HDR((word)p);
00250        if (hhdr == 0) {
00251            GC_bool result;
00252            
00253            if (GC_is_static_root(p)) return(p);
00254            /* Else do it again correctly: */
00255 #           if (defined(DYNAMIC_LOADING) || defined(MSWIN32) || defined(PCR)) \
00256                 && !defined(SRC_M3)
00257                DISABLE_SIGNALS();
00258                GC_register_dynamic_libraries();
00259                result = GC_is_static_root(p);
00260                ENABLE_SIGNALS();
00261                if (result) return(p);
00262 #          endif
00263            goto fail;
00264        } else {
00265            /* p points to the heap. */
00266            word descr;
00267            ptr_t base = GC_base(p);       /* Should be manually inlined? */
00268            
00269            if (base == 0) goto fail;
00270            if (HBLKPTR(base) != HBLKPTR(p)) hhdr = HDR((word)p);
00271            descr = hhdr -> hb_descr;
00272     retry:
00273            switch(descr & DS_TAGS) {
00274                case DS_LENGTH:
00275                    if ((word)((ptr_t)p - (ptr_t)base) > (word)descr) goto fail;
00276                    break;
00277                case DS_BITMAP:
00278                    if ((ptr_t)p - (ptr_t)base
00279                         >= WORDS_TO_BYTES(BITMAP_BITS)
00280                         || ((word)p & (sizeof(word) - 1))) goto fail;
00281                    if (!((1 << (WORDSZ - ((ptr_t)p - (ptr_t)base) - 1))
00282                        & descr)) goto fail;
00283                    break;
00284                case DS_PROC:
00285                    /* We could try to decipher this partially.        */
00286                    /* For now we just punt.                           */
00287                    break;
00288                case DS_PER_OBJECT:
00289                    descr = *(word *)((ptr_t)base + (descr & ~DS_TAGS));
00290                    goto retry;
00291            }
00292            return(p);
00293        }
00294 #   endif
00295 fail:
00296     (*GC_is_visible_print_proc)((ptr_t)p);
00297     return(p);
00298 }
00299 
00300 
00301 GC_PTR GC_pre_incr (p, how_much)
00302 GC_PTR *p;
00303 size_t how_much;
00304 {
00305     GC_PTR initial = *p;
00306     GC_PTR result = GC_same_obj((GC_PTR)((word)initial + how_much), initial);
00307     
00308 #   ifndef ALL_INTERIOR_POINTERS
00309        (void) GC_is_valid_displacement(result);
00310 #   endif
00311     return (*p = result);
00312 }
00313 
00314 GC_PTR GC_post_incr (p, how_much)
00315 GC_PTR *p;
00316 size_t how_much;
00317 {
00318     GC_PTR initial = *p;
00319     GC_PTR result = GC_same_obj((GC_PTR)((word)initial + how_much), initial);
00320  
00321 #   ifndef ALL_INTERIOR_POINTERS
00322        (void) GC_is_valid_displacement(result);
00323 #   endif   
00324     *p = result;
00325     return(initial);
00326 }