#pragma once #include "obj.h" #include "common.h" #include "memory.h" #include "str.h" namespace pkpy{ struct Dict{ using Item = std::pair; static constexpr int __Capacity = 8; static constexpr float __LoadFactor = 0.67f; static_assert(sizeof(Item) * __Capacity <= 128); VM* vm; int _capacity; int _mask; int _size; int _critical_size; Item* _items; Dict(VM* vm): vm(vm), _capacity(__Capacity), _mask(__Capacity-1), _size(0), _critical_size(__Capacity*__LoadFactor+0.5f){ _items = (Item*)pool128.alloc(_capacity * sizeof(Item)); memset(_items, 0, _capacity * sizeof(Item)); } int size() const { return _size; } Dict(Dict&& other){ vm = other.vm; _capacity = other._capacity; _mask = other._mask; _size = other._size; _critical_size = other._critical_size; _items = other._items; other._items = nullptr; } Dict(const Dict& other){ vm = other.vm; _capacity = other._capacity; _mask = other._mask; _size = other._size; _critical_size = other._critical_size; _items = (Item*)pool128.alloc(_capacity * sizeof(Item)); memcpy(_items, other._items, _capacity * sizeof(Item)); } Dict& operator=(const Dict&) = delete; Dict& operator=(Dict&&) = delete; void _probe(PyObject* key, bool& ok, int& i) const; void set(PyObject* key, PyObject* val){ bool ok; int i; _probe(key, ok, i); if(!ok) { _size++; if(_size > _critical_size){ _rehash(); _probe(key, ok, i); } _items[i].first = key; } _items[i].second = val; } void _rehash(){ Item* old_items = _items; int old_capacity = _capacity; _capacity *= 2; _mask = _capacity - 1; _critical_size = _capacity * __LoadFactor + 0.5f; _items = (Item*)pool128.alloc(_capacity * sizeof(Item)); memset(_items, 0, _capacity * sizeof(Item)); for(int i=0; i items() const { std::vector v; for(int i=0; i<_capacity; i++){ if(_items[i].first == nullptr) continue; v.push_back(_items[i]); } return v; } void clear(){ memset(_items, 0, _capacity * sizeof(Item)); _size = 0; } ~Dict(){ if(_items!=nullptr) pool128.dealloc(_items); } void _gc_mark() const{ for(int i=0; i<_capacity; i++){ if(_items[i].first == nullptr) continue; OBJ_MARK(_items[i].first); OBJ_MARK(_items[i].second); } } }; } // namespace pkpy