+2008-08-21 Hans Boehm <Hans.Boehm@hp.com>
+ * mark.c: (GC_push_next_marked, GC_push_next_marked_dirty,
+ GC_push_next_marked_uncollectable): Never invoke GC_push_marked
+ on free hblk.
+ * headers.c: Test COUNT_HDR_CACHE_HITS not USE_HDR_CACHE.
+ (GC_header_cache_miss): Always blacklist pointers for free
+ hblks. Add assertion and comment.
+ * pthread_support.c (GC_register_my_thread): Fix #if indentation.
+ * include/private/gc_hdrs.h: USE_HDR_CACHE is no longer tested.
+ Delete it.
+ * include/private/gc_pmark.h: (PUSH_OBJ): Add assertion.
+
+2008-08-21 Hans Boehm <Hans.Boehm@hp.com>
+ * alloc.c, include/gc_mark.h, Makefile.direct: Improve comments.
+
2008-08-01 Hans Boehm <Hans.Boehm@hp.com> (Really Klaus Treichel)
* configure.ac: Set win32_threads on MinGW.
* configure: Regenerate.
# may help performance on recent Linux installations. (It failed for
# me on RedHat 8, but appears to work on RedHat 9.)
# -DPARALLEL_MARK allows the marker to run in multiple threads. Recommended
-# for multiprocessors. Currently requires Linux on X86 or IA64, though
-# support for other Posix platforms should be fairly easy to add,
+# for multiprocessors. Currently works only on some pthreads platforms,
+# though support for other platforms should be fairly easy to add,
# if the thread implementation is otherwise supported.
# -DNO_GETENV prevents the collector from looking at environment variables.
# These may otherwise alter its configuration, or turn off GC altogether.
(unsigned long)GC_bytes_allocd);
}
/* Adjust heap limits generously for blacklisting to work better. */
- /* GC_add_to_heap performs minimal adjustment need for correctness. */
+ /* GC_add_to_heap performs minimal adjustment needed for */
+ /* correctness. */
expansion_slop = min_bytes_allocd() + 4*MAXHINCR*HBLKSIZE;
if ((GC_last_heap_addr == 0 && !((word)space & SIGNB))
|| (GC_last_heap_addr != 0 && GC_last_heap_addr < (ptr_t)space)) {
/* GUARANTEED to return 0 for a pointer past the first page */
/* of an object unless both GC_all_interior_pointers is set */
/* and p is in fact a valid object pointer. */
+/* Never returns a pointer to a free hblk. */
#ifdef PRINT_BLACK_LIST
hdr * GC_header_cache_miss(ptr_t p, hdr_cache_entry *hce, ptr_t source)
#else
hhdr = HDR(current);
} while(IS_FORWARDING_ADDR_OR_NIL(hhdr));
/* current points to near the start of the large object */
- if (hhdr -> hb_flags & IGNORE_OFF_PAGE
- || HBLK_IS_FREE(hhdr))
+ if (hhdr -> hb_flags & IGNORE_OFF_PAGE)
return 0;
- if (p - current >= (ptrdiff_t)(hhdr->hb_sz)) {
+ if (HBLK_IS_FREE(hhdr)
+ || p - current >= (ptrdiff_t)(hhdr->hb_sz)) {
GC_ADD_TO_BLACK_LIST_NORMAL(p, source);
/* Pointer past the end of the block */
return 0;
}
} else {
GC_ADD_TO_BLACK_LIST_NORMAL(p, source);
+ /* And return zero: */
}
+ GC_ASSERT(hhdr == 0 || !HBLK_IS_FREE(hhdr));
return hhdr;
/* Pointers past the first page are probably too rare */
/* to add them to the cache. We don't. */
hdr_free_list = hhdr;
}
-#ifdef USE_HDR_CACHE
+#ifdef COUNT_HDR_CACHE_HITS
word GC_hdr_cache_hits = 0;
word GC_hdr_cache_misses = 0;
#endif
extern void * GC_greatest_plausible_heap_addr;
/* Bounds on the heap. Guaranteed valid */
/* Likely to include future heap expansion. */
+ /* Hence usually includes not-yet-mapped */
+ /* memory. */
/* Handle nested references in a custom mark procedure. */
/* Check if obj is a valid object. If so, ensure that it is marked. */
# define TOP_SZ (1 << LOG_TOP_SZ)
# define BOTTOM_SZ (1 << LOG_BOTTOM_SZ)
-#ifndef SMALL_CONFIG
-# define USE_HDR_CACHE
-#endif
-
/* #define COUNT_HDR_CACHE_HITS */
# ifdef COUNT_HDR_CACHE_HITS
{ \
register word _descr = (hhdr) -> hb_descr; \
\
+ GC_ASSERT(!HBLK_IS_FREE(hhdr)); \
if (_descr != 0) { \
mark_stack_top++; \
if (mark_stack_top >= mark_stack_limit) { \
{
hdr * hhdr = HDR(h);
- if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr), FALSE)) {
+ if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr) || HBLK_IS_FREE(hhdr), FALSE)) {
h = GC_next_used_block(h);
if (h == 0) return(0);
hhdr = GC_find_header((ptr_t)h);
if (!GC_dirty_maintained) { ABORT("dirty bits not set up"); }
for (;;) {
- if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr), FALSE)) {
+ if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr)
+ || HBLK_IS_FREE(hhdr), FALSE)) {
h = GC_next_used_block(h);
if (h == 0) return(0);
hhdr = GC_find_header((ptr_t)h);
hdr * hhdr = HDR(h);
for (;;) {
- if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr), FALSE)) {
+ if (EXPECT(IS_FORWARDING_ADDR_OR_NIL(hhdr)
+ || HBLK_IS_FREE(hhdr), FALSE)) {
h = GC_next_used_block(h);
if (h == 0) return(0);
hhdr = GC_find_header((ptr_t)h);
me -> flags |= DETACHED;
/* Treat as detached, since we do not need to worry about */
/* pointer results. */
-# if defined(THREAD_LOCAL_ALLOC)
- GC_init_thread_local(&(me->tlfs));
-# endif
+# if defined(THREAD_LOCAL_ALLOC)
+ GC_init_thread_local(&(me->tlfs));
+# endif
UNLOCK();
return GC_SUCCESS;
} else {