diff --git a/src/compiler.h b/src/compiler.h index 050dd7d5..35cf07c9 100644 --- a/src/compiler.h +++ b/src/compiler.h @@ -55,6 +55,7 @@ class Compiler { } static void init_pratt_rules(){ + if(rules[TK(".")].precedence != PREC_NONE) return; // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/ #define METHOD(name) &Compiler::name #define NO_INFIX nullptr, PREC_NONE diff --git a/src/frame.h b/src/frame.h index aef2fd21..7b162f43 100644 --- a/src/frame.h +++ b/src/frame.h @@ -7,7 +7,7 @@ namespace pkpy{ static THREAD_LOCAL uint64_t kFrameGlobalId = 0; -using ValueStack = small_vector; +using ValueStack = pod_vector; struct Frame { ValueStack _data; diff --git a/src/lexer.h b/src/lexer.h index 3b5b762c..74c8f96b 100644 --- a/src/lexer.h +++ b/src/lexer.h @@ -100,7 +100,7 @@ struct Lexer { const char* curr_char; int current_line = 1; std::vector nexts; - small_stack indents; + stack indents; int brackets_level = 0; bool used = false; diff --git a/src/memory.h b/src/memory.h index 2fc53ba8..24d78f90 100644 --- a/src/memory.h +++ b/src/memory.h @@ -1,7 +1,6 @@ #pragma once #include "common.h" -#include "vector.h" namespace pkpy{ @@ -69,48 +68,12 @@ shared_ptr make_sp(Args&&... args) { return shared_ptr(p); } -template -struct FreeListA { - std::vector buckets[__Bucket+1]; - - T* alloc(int n){ - static_assert(std::is_standard_layout_v); - T* p; - if(n > __Bucket || buckets[n].empty()){ - p = (T*)malloc(sizeof(T) * n); - }else{ - p = buckets[n].back(); - buckets[n].pop_back(); - } - if constexpr(__ZeroInit){ - // the constructor of T should be equivalent to zero initialization - memset((void*)p, 0, sizeof(T) * n); - } - return p; - } - - void dealloc(T* p, int n){ - if(p == nullptr) return; - if(n > __Bucket || buckets[n].size() >= 80){ - free(p); - }else{ - buckets[n].push_back(p); - } - } - - ~FreeListA(){ - for(int i=0; i<=__Bucket; i++){ - for(T* p : buckets[i]) free(p); - } - } -}; - - struct LinkedListNode{ LinkedListNode* prev; LinkedListNode* next; }; + template struct DoubleLinkedList{ static_assert(std::is_base_of_v); @@ -295,6 +258,9 @@ struct MemoryPool{ } void dealloc(void* p){ +#if DEBUG_MEMORY_POOL + if(p == nullptr) throw std::runtime_error("MemoryPool::dealloc() called on nullptr"); +#endif Block* block = (Block*)((char*)p - sizeof(void*)); if(block->arena == nullptr){ free(block); @@ -328,4 +294,8 @@ struct MemoryPool{ } }; +inline MemoryPool<64> pool64; +inline MemoryPool<128> pool128; +inline MemoryPool<256> pool256; + }; // namespace pkpy diff --git a/src/namedict.h b/src/namedict.h index 0a8f085f..ba40eae6 100644 --- a/src/namedict.h +++ b/src/namedict.h @@ -34,8 +34,6 @@ inline static uint16_t find_perfect_hash_seed(uint16_t capacity, const std::vect struct NameDict { using Item = std::pair; - inline static THREAD_LOCAL FreeListA _pool; - uint16_t _capacity; uint16_t _size; float _load_factor; @@ -43,31 +41,36 @@ struct NameDict { uint16_t _mask; Item* _items; + void _alloc(int cap){ + _items = (Item*)pool128.alloc(cap * sizeof(Item)); + memset(_items, 0, cap * sizeof(Item)); + } + 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) { - _items = _pool.alloc(_capacity); + _alloc(capacity); } NameDict(const NameDict& other) { memcpy(this, &other, sizeof(NameDict)); - _items = _pool.alloc(_capacity); + _alloc(_capacity); for(int i=0; i<_capacity; i++){ _items[i] = other._items[i]; } } NameDict& operator=(const NameDict& other) { - _pool.dealloc(_items, _capacity); + pool128.dealloc(_items); memcpy(this, &other, sizeof(NameDict)); - _items = _pool.alloc(_capacity); + _alloc(_capacity); for(int i=0; i<_capacity; i++){ _items[i] = other._items[i]; } return *this; } - ~NameDict(){ _pool.dealloc(_items, _capacity); } + ~NameDict(){ pool128.dealloc(_items); } NameDict(NameDict&&) = delete; NameDict& operator=(NameDict&&) = delete; @@ -109,7 +112,7 @@ while(!_items[i].first.empty()) { \ _capacity = find_next_capacity(_capacity * 2); _mask = _capacity - 1; } - _items = _pool.alloc(_capacity); + _alloc(_capacity); for(uint16_t i=0; i + +namespace pkpy{ + +struct String{ + char* data; + int size; + + String(): data((char*)pool64.alloc(0)), size(0) {} + String(int size): data((char*)pool64.alloc(size)), size(size) {} + String(const char* str) { + size = strlen(str); + data = (char*)pool64.alloc(size); + memcpy(data, str, size); + } + + String(const String& other): data((char*)pool64.alloc(other.size)), size(other.size) { + memcpy(data, other.data, size); + } + + String(String&& other): data(other.data), size(other.size) { + other.data = nullptr; + } + + String& operator=(const String& other){ + if(data!=nullptr) pool64.dealloc(data); + size = other.size; + data = (char*)pool64.alloc(size); + memcpy(data, other.data, size); + return *this; + } + + String& operator=(String&& other){ + if(data!=nullptr) pool64.dealloc(data); + size = other.size; + data = other.data; + other.data = nullptr; + return *this; + } + + ~String(){ + if(data!=nullptr) pool64.dealloc(data); + } + + char operator[](int idx) const { + return data[idx]; + } + + int length() const { + return size; + } + + String operator+(const String& other) const { + String ret(size + other.size); + memcpy(ret.data, data, size); + memcpy(ret.data + size, other.data, other.size); + return ret; + } + + friend std::ostream& operator<<(std::ostream& os, const String& str){ + os.write(str.data, str.size); + return os; + } + + bool operator==(const String& other) const { + if(size != other.size) return false; + return memcmp(data, other.data, size) == 0; + } + + bool operator!=(const String& other) const { + if(size != other.size) return true; + return memcmp(data, other.data, size) != 0; + } + + bool operator<(const String& other) const { + int ret = strncmp(data, other.data, std::min(size, other.size)); + if(ret != 0) return ret < 0; + return size < other.size; + } + + bool operator>(const String& other) const { + int ret = strncmp(data, other.data, std::min(size, other.size)); + if(ret != 0) return ret > 0; + return size > other.size; + } + + bool operator<=(const String& other) const { + int ret = strncmp(data, other.data, std::min(size, other.size)); + if(ret != 0) return ret < 0; + return size <= other.size; + } + + bool operator>=(const String& other) const { + int ret = strncmp(data, other.data, std::min(size, other.size)); + if(ret != 0) return ret > 0; + return size >= other.size; + } + + String substr(int start, int len) const { + String ret(len); + memcpy(ret.data, data + start, len); + return ret; + } + + String substr(int start) const { + return substr(start, size - start); + } + + char* dup_c_str() const { + char* p = (char*)malloc(size + 1); + memcpy(p, data, size); + p[size] = 0; + return p; + } + + std::string_view view() const { + return std::string_view(data, size); + } + + std::string str() const { + return std::string(data, size); + } + + String lstrip() const { + std::string copy = str(); + copy.erase(copy.begin(), std::find_if(copy.begin(), copy.end(), [](char c) { + // std::isspace(c) does not working on windows (Debug) + return c != ' ' && c != '\t' && c != '\r' && c != '\n'; + })); + return String(copy.c_str()); + } +}; + +struct UnicodeString: String{ + +}; + + +} // namespace pkpy \ No newline at end of file diff --git a/src/tuplelist.h b/src/tuplelist.h index 9ec0c71b..0abc993f 100644 --- a/src/tuplelist.h +++ b/src/tuplelist.h @@ -3,19 +3,18 @@ #include "common.h" #include "memory.h" #include "str.h" +#include "vector.h" namespace pkpy { -using List = small_vector; +using List = pod_vector; class Args { - inline static THREAD_LOCAL FreeListA _pool; - PyObject** _args; int _size; void _alloc(int n){ - this->_args = (n==0) ? nullptr : _pool.alloc(n); + this->_args = (n==0) ? nullptr : (PyObject**)pool64.alloc(n * sizeof(void*)); this->_size = n; } @@ -48,7 +47,7 @@ public: PyObject* operator[](int i) const { return _args[i]; } Args& operator=(Args&& other) noexcept { - _pool.dealloc(_args, _size); + if(_args!=nullptr) pool64.dealloc(_args); this->_args = other._args; this->_size = other._size; other._args = nullptr; @@ -71,10 +70,10 @@ public: _alloc(old_size+1); _args[0] = self; for(int i=0; i -struct small_vector{ +template +struct pod_vector{ + static_assert(128 % sizeof(T) == 0); + static_assert(std::is_pod_v); + static constexpr int N = 128 / sizeof(T); + static_assert(N > 4); int _size; int _capacity; T* _data; - T _buffer[N]; - small_vector(): _size(0), _capacity(N) { - static_assert(std::is_pod_v); - _data = _buffer; + pod_vector(): _size(0), _capacity(N) { + _data = (T*)pool128.alloc(_capacity * sizeof(T)); } - small_vector(int size): _size(0), _capacity(N){ - _data = _buffer; - reserve(size); - _size = size; + pod_vector(int size): _size(size), _capacity(std::max(N, size)) { + _data = (T*)pool128.alloc(_capacity * sizeof(T)); } - small_vector(const small_vector& other): _size(other._size), _capacity(other._capacity) { - if(other.is_small()){ - _data = _buffer; - memcpy(_buffer, other._buffer, sizeof(T) * _size); - } else { - _data = (T*)malloc(sizeof(T) * _capacity); - memcpy(_data, other._data, sizeof(T) * _size); - } + pod_vector(const pod_vector& other): _size(other._size), _capacity(other._capacity) { + _data = (T*)pool128.alloc(_capacity * sizeof(T)); + memcpy(_data, other._data, sizeof(T) * _size); } - small_vector(small_vector&& other) noexcept { + pod_vector(pod_vector&& other) noexcept { _size = other._size; _capacity = other._capacity; - if(other.is_small()){ - _data = _buffer; - memcpy(_buffer, other._buffer, sizeof(T) * _size); - } else { - _data = other._data; - other._data = other._buffer; - } + _data = other._data; + other._data = nullptr; } - small_vector& operator=(small_vector&& other) noexcept { - if (!is_small()) free(_data); + pod_vector& operator=(pod_vector&& other) noexcept { + if(_data!=nullptr) pool128.dealloc(_data); _size = other._size; _capacity = other._capacity; - if(other.is_small()){ - _data = _buffer; - memcpy(_buffer, other._buffer, sizeof(T) * _size); - } else { - _data = other._data; - other._data = other._buffer; - } + _data = other._data; + other._data = nullptr; return *this; } // remove copy assignment - small_vector& operator=(const small_vector& other) = delete; + pod_vector& operator=(const pod_vector& other) = delete; template void push_back(__ValueT&& t) { @@ -70,16 +56,12 @@ struct small_vector{ void reserve(int cap){ if(cap < _capacity) return; _capacity = cap; - if (is_small()) { - _data = (T*)malloc(sizeof(T) * _capacity); - memcpy(_data, _buffer, sizeof(T) * _size); - } else { - _data = (T*)realloc(_data, sizeof(T) * _capacity); - } + if(_data!=nullptr) pool128.dealloc(_data); + _data = (T*)pool128.alloc(_capacity * sizeof(T)); } void pop_back() { _size--; } - void extend(const small_vector& other){ + void extend(const pod_vector& other){ for(int i=0; i -using small_stack = stack>; +template +using pod_stack = stack>; } // namespace pkpy \ No newline at end of file