Przeglądaj źródła

impl `small_vector`

blueloveTH 2 lat temu
rodzic
commit
e69b66f0b7
5 zmienionych plików z 120 dodań i 20 usunięć
  1. 1 1
      amalgamate.py
  2. 0 16
      src/common.h
  3. 6 3
      src/frame.h
  4. 1 0
      src/memory.h
  5. 112 0
      src/vector.h

+ 1 - 1
amalgamate.py

@@ -6,7 +6,7 @@ with open("src/opcodes.h", "rt", encoding='utf-8') as f:
 	OPCODES_TEXT = f.read()
 	OPCODES_TEXT = f.read()
 
 
 pipeline = [
 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"],
 	["obj.h", "codeobject.h", "frame.h"],
 	["gc.h", "vm.h", "ceval.h", "expr.h", "compiler.h", "repl.h"],
 	["gc.h", "vm.h", "ceval.h", "expr.h", "compiler.h", "repl.h"],
 	["iter.h", "cffi.h", "io.h", "_generated.h", "pocketpy.h"]
 	["iter.h", "cffi.h", "io.h", "_generated.h", "pocketpy.h"]

+ 0 - 16
src/common.h

@@ -107,22 +107,6 @@ inline bool is_both_int(PyObject* a, PyObject* b) noexcept {
     return is_int(a) && is_int(b);
     return is_int(a) && is_int(b);
 }
 }
 
 
-template <typename T>
-class stack{
-	std::vector<T> 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<T>& data() const { return vec; }
-};
-
 struct Expr;
 struct Expr;
 typedef std::unique_ptr<Expr> Expr_;
 typedef std::unique_ptr<Expr> Expr_;
 
 

+ 6 - 3
src/frame.h

@@ -1,13 +1,16 @@
 #pragma once
 #pragma once
 
 
 #include "codeobject.h"
 #include "codeobject.h"
+#include "vector.h"
 
 
 namespace pkpy{
 namespace pkpy{
 
 
 static THREAD_LOCAL uint64_t kFrameGlobalId = 0;
 static THREAD_LOCAL uint64_t kFrameGlobalId = 0;
 
 
+using ValueStack = small_vector<PyObject*, 6>;
+
 struct Frame {
 struct Frame {
-    std::vector<PyObject*> _data;
+    ValueStack _data;
     int _ip = -1;
     int _ip = -1;
     int _next_ip = 0;
     int _next_ip = 0;
 
 
@@ -16,7 +19,7 @@ struct Frame {
     NameDict_ _locals;
     NameDict_ _locals;
     NameDict_ _closure;
     NameDict_ _closure;
     const uint64_t id;
     const uint64_t id;
-    std::vector<std::pair<int, std::vector<PyObject*>>> s_try_block;
+    std::vector<std::pair<int, ValueStack>> s_try_block;
     const NameDict* names[5];     // name resolution array, zero terminated
     const NameDict* names[5];     // name resolution array, zero terminated
 
 
     NameDict& f_locals() noexcept { return *_locals; }
     NameDict& f_locals() noexcept { return *_locals; }
@@ -148,7 +151,7 @@ struct Frame {
     }
     }
 
 
     void pop_n(int n){
     void pop_n(int n){
-        _data.resize(_data.size()-n);
+        _data.pop_back_n(n);
     }
     }
 
 
     void _mark() const {
     void _mark() const {

+ 1 - 0
src/memory.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 
 
 #include "common.h"
 #include "common.h"
+#include "vector.h"
 
 
 namespace pkpy{
 namespace pkpy{
 
 

+ 112 - 0
src/vector.h

@@ -0,0 +1,112 @@
+#pragma once
+
+#include "common.h"
+
+namespace pkpy{
+
+template<typename T, int N>
+struct small_vector{
+    int _size;
+    int _capacity;
+    T* _data;
+    T _buffer[N];
+
+    small_vector(): _size(0), _capacity(N) {
+        static_assert(std::is_pod_v<T>);
+        _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<typename __ValueT>
+    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 <typename T, typename Container=std::vector<T>>
+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 <typename T, int N=8>
+using small_stack = stack<T, small_vector<T, N>>;
+} // namespace pkpy