From e69b66f0b78cd032f0e318ec6be3a6d02bcb574a Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Thu, 6 Apr 2023 14:51:18 +0800 Subject: [PATCH] impl `small_vector` --- amalgamate.py | 2 +- src/common.h | 16 -------- src/frame.h | 9 ++-- src/memory.h | 1 + src/vector.h | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 20 deletions(-) create mode 100644 src/vector.h diff --git a/amalgamate.py b/amalgamate.py index b5cd8fd5..99ef93fe 100644 --- a/amalgamate.py +++ b/amalgamate.py @@ -6,7 +6,7 @@ with open("src/opcodes.h", "rt", encoding='utf-8') as f: OPCODES_TEXT = f.read() pipeline = [ - ["common.h", "memory.h", "str.h", "tuplelist.h", "namedict.h", "error.h", "lexer.h"], + ["common.h", "vector.h", "memory.h", "str.h", "tuplelist.h", "namedict.h", "error.h", "lexer.h"], ["obj.h", "codeobject.h", "frame.h"], ["gc.h", "vm.h", "ceval.h", "expr.h", "compiler.h", "repl.h"], ["iter.h", "cffi.h", "io.h", "_generated.h", "pocketpy.h"] diff --git a/src/common.h b/src/common.h index 45caad03..b0175192 100644 --- a/src/common.h +++ b/src/common.h @@ -107,22 +107,6 @@ inline bool is_both_int(PyObject* a, PyObject* b) noexcept { return is_int(a) && is_int(b); } -template -class stack{ - std::vector vec; -public: - void push(const T& t){ vec.push_back(t); } - void push(T&& t){ vec.push_back(std::move(t)); } - void pop(){ vec.pop_back(); } - void clear(){ vec.clear(); } - bool empty() const { return vec.empty(); } - size_t size() const { return vec.size(); } - T& top(){ return vec.back(); } - const T& top() const { return vec.back(); } - T popx(){ T t = std::move(vec.back()); vec.pop_back(); return t; } - const std::vector& data() const { return vec; } -}; - struct Expr; typedef std::unique_ptr Expr_; diff --git a/src/frame.h b/src/frame.h index ebecb893..c0f1c285 100644 --- a/src/frame.h +++ b/src/frame.h @@ -1,13 +1,16 @@ #pragma once #include "codeobject.h" +#include "vector.h" namespace pkpy{ static THREAD_LOCAL uint64_t kFrameGlobalId = 0; +using ValueStack = small_vector; + struct Frame { - std::vector _data; + ValueStack _data; int _ip = -1; int _next_ip = 0; @@ -16,7 +19,7 @@ struct Frame { NameDict_ _locals; NameDict_ _closure; const uint64_t id; - std::vector>> s_try_block; + std::vector> s_try_block; const NameDict* names[5]; // name resolution array, zero terminated NameDict& f_locals() noexcept { return *_locals; } @@ -148,7 +151,7 @@ struct Frame { } void pop_n(int n){ - _data.resize(_data.size()-n); + _data.pop_back_n(n); } void _mark() const { diff --git a/src/memory.h b/src/memory.h index 62d9932f..e7559865 100644 --- a/src/memory.h +++ b/src/memory.h @@ -1,6 +1,7 @@ #pragma once #include "common.h" +#include "vector.h" namespace pkpy{ diff --git a/src/vector.h b/src/vector.h new file mode 100644 index 00000000..e4f05474 --- /dev/null +++ b/src/vector.h @@ -0,0 +1,112 @@ +#pragma once + +#include "common.h" + +namespace pkpy{ + +template +struct small_vector{ + int _size; + int _capacity; + T* _data; + T _buffer[N]; + + small_vector(): _size(0), _capacity(N) { + static_assert(std::is_pod_v); + _data = _buffer; + } + + 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); + } + } + + small_vector(small_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; + } + } + + small_vector& operator=(small_vector&& other) noexcept { + if (!is_small()) free(_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; + } + return *this; + } + + template + void push_back(__ValueT&& t) { + if (_size == _capacity) { + _capacity *= 2; + if (is_small()) { + _data = (T*)malloc(sizeof(T) * _capacity); + memcpy(_data, _buffer, sizeof(T) * _size); + } else { + _data = (T*)realloc(_data, sizeof(T) * _capacity); + } + } + _data[_size++] = std::forward<__ValueT>(t); + } + + void pop_back() { _size--; } + + T& operator[](int index) { return _data[index]; } + const T& operator[](int index) const { return _data[index]; } + + T* begin() { return _data; } + T* end() { return _data + _size; } + const T* begin() const { return _data; } + const T* end() const { return _data + _size; } + T& back() { return _data[_size - 1]; } + const T& back() const { return _data[_size - 1]; } + + bool empty() const { return _size == 0; } + int size() const { return _size; } + T* data() { return _data; } + const T* data() const { return _data; } + bool is_small() const { return _data == _buffer; } + void pop_back_n(int n) { _size -= n; } + + ~small_vector() { + if (!is_small()) free(_data); + } +}; + + +template > +class stack{ + Container vec; +public: + void push(const T& t){ vec.push_back(t); } + void push(T&& t){ vec.push_back(std::move(t)); } + void pop(){ vec.pop_back(); } + void clear(){ vec.clear(); } + bool empty() const { return vec.empty(); } + size_t size() const { return vec.size(); } + T& top(){ return vec.back(); } + const T& top() const { return vec.back(); } + T popx(){ T t = std::move(vec.back()); vec.pop_back(); return t; } + const Container& data() const { return vec; } +}; + +template +using small_stack = stack>; +} // namespace pkpy \ No newline at end of file