Modify placer to allow single object containers, use offset in container.

This commit is contained in:
Nikolay Igotti
2016-09-28 16:37:01 +03:00
parent 89d6c24f56
commit cbdcd863d1
2 changed files with 164 additions and 116 deletions
+162 -114
View File
@@ -11,53 +11,120 @@
class Container;
class TypeInfo;
// Header of every object. Now contains direct references, will contain
// offsets in real translated code.
// Could be made 64-bit for large memory configs.
typedef uint32_t container_offset_t;
// Header of every object.
struct ObjHeader {
Container* container_;
const TypeInfo* type_info_;
container_offset_t container_offset_negative_;
};
// Header of value type array objects.
struct ArrayHeader : public ObjHeader {
int count_;
uint32_t count_;
};
struct ContainerHeader {
// Reference counter of container.
int ref_count_;
// Class representing placement container. Container is used for reference counting,
// and it is assumed that objects with related placement will share container. Only
// whole container can be freed, individual objects are not taken into account.
class Container {
private:
// Data where everything is being stored.
uint8_t* data_;
void AddRef() {
ref_count_++;
}
void Release() {
if (--ref_count_ == 0) {
free(this);
}
}
};
struct ArenaContainerHeader : public ContainerHeader {
// Current allocation limit. As objects never freed, we can have rather simple
// allocation algorithm.
uint8_t* current_;
// Total size of the container.
int size_;
// Reference counter of container.
int ref_count_;
uint8_t* end_;
};
// Class representing placement container for single object.
class Container {
protected:
// Data where everything is being stored.
ContainerHeader* header_;
void SetMeta(ObjHeader* obj, const TypeInfo* type_info) {
obj->container_offset_negative_ =
reinterpret_cast<uintptr_t>(obj) - reinterpret_cast<uintptr_t>(header_);
obj->type_info_ = type_info;
}
public:
Container(int size)
: size_(size), ref_count_(1) {
data_ = reinterpret_cast<uint8_t*>(calloc(size_, 1));
current_ = data_;
// Increment reference counter associated with container.
void AddRef() {
if (header_) header_->AddRef();
}
~Container() {
assert(ref_count_ == 0);
free(data_);
// Decrement reference counter associated with container.
// For objects whith tricky lifetime (such as ones shared between threads objects)
// individual container per object (ObjectContainer) shall be created.
// As an alternative, such objects could be evacuated from short-lived containers.
void Release() {
if (header_) header_->Release();
}
};
// Container for a single object.
class ObjectContainer : public Container {
public:
explicit ObjectContainer(int size) {
header_ = reinterpret_cast<ContainerHeader*>(
calloc(size + sizeof(ContainerHeader), 1));
header_->ref_count_ = 1;
}
~ObjectContainer() {
assert(header_->ref_count_ == 0);
free(header_);
}
void* GetPlace() const {
return reinterpret_cast<uint8_t*>(header_) + sizeof(ContainerHeader);
}
};
// Class representing arena-style placement container.
// Container is used for reference counting,
// and it is assumed that objects with related placement will share container. Only
// whole container can be freed, individual objects are not taken into account.
class ArenaContainer : public Container {
public:
explicit ArenaContainer(int size) {
header_ = reinterpret_cast<ArenaContainerHeader*>(
calloc(size + sizeof(ArenaContainerHeader), 1));
header_->ref_count_ = 1;
ArenaContainerHeader* header = static_cast<ArenaContainerHeader*>(header_);
header->current_ = reinterpret_cast<uint8_t*>(header_) + sizeof(ArenaContainerHeader);
header->end_ = header->current_ + size;
}
~ArenaContainer() {
if (header_) {
assert(header_->ref_count_ == 0);
free(header_);
}
}
// Allocation function.
void* Place(int size) {
if (current_ + size > data_ + size_) {
ArenaContainerHeader* header = reinterpret_cast<ArenaContainerHeader*>(header_);
if (header->current_ + size > header->end_) {
return nullptr;
}
void* result = current_;
current_ += size;
void* result = header->current_;
header->current_ += size;
return result;
}
@@ -68,31 +135,13 @@ class Container {
// is type infor for an array, not for an individual element.
ArrayHeader* PlaceArray(const TypeInfo* array_type_info, int count);
// Increment reference counter associated with container.
void AddRef() {
if (data_) {
// printf("addref %d\n", ref_count_);
ref_count_++;
}
}
// Decrement reference counter associated with container.
// For objects whith tricky lifetime (such as ones shared between threads objects)
// individual container per object shall be created. As an alternative, such objects
// could be evacuated from short-lived containers.
void Release() {
if (data_) {
// printf("release %d\n", ref_count_);
ref_count_--;
}
}
// Dispose whole container ignoring non-zero refcount. Use with care.
void Dispose() {
ref_count_ = 0;
free(data_);
data_ = nullptr;
current_ = nullptr;
if (header_) {
header_->ref_count_ = 0;
free(header_);
header_ = nullptr;
}
}
};
@@ -114,19 +163,20 @@ class AnyObjRef {
explicit AnyObjRef(ObjHeader* ptr) : ptr_(ptr) {
if (ptr_) {
container()->AddRef();
container_header()->AddRef();
}
}
public:
~AnyObjRef() {
if (ptr_) {
container()->Release();
container_header()->Release();
}
}
Container* container() const {
return ptr_->container_;
ContainerHeader* container_header() const {
return reinterpret_cast<ContainerHeader*>(
reinterpret_cast<uint8_t*>(ptr_) - ptr_->container_offset_negative_);
}
const TypeInfo* type_info() const {
@@ -146,11 +196,11 @@ class AnyObjRef {
void Assign(const AnyObjRef& other) {
// TODO: optimize for an important case where containers match?
if (ptr_) {
container()->Release();
container_header()->Release();
}
ptr_ = other.ptr_;
if (ptr_) {
container()->AddRef();
container_header()->AddRef();
}
}
@@ -210,7 +260,7 @@ class ObjRef : public AnyObjRef {
void CopyTo(ObjRef<T> other) const;
// Clones object to given container.
ObjRef<T> Clone(Container* container) {
ObjRef<T> Clone(ArenaContainer* container) {
ObjRef<T> result = Alloc(container);
CopyTo(result);
return result;
@@ -223,7 +273,7 @@ class ObjRef : public AnyObjRef {
}
// Allocates properly typed object in container.
static ObjRef<T> Alloc(Container* container) {
static ObjRef<T> Alloc(ArenaContainer* container) {
return ObjRef<T>(container->PlaceObject(T::GetTypeInfo()));
}
};
@@ -236,7 +286,7 @@ class ArrayRef : public AnyObjRef {
ArrayHeader* header() { return reinterpret_cast<ArrayHeader*>(ptr_); }
public:
static ArrayRef<T> Alloc(Container* container, int count) {
static ArrayRef<T> Alloc(ArenaContainer* container, int count) {
auto result = ArrayRef<T>(container->PlaceArray(GetArrayTypeInfo<T>(), count));
result.header()->count_ = count;
return result;
@@ -281,10 +331,10 @@ class TypeInfo {
int fields_count_;
public:
TypeInfo(name_hash_t name, int size, const TypeInfo* super_type,
std::initializer_list<int> obj_offsets,
std::initializer_list<TypeInfo*> implemented_interfaces,
std::initializer_list<MethodTableRecord> methods,
std::initializer_list<FieldTableRecord> fields)
std::initializer_list<int> obj_offsets,
std::initializer_list<TypeInfo*> implemented_interfaces,
std::initializer_list<MethodTableRecord> methods,
std::initializer_list<FieldTableRecord> fields)
: name_(name), size_(size), super_type_(super_type),
obj_offsets_(obj_offsets.begin()), obj_offsets_count_(obj_offsets.size()),
implemented_interfaces_(implemented_interfaces.begin()),
@@ -301,25 +351,23 @@ class TypeInfo {
}
};
inline ObjHeader* Container::PlaceObject(const TypeInfo* type_info) {
inline ObjHeader* ArenaContainer::PlaceObject(const TypeInfo* type_info) {
int size = type_info->size() + sizeof(ObjHeader);
ObjHeader* result = reinterpret_cast<ObjHeader*>(Place(size));
if (!result) {
ObjHeader* result = reinterpret_cast<ObjHeader*>(Place(size));
if (!result) {
return nullptr;
}
result->container_ = this;
result->type_info_ = type_info;
return result;
}
SetMeta(result, type_info);
return result;
}
inline ArrayHeader* Container::PlaceArray(const TypeInfo* type_info, int count) {
inline ArrayHeader* ArenaContainer::PlaceArray(const TypeInfo* type_info, int count) {
int size = sizeof(ArrayHeader) + type_info->size() * count;
ArrayHeader* result = reinterpret_cast<ArrayHeader*>(Place(size));
if (!result) {
return nullptr;
}
result->container_ = this;
result->type_info_ = type_info;
SetMeta(result, type_info);
result->count_ = count;
return result;
}
@@ -335,7 +383,7 @@ inline void ObjRef<T>::CopyTo(ObjRef<T> other) const {
for (int i = 0; i < obj_offsets_count; ++i) {
AnyObjRef any = other.any_obj_at(obj_offsets[i]);
if (!any.null()) {
any.container()->AddRef();
any.container_header()->AddRef();
}
}
} else {
@@ -346,49 +394,49 @@ inline void ObjRef<T>::CopyTo(ObjRef<T> other) const {
// This is magic for compile-time hash computation. Not needed in real translator.
static constexpr uint32_t crc_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
template<size_t idx>
+2 -2
View File
@@ -41,14 +41,14 @@ void ReturnByValue(ObjRef<List> value) {
value.at<int, data_offset>().set(239);
}
ObjRef<List> ReturnByRef(Container* container) {
ObjRef<List> ReturnByRef(ArenaContainer* container) {
auto result = ObjRef<List>::Alloc(container);
result.at<int, data_offset>().set(30);
return result;
}
void test_placer() {
Container heap(1024);
ArenaContainer heap(1024);
{
ObjRef<List> head = ObjRef<List>::Alloc(&heap);
head.at<int, data_offset>().set(1);