Simplify the handling of OffPtr

This commit is contained in:
Konstantin Nazarov 2024-08-06 20:32:55 +01:00
parent 92f546107e
commit b40f835bfb
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
5 changed files with 63 additions and 50 deletions

View file

@ -133,14 +133,14 @@ Result<PodObject*> Arena::gc_pair(PodPair* obj) {
nobj->header.tag = Tag::Pair; nobj->header.tag = Tag::Pair;
PodObject* first = obj->first.get(obj); PodObject* first = obj->first.get();
PodObject* rest = obj->rest.get(obj); PodObject* rest = obj->rest.get();
first = TRY(gc_pod(first)); first = TRY(gc_pod(first));
rest = TRY(gc_pod(rest)); rest = TRY(gc_pod(rest));
nobj->first = OffPtr<PodObject>(nobj, first); nobj->first = first;
nobj->rest = OffPtr<PodObject>(nobj, rest); nobj->rest = rest;
return nobj; return nobj;
} }
@ -150,8 +150,8 @@ Result<PodObject*> Arena::gc_array(PodArray* obj) {
nobj->header.tag = Tag::Array; nobj->header.tag = Tag::Array;
nobj->size = obj->size; nobj->size = obj->size;
for (uint64_t i = 0; i < obj->size; i++) { for (uint64_t i = 0; i < obj->size; i++) {
PodObject* val = obj->data[i].get(obj); PodObject* val = obj->data[i].get();
nobj->data[i] = OffPtr<PodObject>(nobj, TRY(gc_pod(val))); nobj->data[i] = TRY(gc_pod(val));
} }
return nobj; return nobj;
} }
@ -169,8 +169,8 @@ Result<PodObject*> Arena::gc_dict(PodDict* obj) {
nobj->header.tag = Tag::Dict; nobj->header.tag = Tag::Dict;
nobj->size = obj->size; nobj->size = obj->size;
for (uint64_t i = 0; i < obj->size * 2; i++) { for (uint64_t i = 0; i < obj->size * 2; i++) {
PodObject* val = obj->data[i].get(obj); PodObject* val = obj->data[i].get();
nobj->data[i] = OffPtr<PodObject>(nobj, TRY(gc_pod(val))); nobj->data[i] = TRY(gc_pod(val));
} }
return nobj; return nobj;
// return ErrorCode::NotImplemented; // return ErrorCode::NotImplemented;

View file

@ -9,7 +9,7 @@
Syntax::Syntax(String filename, String modulename, Value expression) {} Syntax::Syntax(String filename, String modulename, Value expression) {}
Result<Value> Syntax::get_value(Arena& arena) { Result<Value> Syntax::get_value(Arena& arena) {
return Value::create(arena, _value->expression.get(&*_value)); return Value::create(arena, _value->expression.get());
} }
Result<Value> Value::create(Arena& arena, PodObject* obj) { Result<Value> Value::create(Arena& arena, PodObject* obj) {
@ -122,18 +122,18 @@ Result<Value> Bool::copy(Arena& arena) const {
Result<Pair> Pair::create(Arena& arena, Value& first, Value& rest) { Result<Pair> Pair::create(Arena& arena, Value& first, Value& rest) {
auto pod = TRY(arena.alloc<PodPair>()); auto pod = TRY(arena.alloc<PodPair>());
pod->header.tag = Tag::Pair; pod->header.tag = Tag::Pair;
pod->first = OffPtr<PodObject>(pod, first.pod()); pod->first = first.pod();
pod->rest = OffPtr<PodObject>(pod, rest.pod()); pod->rest = rest.pod();
return Pair(TRY(MkGcRoot(pod, arena))); return Pair(TRY(MkGcRoot(pod, arena)));
} }
Result<Value> Pair::first(Arena& arena) { Result<Value> Pair::first(Arena& arena) {
auto val = _value->first.get(pod()); auto val = _value->first.get();
return Value::create(arena, val); return Value::create(arena, val);
} }
Result<Value> Pair::rest(Arena& arena) { Result<Value> Pair::rest(Arena& arena) {
auto val = _value->rest.get(pod()); auto val = _value->rest.get();
return Value::create(arena, val); return Value::create(arena, val);
} }
@ -172,7 +172,7 @@ Result<void> debug_print(Arena& arena, Value& val) {
Result<Value> Array::get(Arena& arena, uint64_t idx) { Result<Value> Array::get(Arena& arena, uint64_t idx) {
if (idx >= _value->size) return ErrorCode::IndexOutOfRange; if (idx >= _value->size) return ErrorCode::IndexOutOfRange;
auto val = _value->data[idx].get(pod()); auto val = _value->data[idx].get();
return Value::create(arena, val); return Value::create(arena, val);
} }
@ -188,9 +188,9 @@ Result<Array> Array::append(Arena& arena, Value& rhs) {
pod->header.tag = Tag::Array; pod->header.tag = Tag::Array;
pod->size = res_size; pod->size = res_size;
for (uint64_t i = 0; i < size(); i++) { for (uint64_t i = 0; i < size(); i++) {
pod->data[i] = OffPtr<PodObject>(pod, _value->data[i].get(_value.get())); pod->data[i] = _value->data[i].get();
} }
pod->data[size()] = OffPtr<PodObject>(pod, rhs.pod()); pod->data[size()] = rhs.pod();
return Array(TRY(MkGcRoot(pod, arena))); return Array(TRY(MkGcRoot(pod, arena)));
} }
@ -204,13 +204,13 @@ short cmp_tag(Tag lhs, Tag rhs) {
Result<Value> Dict::get(Arena& arena, Value& key) { Result<Value> Dict::get(Arena& arena, Value& key) {
auto pos = TRY(find(arena, key)); auto pos = TRY(find(arena, key));
if (pos > size()) return ErrorCode::KeyError; if (pos > size()) return ErrorCode::KeyError;
auto k = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get()))); auto k = TRY(Value::create(arena, _value->data[pos * 2].get()));
if (TRY(k.cmp(arena, key)) != 0) { if (TRY(k.cmp(arena, key)) != 0) {
return ErrorCode::KeyError; return ErrorCode::KeyError;
} }
return TRY(Value::create(arena, _value->data[pos * 2 + 1].get(_value.get()))); return TRY(Value::create(arena, _value->data[pos * 2 + 1].get()));
} }
Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) { Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) {
@ -219,7 +219,7 @@ Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) {
if (pos >= s) { if (pos >= s) {
s += 1; s += 1;
} else { } else {
auto k = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get()))); auto k = TRY(Value::create(arena, _value->data[pos * 2].get()));
if (TRY(k.cmp(arena, key)) != 0) s += 1; if (TRY(k.cmp(arena, key)) != 0) s += 1;
} }
@ -230,19 +230,16 @@ Result<Dict> Dict::insert(Arena& arena, Value& key, Value& value) {
auto vpod = _value.get(); auto vpod = _value.get();
for (uint64_t i = 0, j = 0; i < s; i++, j++) { for (uint64_t i = 0, j = 0; i < s; i++, j++) {
if (i == pos) { if (i == pos) {
pod->data[i * 2] = OffPtr<PodObject>(pod, key.pod()); pod->data[i * 2] = key.pod();
pod->data[i * 2 + 1] = OffPtr<PodObject>(pod, value.pod()); pod->data[i * 2 + 1] = value.pod();
if (s > size() && i < s - 1) { if (s > size() && i < s - 1) {
i++; i++;
pod->data[i * 2] = pod->data[i * 2] = _value->data[j * 2].get();
OffPtr<PodObject>(pod, _value->data[j * 2].get(vpod)); pod->data[i * 2 + 1] = _value->data[j * 2 + 1].get();
pod->data[i * 2 + 1] =
OffPtr<PodObject>(pod, _value->data[j * 2 + 1].get(vpod));
} }
} else { } else {
pod->data[i * 2] = OffPtr<PodObject>(pod, _value->data[j * 2].get(vpod)); pod->data[i * 2] = _value->data[j * 2].get();
pod->data[i * 2 + 1] = pod->data[i * 2 + 1] = _value->data[j * 2 + 1].get();
OffPtr<PodObject>(pod, _value->data[j * 2 + 1].get(vpod));
} }
} }
@ -254,7 +251,7 @@ Result<uint64_t> Dict::find(Arena& arena, Value& key) {
uint64_t right = size(); uint64_t right = size();
uint64_t pos = (left + right) / 2; uint64_t pos = (left + right) / 2;
while (left < right) { while (left < right) {
auto v = TRY(Value::create(arena, _value->data[pos * 2].get(_value.get()))); auto v = TRY(Value::create(arena, _value->data[pos * 2].get()));
auto c = TRY(v.cmp(arena, key)); auto c = TRY(v.cmp(arena, key));
if (c == 0) { if (c == 0) {
return pos; return pos;
@ -291,9 +288,8 @@ Result<short> Dict::cmp(Arena& arena, Dict& rhs) {
short cmp = short(i == lsize) - short(j == rsize); short cmp = short(i == lsize) - short(j == rsize);
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
Value lc = TRY(Value::create(arena, _value->data[i].get(_value.get()))); Value lc = TRY(Value::create(arena, _value->data[i].get()));
Value rc = Value rc = TRY(Value::create(arena, rhs._value->data[j].get()));
TRY(Value::create(arena, rhs._value->data[j].get(rhs._value.get())));
cmp = TRY(lc.cmp(arena, rc)); cmp = TRY(lc.cmp(arena, rc));
if (cmp != 0) return cmp; if (cmp != 0) return cmp;
i++; i++;

View file

@ -150,8 +150,12 @@ class Array : public Object {
auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*))); auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*)));
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(PodObject*) * lhs_size); for (uint64_t i = 0; i < size(); i++) {
memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char) * rhs_size); pod->data[i] = _value->data[i];
}
for (uint64_t i = size(); i < rhs.size(); i++) {
pod->data[i] = rhs._value->data[i];
}
return Array(TRY(MkGcRoot(pod, arena))); return Array(TRY(MkGcRoot(pod, arena)));
} }
@ -161,7 +165,9 @@ class Array : public Object {
uint64_t res_size = end - start; uint64_t res_size = end - start;
auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*))); auto pod = TRY(arena.alloc<PodArray>(res_size * sizeof(PodObject*)));
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data + start, sizeof(PodObject*) * res_size); for (uint64_t i = 0; i < end - start; i++) {
pod->data[i] = _value->data[start + i];
}
return Array(TRY(MkGcRoot(pod, arena))); return Array(TRY(MkGcRoot(pod, arena)));
} }
@ -326,10 +332,15 @@ class Dict : public Object {
uint64_t lhs_size = size(); uint64_t lhs_size = size();
uint64_t res_size = lhs_size + rhs_size; uint64_t res_size = lhs_size + rhs_size;
auto pod = TRY(arena.alloc<PodDict>(res_size * sizeof(PodObject*))); auto pod = TRY(arena.alloc<PodDict>(2 * res_size * sizeof(PodObject*)));
pod->size = res_size; pod->size = res_size;
memcpy(pod->data, _value->data, sizeof(PodObject*) * lhs_size);
memcpy(pod->data + lhs_size, rhs._value->data, sizeof(char) * rhs_size); for (uint64_t i = 0; i < 2 * size(); i++) {
pod->data[i] = _value->data[i];
}
for (uint64_t i = 2 * size(); i < 2 * rhs.size(); i++) {
pod->data[i] = rhs._value->data[i];
}
return Dict(TRY(MkGcRoot(pod, arena))); return Dict(TRY(MkGcRoot(pod, arena)));
} }

View file

@ -24,13 +24,21 @@ class OffPtr {
public: public:
OffPtr() : _offset(0) {} OffPtr() : _offset(0) {}
template <class R> template <class R>
OffPtr(R* base, T* ptr) OffPtr(T* ptr) : _offset((ptr == 0) ? 0 : (uint8_t*)ptr - (uint8_t*)this){};
: _offset((ptr == 0) ? 0 : (uint8_t*)ptr - (uint8_t*)base){};
template <class R> T* get() const {
T* get(R* base) {
if (_offset == 0) return 0; if (_offset == 0) return 0;
return (T*)(((uint8_t*)base) + _offset); return (T*)(((uint8_t*)this) + _offset);
}
OffPtr<T>& operator=(const OffPtr<T>& rhs) {
_offset = (uint8_t*)rhs.get() - (uint8_t*)this;
return *this;
}
OffPtr<T>& operator=(T* rhs) {
_offset = (uint8_t*)rhs - (uint8_t*)this;
return *this;
} }
private: private:
@ -40,9 +48,10 @@ class OffPtr {
static_assert(sizeof(OffPtr<void>) == 8); static_assert(sizeof(OffPtr<void>) == 8);
struct PodHeader { struct PodHeader {
PodHeader(Tag tag) : tag(tag), forward(0) {} PodHeader(Tag tag) : tag(tag), stat(0), forward(0) {}
Tag tag; Tag tag;
int64_t forward : 56; unsigned stat : 1;
int64_t forward : 55;
}; };
static_assert(sizeof(PodHeader) == 8); static_assert(sizeof(PodHeader) == 8);

View file

@ -194,11 +194,8 @@ Result<String> Writer::write_dict(Dict& val) {
bool is_first = true; bool is_first = true;
for (uint64_t i = 0; i < val.size(); i++) { for (uint64_t i = 0; i < val.size(); i++) {
Value k = TRY( Value k = TRY(Value::create(_arena, val._value->data[i * 2].get()));
Value::create(_arena, val._value->data[i * 2].get(val._value.get()))); Value v = TRY(Value::create(_arena, val._value->data[i * 2 + 1].get()));
Value v = TRY(Value::create(
_arena, val._value->data[i * 2 + 1].get(val._value.get())));
if (!is_first) res = TRY(res.concat(_arena, " ")); if (!is_first) res = TRY(res.concat(_arena, " "));