extern mark_proc GC_mark_procs[MAX_MARK_PROCS];
*/
+#ifndef MARK_DESCR_OFFSET
+# define MARK_DESCR_OFFSET sizeof(word)
+#endif
+
/*
* Mark descriptor stuff that should remain private for now, mostly
* because it's hard to export WORDSZ without including gcconfig.h.
* of the University of Tokyo SGC in a less intrusive, though probably
* also less performant, way.
*/
- void GC_do_parallel_mark();
- /* inititate parallel marking. */
-
- extern GC_bool GC_help_wanted; /* Protected by mark lock */
- extern unsigned GC_helper_count; /* Number of running helpers. */
- /* Protected by mark lock */
- extern unsigned GC_active_count; /* Number of active helpers. */
- /* Protected by mark lock */
- /* May increase and decrease */
- /* within each mark cycle. But */
- /* once it returns to 0, it */
- /* stays zero for the cycle. */
- /* GC_mark_stack_top is also protected by mark lock. */
+
+ /* GC_mark_stack_top is protected by mark lock. */
+
/*
* GC_notify_all_marker() is used when GC_help_wanted is first set,
* when the last helper becomes inactive,
{ \
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) { \
/* For our uses, that's benign: */
# define OR_WORD_EXIT_IF_SET(addr, bits, exit_label) \
{ \
- if (!(*(addr) & (mask))) { \
- AO_or((AO_t *)(addr), (mask); \
+ if (!(*(addr) & (bits))) { \
+ AO_or((AO_t *)(addr), (bits)); \
} else { \
- goto label; \
+ goto exit_label; \
} \
}
# else
# endif
-#ifdef USE_MARK_BYTES
# if defined(I386) && defined(__GNUC__)
# define LONG_MULT(hprod, lprod, x, y) { \
asm("mull %2" : "=a"(lprod), "=d"(hprod) : "g"(y), "0"(x)); \
}
# endif
+#ifdef USE_MARK_BYTES
/* There is a race here, and we may set */
/* the bit twice in the concurrent case. This can result in the */
/* object being pushed twice. But that's only a performance issue. */
#endif
/* If the mark bit corresponding to current is not set, set it, and */
/* push the contents of the object on the mark stack. Current points */
-/* to the bginning of the object. We rely on the fact that the */
+/* to the beginning of the object. We rely on the fact that the */
/* preceding header calculation will succeed for a pointer past the */
/* first page of an object, only if it is in fact a valid pointer */
/* to the object. Thus we can omit the otherwise necessary tests */
} \
GC_ASSERT(hhdr == GC_find_header(base)); \
GC_ASSERT(gran_displ % BYTES_TO_GRANULES(hhdr -> hb_sz) == 0); \
- TRACE(source, GC_log_printf("GC:%d: passed validity tests\n",GC_gc_no)); \
+ TRACE(source, GC_log_printf("GC:%u: passed validity tests\n", \
+ (unsigned)GC_gc_no)); \
SET_MARK_BIT_EXIT_IF_SET(hhdr, gran_displ, exit_label); \
- TRACE(source, GC_log_printf("GC:%d: previously unmarked\n",GC_gc_no)); \
+ TRACE(source, GC_log_printf("GC:%u: previously unmarked\n", \
+ (unsigned)GC_gc_no)); \
TRACE_TARGET(base, \
- GC_log_printf("GC:%d: marking %p from %p instead\n", GC_gc_no, \
+ GC_log_printf("GC:%u: marking %p from %p instead\n", (unsigned)GC_gc_no, \
base, source)); \
INCR_MARKS(hhdr); \
GC_STORE_BACK_PTR((ptr_t)source, base); \
source, exit_label, hhdr, do_offset_check) \
{ \
size_t displ = HBLKDISPL(current); /* Displacement in block; in bytes. */\
- unsigned32 low_prod, high_prod, offset_fraction; \
+ unsigned32 low_prod, high_prod; \
unsigned32 inv_sz = hhdr -> hb_inv_sz; \
ptr_t base = current; \
LONG_MULT(high_prod, low_prod, displ, inv_sz); \
GC_ASSERT((ptr_t)(hhdr -> hb_block) < (ptr_t) current); \
} else { \
/* Accurate enough if HBLKSIZE <= 2**15. */ \
- GC_ASSERT(HBLKSIZE <= (1 << 15)); \
+ GC_STATIC_ASSERT(HBLKSIZE <= (1 << 15)); \
size_t obj_displ = (((low_prod >> 16) + 1) * (hhdr -> hb_sz)) >> 16; \
if (do_offset_check && !GC_valid_offsets[obj_displ]) { \
GC_ADD_TO_BLACK_LIST_NORMAL(current, source); \
/* May get here for pointer to start of block not at */ \
/* beginning of object. If so, it's valid, and we're fine. */ \
GC_ASSERT(high_prod >= 0 && high_prod <= HBLK_OBJS(hhdr -> hb_sz)); \
- TRACE(source, GC_log_printf("GC:%d: passed validity tests\n",GC_gc_no)); \
+ TRACE(source, GC_log_printf("GC:%u: passed validity tests\n", \
+ (unsigned)GC_gc_no)); \
SET_MARK_BIT_EXIT_IF_SET(hhdr, high_prod, exit_label); \
- TRACE(source, GC_log_printf("GC:%d: previously unmarked\n",GC_gc_no)); \
+ TRACE(source, GC_log_printf("GC:%u: previously unmarked\n", \
+ (unsigned)GC_gc_no)); \
TRACE_TARGET(base, \
- GC_log_printf("GC:%d: marking %p from %p instead\n", GC_gc_no, \
+ GC_log_printf("GC:%u: marking %p from %p instead\n", \
+ (unsigned)GC_gc_no, \
base, source)); \
INCR_MARKS(hhdr); \
GC_STORE_BACK_PTR((ptr_t)source, base); \
#if defined(PRINT_BLACK_LIST) || defined(KEEP_BACK_PTRS)
# define PUSH_ONE_CHECKED_STACK(p, source) \
- GC_mark_and_push_stack(p, (ptr_t)(source))
+ GC_mark_and_push_stack((ptr_t)(p), (ptr_t)(source))
#else
# define PUSH_ONE_CHECKED_STACK(p, source) \
- GC_mark_and_push_stack(p)
+ GC_mark_and_push_stack((ptr_t)(p))
#endif
/*
# if NEED_FIXUP_POINTER
/* Try both the raw version and the fixed up one. */
# define GC_PUSH_ONE_STACK(p, source) \
- if ((p) >= (ptr_t)GC_least_plausible_heap_addr \
- && (p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
+ if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \
+ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
PUSH_ONE_CHECKED_STACK(p, source); \
} \
FIXUP_POINTER(p); \
- if ((p) >= (ptr_t)GC_least_plausible_heap_addr \
- && (p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
+ if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \
+ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
PUSH_ONE_CHECKED_STACK(p, source); \
}
# else /* !NEED_FIXUP_POINTER */
*/
# define GC_PUSH_ONE_HEAP(p,source) \
FIXUP_POINTER(p); \
- if ((p) >= (ptr_t)GC_least_plausible_heap_addr \
- && (p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
+ if ((ptr_t)(p) >= (ptr_t)GC_least_plausible_heap_addr \
+ && (ptr_t)(p) < (ptr_t)GC_greatest_plausible_heap_addr) { \
GC_mark_stack_top = GC_mark_and_push( \
(void *)(p), GC_mark_stack_top, \
GC_mark_stack_limit, (void * *)(source)); \
* real_ptr. That is the job of the caller, if appropriate.
* Note that this is called with the mutator running, but
* with us holding the allocation lock. This is safe only if the
- * mutator needs tha allocation lock to reveal hidden pointers.
+ * mutator needs the allocation lock to reveal hidden pointers.
* FIXME: Why do we need the GC_mark_state test below?
*/
# define GC_MARK_FO(real_ptr, mark_proc) \