#pragma once
#ifndef __AUTO_LARGE__
#define __AUTO_LARGE__
#include "Definitions.h"
#include "Statistics.h"
#include "WriteBarrier.h"
#include "auto_zone.h"
namespace Auto {
class Zone;
class Large {
private:
enum {
initial_age = 5
};
Large *_prev; Large *_next; Zone *_zone; usword_t _vm_size; usword_t _size; usword_t _layout; usword_t _refcount; usword_t _age; bool _is_pending; bool _is_marked; bool _is_garbage;
uint32_t _checking_count; WriteBarrier _write_barrier;
Large(Zone *zone, usword_t vm_size, usword_t size, usword_t layout, usword_t refcount, usword_t age, const WriteBarrier &wb);
public:
#if UseArena
static inline const usword_t quantum_index(void *address) { return (((usword_t)address >> allocate_quantum_large_log2) & mask(allocate_quantum_large_max_log2)); }
#else
static inline const usword_t quantum_index(void *address) { return ((usword_t)address >> allocate_quantum_large_log2); }
#endif
static inline const usword_t quantum_count(const size_t size) { return partition2(size, allocate_quantum_large_log2); }
static inline Large *quantum_large(const usword_t q, void*arena) { return (Large *)((usword_t)arena+(q << allocate_quantum_large_log2)); }
static inline usword_t side_data_size() { return align2(sizeof(Large), allocate_quantum_small_log2); }
inline void *address() { return displace(this, side_data_size()); }
static inline bool is_start(void *address) {
return (((uintptr_t)address) & mask(allocate_quantum_large_log2)) == side_data_size();
}
static inline Large *large(void *address) { return (Large *)displace(address, -side_data_size()); }
static Large *allocate(Zone *zone, const usword_t size, usword_t layout, bool refcount_is_one);
void deallocate(Zone *zone);
inline Large *prev() const { return _prev; }
inline Large *next() const { return _next; }
inline Zone *zone() const { return _zone; }
inline usword_t vm_size() const { return _vm_size; }
inline void set_prev(Large *prev) { _prev = prev; }
inline void set_next(Large *next) { _next = next; }
inline Range range() { return Range(address(), size()); }
inline void mark_garbage() { _is_garbage = true; }
inline bool is_garbage() const { return _is_garbage; }
inline uint32_t collection_checking_count() const { return _checking_count; }
inline void set_collection_checking_count(uint32_t count) { _checking_count = count; }
inline usword_t size() const { return _size; }
inline bool is_new() const { return _age != 0; }
inline bool is_newest() const { return _age == initial_age; }
inline usword_t age() const { return _age; }
inline void set_age(usword_t a) { _age = a; }
inline void mature() { _age--; }
inline bool is_pending() const { return _is_pending; }
inline bool is_marked() const { return _is_marked; }
inline usword_t layout() const { return _layout; }
inline bool is_scanned() const { return ::is_scanned(_layout); }
inline bool is_object() const { return ::is_object(_layout); }
inline usword_t refcount() const { return _refcount; }
inline void set_pending() { _is_pending = true; }
inline void clear_pending() { _is_pending = false; }
inline void set_mark() { _is_marked = true; }
inline void clear_mark() { _is_marked = false; }
inline bool test_and_set_mark() {
bool old = _is_marked;
if (!old) _is_marked = true;
return old;
}
inline bool test_clear_mark() {
bool old = _is_marked;
if (old) _is_marked = false;
return old;
}
inline void set_refcount(usword_t refcount) { _refcount = refcount; }
inline void set_layout(usword_t layout) { _layout = layout; }
inline void add(Large *&large_list) {
_prev = NULL;
_next = large_list;
if (large_list) large_list->set_prev(this);
large_list = this;
}
inline void remove(Large *&large_list) {
if (large_list == this) large_list = _next;
if (_prev) _prev->set_next(_next);
if (_next) _next->set_prev(_prev);
_prev = _next = NULL;
}
inline WriteBarrier& write_barrier() {
return _write_barrier;
}
};
};
#endif // __AUTO_LARGE__