From 43b7130f997b14bd1363c8e6f18a9e31c0da772c Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sat, 25 Feb 2023 00:31:17 +0800 Subject: [PATCH] use `uint32_t` --- src/common.h | 2 +- src/frame.h | 24 +++++---- src/namedict.h | 141 ++++++++++++++++++++++++++----------------------- src/obj.h | 5 +- src/vm.h | 4 +- 5 files changed, 95 insertions(+), 81 deletions(-) diff --git a/src/common.h b/src/common.h index 02b7cc3e..81a5d91f 100644 --- a/src/common.h +++ b/src/common.h @@ -73,4 +73,4 @@ struct Type { const float kLocalsLoadFactor = 0.67; const float kInstAttrLoadFactor = 0.67; -const float kTypeAttrLoadFactor = 0.34; \ No newline at end of file +const float kTypeAttrLoadFactor = 0.5; \ No newline at end of file diff --git a/src/frame.h b/src/frame.h index 3a38f8fd..b70fbe75 100644 --- a/src/frame.h +++ b/src/frame.h @@ -2,7 +2,7 @@ #include "codeobject.h" -static THREAD_LOCAL i64 kFrameGlobalId = 0; +static THREAD_LOCAL uint64_t kFrameGlobalId = 0; struct Frame { std::vector _data; @@ -11,10 +11,10 @@ struct Frame { const CodeObject* co; PyVar _module; - pkpy::shared_ptr _locals; - pkpy::shared_ptr _closure; - const i64 id; - std::stack>> s_try_block; + NameDict_ _locals; + NameDict_ _closure; + const uint64_t id; + std::vector>> s_try_block; inline pkpy::NameDict& f_locals() noexcept { return _locals != nullptr ? *_locals : _module->attr(); } inline pkpy::NameDict& f_globals() noexcept { return _module->attr(); } @@ -24,9 +24,11 @@ struct Frame { return _closure->try_get(name); } - Frame(const CodeObject_& co, const PyVar& _module, - pkpy::shared_ptr _locals=nullptr, pkpy::shared_ptr _closure=nullptr) - : co(co.get()), _module(_module), _locals(_locals), _closure(_closure), id(kFrameGlobalId++) { } + Frame(const CodeObject_& co, + const PyVar& _module, + const NameDict_& _locals=nullptr, + const NameDict_& _closure=nullptr) + : co(co.get()), _module(_module), _locals(_locals), _closure(_closure), id(kFrameGlobalId++) { } inline const Bytecode& next_bytecode() { _ip = _next_ip++; @@ -96,17 +98,17 @@ struct Frame { inline void jump_rel(int i){ _next_ip += i; } inline void on_try_block_enter(){ - s_try_block.push(std::make_pair(co->codes[_ip].block, _data)); + s_try_block.emplace_back(co->codes[_ip].block, _data); } inline void on_try_block_exit(){ - s_try_block.pop(); + s_try_block.pop_back(); } bool jump_to_exception_handler(){ if(s_try_block.empty()) return false; PyVar obj = pop(); - auto& p = s_try_block.top(); + auto& p = s_try_block.back(); _data = std::move(p.second); _data.push_back(obj); _next_ip = co->blocks[p.first].end; diff --git a/src/namedict.h b/src/namedict.h index ed6da0f2..7bcbec82 100644 --- a/src/namedict.h +++ b/src/namedict.h @@ -4,16 +4,17 @@ #include "memory.h" #include "str.h" +const int kNameDictNodeSize = sizeof(StrName) + sizeof(PyVar); template struct DictArrayPool { - std::deque buckets[__Bucket+1]; + std::vector buckets[__Bucket+1]; - StrName* alloc(uint32_t n){ + StrName* alloc(uint16_t n){ StrName* _keys; if(n > __Bucket || buckets[n].empty()){ - _keys = (StrName*)malloc((sizeof(StrName)+sizeof(PyVar)) * n); - memset((void*)_keys, 0, (sizeof(StrName)+sizeof(PyVar)) * n); + _keys = (StrName*)malloc(kNameDictNodeSize * n); + memset((void*)_keys, 0, kNameDictNodeSize * n); }else{ _keys = buckets[n].back(); memset((void*)_keys, 0, sizeof(StrName) * n); @@ -22,7 +23,7 @@ struct DictArrayPool { return _keys; } - void dealloc(StrName* head, uint32_t n){ + void dealloc(StrName* head, uint16_t n){ PyVar* _values = (PyVar*)(head + n); if(n > __Bucket || buckets[n].size() >= __BucketSize){ for(int i=0; i kHashSeeds = {2654435761, 740041872, 89791836, 2530921597, 3099937610, 4149637300, 2701344377, 1871341841, 1162794509, 172427115, 1636841237, 716883023, 3294650677, 54921151, 3697702254, 632800580, 704251301, 1107400416, 3158440428, 581874317, 3196521560, 2374935651, 3196227762, 2033551959, 2028119291, 348132418, 392150876, 3839168722, 3705071505, 742931757, 2917622539, 3641634736, 3438863246, 1211314974, 1389620692, 3842835768, 165823282, 2225611914, 1862128271, 2147948325, 3759309280, 2087364973, 3453466014, 2082604761, 3627961499, 967790220, 3285133283, 2749567844, 262853493, 142639230, 3079101350, 2942333634, 1470374050, 3719337124, 2487858314, 1605159164, 2958061235, 3310454023, 3143584575, 3696188862, 3455413544, 148400163, 889426286, 1485235735}; + const std::vector kHashSeeds = {9629, 43049, 13267, 59509, 39251, 1249, 35803, 54469, 27689, 9719, 34897, 18973, 30661, 19913, 27919, 32143, 3467, 28019, 1051, 39419, 1361, 28547, 48197, 2609, 24317, 22861, 41467, 17623, 52837, 59053, 33589, 32117}; static DictArrayPool<32> _dict_pool; - uint32_t find_next_capacity(uint32_t n){ - uint32_t x = 2; - while(x < n) x *= 2; + uint16_t find_next_capacity(uint16_t n){ + uint16_t x = 2; + while(x < n) x <<= 1; return x; } -#define _hash(key, mask, hash_seed) ( ( (key).index * (hash_seed) >> 16 ) & (mask) ) +#define _hash(key, mask, hash_seed) ( ( (key).index * (hash_seed) >> 8 ) & (mask) ) - uint32_t find_perfect_hash_seed(uint32_t capacity, const std::vector& keys){ + uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vector& keys){ if(keys.empty()) return kHashSeeds[0]; - std::set indices; - std::vector> scores; + std::set indices; + std::pair best_score = {kHashSeeds[0], 0}; for(int i=0; i best_score.second) best_score = {kHashSeeds[i], score}; } - std::sort(scores.begin(), scores.end(), [](auto a, auto b){ return a.second > b.second; }); - return scores[0].first; + return best_score.first; } struct NameDict { - uint32_t _capacity; - uint32_t _size; + uint16_t _capacity; + uint16_t _size; float _load_factor; - uint32_t _hash_seed; - uint32_t _mask; + uint16_t _hash_seed; + uint16_t _mask; StrName* _keys; - PyVar* _values; - inline void _alloc(uint32_t capacity){ - _keys = _dict_pool.alloc(capacity); - _values = (PyVar*)(_keys + capacity); + inline PyVar& value(uint16_t i){ + return reinterpret_cast(_keys + _capacity)[i]; } - inline void _dealloc(StrName* head, uint32_t capacity){ + inline const PyVar& value(uint16_t i) const { + return reinterpret_cast(_keys + _capacity)[i]; + } + + inline void _alloc(uint16_t capacity){ + _keys = _dict_pool.alloc(capacity); + } + + inline static void _dealloc(StrName* head, uint16_t capacity){ + if(head == nullptr) return; _dict_pool.dealloc(head, capacity); } - NameDict(uint32_t capacity=2, float load_factor=0.67, uint32_t hash_seed=kHashSeeds[0]): + NameDict(uint16_t capacity=2, float load_factor=0.67, uint16_t hash_seed=kHashSeeds[0]): _capacity(capacity), _size(0), _load_factor(load_factor), _hash_seed(hash_seed), _mask(capacity-1) { _alloc(capacity); } NameDict(const NameDict& other) { - this->_capacity = other._capacity; - this->_size = other._size; - this->_load_factor = other._load_factor; - this->_hash_seed = other._hash_seed; + memcpy(this, &other, sizeof(NameDict)); _alloc(_capacity); - this->_mask = other._mask; - for(uint32_t i=0; i<_capacity; i++){ + for(int i=0; i<_capacity; i++){ _keys[i] = other._keys[i]; - _values[i] = other._values[i]; + value(i) = other.value(i); } } + + NameDict& operator=(const NameDict& other) { + _dealloc(_keys, _capacity); + memcpy(this, &other, sizeof(NameDict)); + _alloc(_capacity); + for(int i=0; i<_capacity; i++){ + _keys[i] = other._keys[i]; + value(i) = other.value(i); + } + return *this; + } - NameDict& operator=(const NameDict&) = delete; + ~NameDict(){ _dict_pool.dealloc(_keys, _capacity); } + NameDict(NameDict&&) = delete; NameDict& operator=(NameDict&&) = delete; - - uint32_t size() const { return _size; } + uint16_t size() const { return _size; } #define HASH_PROBE(key, ok, i) \ ok = false; \ @@ -118,22 +132,22 @@ namespace pkpy{ } const PyVar& operator[](StrName key) const { - bool ok; uint32_t i; + bool ok; uint16_t i; HASH_PROBE(key, ok, i); if(!ok) throw std::out_of_range("NameDict key not found: " + key.str()); - return _values[i]; + return value(i); } PyVar& get(StrName key){ - bool ok; uint32_t i; + bool ok; uint16_t i; HASH_PROBE(key, ok, i); if(!ok) throw std::out_of_range("NameDict key not found: " + key.str()); - return _values[i]; + return value(i); } template - void set(StrName key, T&& value){ - bool ok; uint32_t i; + void set(StrName key, T&& val){ + bool ok; uint16_t i; HASH_PROBE(key, ok, i); if(!ok) { _size++; @@ -143,25 +157,25 @@ namespace pkpy{ } _keys[i] = key; } - _values[i] = std::forward(value); + value(i) = std::forward(val); } void _rehash(bool resize){ StrName* old_keys = _keys; - PyVar* old_values = _values; - uint32_t old_capacity = _capacity; + PyVar* old_values = &value(0); + uint16_t old_capacity = _capacity; if(resize){ _capacity = find_next_capacity(_capacity * 2); _mask = _capacity - 1; } _alloc(_capacity); - for(uint32_t i=0; i> items() const { std::vector> v; - for(uint32_t i=0; i<_capacity; i++){ + for(uint16_t i=0; i<_capacity; i++){ if(_keys[i].empty()) continue; - v.push_back(std::make_pair(_keys[i], _values[i])); + v.push_back(std::make_pair(_keys[i], value(i))); } return v; } std::vector keys() const { std::vector v; - for(uint32_t i=0; i<_capacity; i++){ + for(uint16_t i=0; i<_capacity; i++){ if(_keys[i].empty()) continue; v.push_back(_keys[i]); } diff --git a/src/obj.h b/src/obj.h index 28b061df..8d90c25f 100644 --- a/src/obj.h +++ b/src/obj.h @@ -10,6 +10,7 @@ class VM; typedef std::function NativeFuncRaw; typedef pkpy::shared_ptr CodeObject_; +typedef pkpy::shared_ptr NameDict_; namespace pkpy{ struct NativeFunc { @@ -30,8 +31,8 @@ struct Function { std::vector kwargs_order; // runtime settings - PyVar _module; - pkpy::shared_ptr _closure; + PyVar _module = nullptr; + NameDict_ _closure = nullptr; bool has_name(const Str& val) const { bool _0 = std::find(args.begin(), args.end(), val) != args.end(); diff --git a/src/vm.h b/src/vm.h index 6bf5f375..5e96655d 100644 --- a/src/vm.h +++ b/src/vm.h @@ -159,7 +159,7 @@ public: return f(this, args); } else if(is_type(*callable, tp_function)){ const pkpy::Function& fn = PyFunction_AS_C(*callable); - auto locals = pkpy::make_shared( + NameDict_ locals = pkpy::make_shared( fn.code->perfect_locals_capacity, kLocalsLoadFactor, fn.code->perfect_hash_seed @@ -218,7 +218,7 @@ public: }catch (const pkpy::Exception& e){ *_stderr << e.summary() << '\n'; } -#ifdef _NDEBUG +#if !defined(__GNUC__) catch (const std::exception& e) { *_stderr << "An std::exception occurred! It could be a bug.\n"; *_stderr << e.what() << '\n';