AutoWriteBarrier.h [plain text]
#pragma once
#ifndef __AUTO_WRITEBARRIER__
#define __AUTO_WRITEBARRIER__
#include "AutoConfiguration.h"
#include "AutoDefs.h"
#include "AutoRange.h"
namespace Auto {
class MemoryScanner;
class Zone;
class WriteBarrier : public Range {
private:
void *_base; usword_t _protect;
public:
enum {
card_unmarked = 0,
card_marked_untouched = 0x1,
card_marked = 0x3
};
WriteBarrier(void *base, void *address, const usword_t size, const usword_t protect = 0)
: Range(address, size), _base(base), _protect(protect)
{
}
static inline const usword_t bytes_needed(usword_t n) {
return partition2(n, write_barrier_quantum_log2);
}
inline const usword_t card_index(void *address) const {
uintptr_t normalized = (uintptr_t)address - (uintptr_t)_base;
usword_t i = normalized >> write_barrier_quantum_log2;
ASSERTION(_protect <= i);
ASSERTION(i < size());
return i;
}
inline bool contains_card(void *address) {
usword_t i = card_index(address);
return (_protect <= i && i < size());
}
inline void *card_address(usword_t i) const { return displace(_base, i << write_barrier_quantum_log2); }
inline bool is_card_marked(usword_t i) { return ((unsigned char *)address())[i] != card_unmarked; }
inline void mark_card(usword_t i) {
((unsigned char *)address())[i] = card_marked;
}
usword_t mark_cards_untouched();
usword_t clear_untouched_cards();
inline bool is_card_marked(void *address) {
usword_t i = card_index(address);
return is_card_marked(i);
}
inline void mark_card(void *address) {
const usword_t i = card_index(address);
mark_card(i);
}
inline void mark_cards(void *address, const usword_t size) {
usword_t i = card_index(address);
const usword_t j = card_index(displace(address, size - 1));
for ( ; i <= j; i++) mark_card(i);
}
void scan_marked_ranges(void *address, const usword_t size, void (^scanner) (Range&, WriteBarrier*));
void scan_marked_ranges(void *address, const usword_t size, void (*scanner) (Range&, WriteBarrier*, void*), void *arg) {
scan_marked_ranges(address, size, ^(Range &range, WriteBarrier *wb) { scanner(range, wb, arg); });
}
void scan_marked_ranges(void *address, const usword_t size, MemoryScanner &scanner);
void scan_marked_ranges(const Range &range, MemoryScanner &scanner) { scan_marked_ranges(range.address(), range.size(), scanner); }
bool range_has_marked_cards(void *address, const usword_t size);
};
};
#endif // __AUTO_WRITEBARRIER__