factor/native/cards.h

78 lines
1.8 KiB
C

CELL heap_start;
CELL heap_end;
/* card marking write barrier. a card is a byte storing a mark flag,
and the offset (in cells) of the first object in the card.
the mark flag is set by the write barrier when an object in the
card has a slot written to.
the offset of the first object is set by the allocator.
*/
#define CARD_MARK_MASK 0x80
#define CARD_BASE_MASK 0x7f
typedef u8 CARD;
CARD *cards;
CARD *cards_end;
/* A card is 16 bytes (128 bits), 5 address bits per card.
it is important that 7 bits is sufficient to represent every
offset within the card */
#define CARD_SIZE 128
#define CARD_BITS 7
#define ADDR_CARD_MASK (CARD_SIZE-1)
INLINE CARD card_marked(CARD c)
{
return c & CARD_MARK_MASK;
}
INLINE void unmark_card(CARD *c)
{
*c &= CARD_BASE_MASK;
}
INLINE void clear_card(CARD *c)
{
*c = CARD_BASE_MASK; /* invalid value */
}
INLINE u8 card_base(CARD c)
{
return c & CARD_BASE_MASK;
}
#ifdef FACTOR_PPC
register CELL cards_offset asm("r16");
#else
CELL cards_offset;
#endif
#define ADDR_TO_CARD(a) (CARD*)(((CELL)a >> CARD_BITS) + cards_offset)
#define CARD_TO_ADDR(c) (CELL*)(((CELL)c - cards_offset)<<CARD_BITS)
/* this is an inefficient write barrier. compiled definitions use a more
efficient one hand-coded in assembly. the write barrier must be called
any time we are potentially storing a pointer from an older generation
to a younger one */
INLINE void write_barrier(CELL address)
{
CARD *c = ADDR_TO_CARD(address);
*c |= CARD_MARK_MASK;
}
/* we need to remember the first object allocated in the card */
INLINE void allot_barrier(CELL address)
{
CARD *ptr = ADDR_TO_CARD(address);
CARD c = *ptr;
CELL b = card_base(c);
CELL a = (address & ADDR_CARD_MASK);
*ptr = (card_marked(c) | ((b < a) ? b : a));
}
void unmark_cards(CELL from, CELL to);
void clear_cards(CELL from, CELL to);
void collect_cards(CELL gen);