PageRenderTime 37ms CodeModel.GetById 13ms app.highlight 18ms RepoModel.GetById 2ms app.codeStats 0ms

/vendor/gc/checksums.c

http://github.com/feyeleanor/RubyGoLightly
C | 196 lines | 146 code | 24 blank | 26 comment | 41 complexity | b91bb036867f9dbe5cfe432cff6e902a MD5 | raw file
  1/*
  2 * Copyright (c) 1992-1994 by Xerox Corporation.  All rights reserved.
  3 *
  4 * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
  5 * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
  6 *
  7 * Permission is hereby granted to use or copy this program
  8 * for any purpose,  provided the above notices are retained on all copies.
  9 * Permission to modify the code and to distribute modified code is granted,
 10 * provided the above notices are retained, and a notice that the code was
 11 * modified is included with the above copyright notice.
 12 */
 13/* Boehm, March 29, 1995 12:51 pm PST */
 14# ifdef CHECKSUMS
 15
 16# include "private/gc_priv.h"
 17
 18/* This is debugging code intended to verify the results of dirty bit	*/
 19/* computations. Works only in a single threaded environment.		*/
 20/* We assume that stubborn objects are changed only when they are 	*/
 21/* enabled for writing.  (Certain kinds of writing are actually		*/
 22/* safe under other conditions.)					*/
 23# define NSUMS 10000
 24
 25# define OFFSET 0x10000
 26
 27typedef struct {
 28	GC_bool new_valid;
 29	word old_sum;
 30	word new_sum;
 31	struct hblk * block;	/* Block to which this refers + OFFSET  */
 32				/* to hide it from collector.		*/
 33} page_entry;
 34
 35page_entry GC_sums [NSUMS];
 36
 37word GC_checksum(h)
 38struct hblk *h;
 39{
 40    register word *p = (word *)h;
 41    register word *lim = (word *)(h+1);
 42    register word result = 0;
 43    
 44    while (p < lim) {
 45        result += *p++;
 46    }
 47    return(result | 0x80000000 /* doesn't look like pointer */);
 48}
 49
 50# ifdef STUBBORN_ALLOC
 51/* Check whether a stubborn object from the given block appears on	*/
 52/* the appropriate free list.						*/
 53GC_bool GC_on_free_list(struct hblk *h)
 54struct hblk *h;
 55{
 56    hdr * hhdr = HDR(h);
 57    int sz = BYTES_TO_WORDS(hhdr -> hb_sz);
 58    ptr_t p;
 59    
 60    if (sz > MAXOBJWORDS) return(FALSE);
 61    for (p = GC_sobjfreelist[sz]; p != 0; p = obj_link(p)) {
 62        if (HBLKPTR(p) == h) return(TRUE);
 63    }
 64    return(FALSE);
 65}
 66# endif
 67 
 68int GC_n_dirty_errors;
 69int GC_n_changed_errors;
 70int GC_n_clean;
 71int GC_n_dirty;
 72
 73void GC_update_check_page(struct hblk *h, int index)
 74{
 75    page_entry *pe = GC_sums + index;
 76    register hdr * hhdr = HDR(h);
 77    struct hblk *b;
 78    
 79    if (pe -> block != 0 && pe -> block != h + OFFSET) ABORT("goofed");
 80    pe -> old_sum = pe -> new_sum;
 81    pe -> new_sum = GC_checksum(h);
 82#   if !defined(MSWIN32) && !defined(MSWINCE)
 83        if (pe -> new_sum != 0x80000000 && !GC_page_was_ever_dirty(h)) {
 84            GC_printf("GC_page_was_ever_dirty(%p) is wrong\n", h);
 85        }
 86#   endif
 87    if (GC_page_was_dirty(h)) {
 88    	GC_n_dirty++;
 89    } else {
 90    	GC_n_clean++;
 91    }
 92    b = h;
 93    while (IS_FORWARDING_ADDR_OR_NIL(hhdr) && hhdr != 0) {
 94	b -= (word)hhdr;
 95	hhdr = HDR(b);
 96    }
 97    if (pe -> new_valid
 98	&& hhdr != 0 && hhdr -> hb_descr != 0 /* may contain pointers */
 99	&& pe -> old_sum != pe -> new_sum) {
100    	if (!GC_page_was_dirty(h) || !GC_page_was_ever_dirty(h)) {
101    	    /* Set breakpoint here */GC_n_dirty_errors++;
102    	}
103#	ifdef STUBBORN_ALLOC
104    	  if (!HBLK_IS_FREE(hhdr)
105    	    && hhdr -> hb_obj_kind == STUBBORN
106    	    && !GC_page_was_changed(h)
107    	    && !GC_on_free_list(h)) {
108    	    /* if GC_on_free_list(h) then reclaim may have touched it	*/
109    	    /* without any allocations taking place.			*/
110    	    /* Set breakpoint here */GC_n_changed_errors++;
111    	  }
112#	endif
113    }
114    pe -> new_valid = TRUE;
115    pe -> block = h + OFFSET;
116}
117
118unsigned long GC_bytes_in_used_blocks;
119
120void GC_add_block(h, dummy)
121struct hblk *h;
122word dummy;
123{
124   hdr * hhdr = HDR(h);
125   bytes = hhdr -> hb_sz;
126   
127   bytes += HBLKSIZE-1;
128   bytes &= ~(HBLKSIZE-1);
129   GC_bytes_in_used_blocks += bytes;
130}
131
132void GC_check_blocks()
133{
134    unsigned long bytes_in_free_blocks = GC_large_free_bytes;
135    
136    GC_bytes_in_used_blocks = 0;
137    GC_apply_to_all_blocks(GC_add_block, (word)0);
138    GC_printf("GC_bytes_in_used_blocks = %lu, bytes_in_free_blocks = %lu ",
139    	      GC_bytes_in_used_blocks, bytes_in_free_blocks);
140    GC_printf("GC_heapsize = %lu\n", (unsigned long)GC_heapsize);
141    if (GC_bytes_in_used_blocks + bytes_in_free_blocks != GC_heapsize) {
142    	GC_printf("LOST SOME BLOCKS!!\n");
143    }
144}
145
146/* Should be called immediately after GC_read_dirty and GC_read_changed. */
147void GC_check_dirty()
148{
149    register int index;
150    register unsigned i;
151    register struct hblk *h;
152    register ptr_t start;
153    
154    GC_check_blocks();
155    
156    GC_n_dirty_errors = 0;
157    GC_n_changed_errors = 0;
158    GC_n_clean = 0;
159    GC_n_dirty = 0;
160    
161    index = 0;
162    for (i = 0; i < GC_n_heap_sects; i++) {
163    	start = GC_heap_sects[i].hs_start;
164        for (h = (struct hblk *)start;
165             h < (struct hblk *)(start + GC_heap_sects[i].hs_bytes);
166             h++) {
167             GC_update_check_page(h, index);
168             index++;
169             if (index >= NSUMS) goto out;
170        }
171    }
172out:
173    GC_printf("Checked %lu clean and %lu dirty pages\n",
174    	      (unsigned long) GC_n_clean, (unsigned long) GC_n_dirty);
175    if (GC_n_dirty_errors > 0) {
176        GC_printf("Found %lu dirty bit errors\n",
177        	  (unsigned long)GC_n_dirty_errors);
178    }
179    if (GC_n_changed_errors > 0) {
180    	GC_printf("Found %lu changed bit errors\n",
181        	  (unsigned long)GC_n_changed_errors);
182	GC_printf("These may be benign (provoked by nonpointer changes)\n");
183#	ifdef THREADS
184	    GC_printf(
185	    "Also expect 1 per thread currently allocating a stubborn obj.\n");
186#	endif
187    }
188}
189
190# else
191
192extern int GC_quiet;
193	/* ANSI C doesn't allow translation units to be empty.	*/
194	/* So we guarantee this one is nonempty.		*/
195
196# endif /* CHECKSUMS */