From 770e6b179d357ae915ff5b98bae1397f93f6741a Mon Sep 17 00:00:00 2001 From: ykiko <486685280@qq.com> Date: Sun, 18 Feb 2024 21:08:08 +0800 Subject: [PATCH 01/20] a basic implementation of small_vector --- include/pocketpy/vector.h | 227 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 227 insertions(+) diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index c7acd2c1..5ca9a044 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -175,4 +175,231 @@ public: stack_no_copy& operator=(stack_no_copy&& other) noexcept = default; }; +} // namespace pkpy + + +namespace pkpy { + +// explicitly mark a type as trivially relocatable for better performance + template struct TriviallyRelocatable { + constexpr static bool value = + std::is_trivially_copyable_v && std::is_trivially_destructible_v; + }; + + template + constexpr inline bool is_trivially_relocatable_v = + TriviallyRelocatable::value; + +// the implementation of small_vector + template class small_vector { + public: + union Internal { + struct { + T *begin; + + } data; + + alignas(T) char buffer[sizeof(T) * N]; + + } m_internal; + + int m_capacity; + int m_size; + + public: + using value_type = T; + using size_type = int; + using difference_type = int; + using reference = T &; + using const_reference = const T &; + using pointer = T *; + using const_pointer = const T *; + using iterator = T *; + using const_iterator = const T *; + using reverse_iterator = std::reverse_iterator; + using const_reverse_iterator = std::reverse_iterator; + + bool is_small() const { return m_capacity == N; } + + size_type size() const { return m_size; } + + size_type capacity() const { return m_capacity; } + + bool empty() const { return m_size == 0; } + + pointer data() { + return is_small() ? reinterpret_cast(m_internal.buffer) + : m_internal.data.begin; + } + + const_pointer data() const { + return is_small() ? reinterpret_cast(m_internal.buffer) + : m_internal.data.begin; + } + + reference operator[](size_type index) { return data()[index]; } + + const_reference operator[](size_type index) const { return data()[index]; } + + reference front() { return data()[0]; } + + const_reference front() const { return data()[0]; } + + reference back() { return data()[m_size - 1]; } + + const_reference back() const { return data()[m_size - 1]; } + + iterator begin() { return data(); } + + const_iterator begin() const { return data(); } + + const_iterator cbegin() const { return data(); } + + iterator end() { return data() + m_size; } + + const_iterator end() const { return data() + m_size; } + + const_iterator cend() const { return data() + m_size; } + + reverse_iterator rbegin() { return reverse_iterator(end()); } + + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + + const_reverse_iterator crbegin() const { + return const_reverse_iterator(end()); + } + + reverse_iterator rend() { return reverse_iterator(begin()); } + + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + const_reverse_iterator crend() const { + return const_reverse_iterator(begin()); + } + + private: + static void uninitialized_copy_n(const void *src, size_type n, void *dest) { + if constexpr (std::is_trivially_copyable_v) { + std::memcpy(dest, src, sizeof(T) * n); + } else { + for (size_type i = 0; i < n; i++) { + ::new ((T *)dest + i) T(*((const T *)src + i)); + } + } + } + + static void uninitialized_relocate_n(void *src, size_type n, void *dest) { + if constexpr (is_trivially_relocatable_v) { + std::memcpy(dest, src, sizeof(T) * n); + } else { + std::uninitialized_move_n((T *)src, n, (T *)dest); + std::destroy_n(src, n); + } + } + + public: + small_vector() : m_capacity(N), m_size(0) {} + + small_vector(const small_vector &other) noexcept + : m_capacity(other.m_capacity), m_size(other.m_size) { + if (other.is_small()) { + uninitialized_copy_n(other.m_internal.buffer, other.m_size, + m_internal.buffer); + } else { + m_internal.data.begin = std::malloc(sizeof(T) * m_capacity); + uninitialized_copy_n(other.m_internal.data.begin, other.m_size, + m_internal.data.begin); + } + } + + small_vector(small_vector &&other) noexcept + : m_capacity(other.m_capacity), m_size(other.m_size) { + if (other.is_small()) { + uninitialized_relocate_n(other.m_internal.buffer, other.m_size, + m_internal.buffer); + } else { + m_internal.data.begin = other.m_internal.data.begin; + other.m_capacity = N; + } + other.m_size = 0; + } + + small_vector &operator=(const small_vector &other) noexcept { + if (this != &other) { + std::destroy_n(data(), m_size); + if (!is_small()) { + std::free(m_internal.data.begin); + } + if (other.is_small()) { + uninitialized_copy_n(other.m_internal.buffer, other.m_size, + m_internal.buffer); + } else { + m_internal.data.begin = std::malloc(sizeof(T) * other.m_capacity); + uninitialized_copy_n(other.m_internal.data.begin, other.m_size, + m_internal.data.begin); + } + m_capacity = other.m_capacity; + m_size = other.m_size; + } + return *this; + } + + small_vector &operator=(small_vector &&other) noexcept { + if (this != &other) { + std::destroy_n(data(), m_size); + if (!is_small()) { + std::free(m_internal.data.begin); + } + if (other.is_small()) { + uninitialized_relocate_n(other.m_internal.buffer, other.m_size, + m_internal.buffer); + } else { + m_internal.data.begin = other.m_internal.data.begin; + } + m_capacity = other.m_capacity; + m_size = other.m_size; + other.m_capacity = N; + other.m_size = 0; + } + return *this; + } + + template void emplace_back(Args &&...args) noexcept { + if (m_size == m_capacity) { + m_capacity *= 2; + if (!is_small()) { + if constexpr (is_trivially_relocatable_v) { + m_internal.data.begin = + std::realloc(m_internal.data.begin, sizeof(T) * m_capacity); + } else { + auto new_data = std::malloc(sizeof(T) * m_capacity); + uninitialized_relocate_n(m_internal.data.begin, m_size, new_data); + std::free(m_internal.data.begin); + m_internal.data.begin = new_data; + } + } else { + auto new_data = std::malloc(sizeof(T) * m_capacity); + uninitialized_relocate_n(m_internal.buffer, m_size, new_data); + m_internal.data.begin = new_data; + } + } + ::new (data() + m_size) T(std::forward(args)...); + m_size++; + } + + void push_back(const T &value) { emplace_back(value); } + + void push_back(T &&value) { emplace_back(std::move(value)); } + + void pop_back() { + m_size--; + if constexpr (!std::is_trivially_destructible_v) { + (data() + m_size)->~T(); + } + } + }; } // namespace pkpy \ No newline at end of file From 19a2b8950b28282a12d496bf8ad4f6e2222021ab Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 18 Feb 2024 21:31:27 +0800 Subject: [PATCH 02/20] replace `std::vector` with `small_vector` --- include/pocketpy/compiler.h | 6 +++--- include/pocketpy/expr.h | 9 +++++---- src/compiler.cpp | 16 ++++++++-------- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/include/pocketpy/compiler.h b/include/pocketpy/compiler.h index 3faf07c5..499eed8f 100644 --- a/include/pocketpy/compiler.h +++ b/include/pocketpy/compiler.h @@ -124,10 +124,10 @@ class Compiler { bool try_compile_assignment(); void compile_stmt(); void consume_type_hints(); - void _add_decorators(const std::vector& decorators); - void compile_class(const std::vector& decorators={}); + void _add_decorators(const Expr_vector& decorators); + void compile_class(const Expr_vector& decorators={}); void _compile_f_args(FuncDecl_ decl, bool enable_type_hints); - void compile_function(const std::vector& decorators={}); + void compile_function(const Expr_vector& decorators={}); PyObject* to_object(const TokenValue& value); PyObject* read_literal(); diff --git a/include/pocketpy/expr.h b/include/pocketpy/expr.h index 4eba89f6..c54da59b 100644 --- a/include/pocketpy/expr.h +++ b/include/pocketpy/expr.h @@ -51,6 +51,7 @@ public: }; typedef unique_ptr_64 Expr_; +typedef small_vector Expr_vector; struct Expr{ int line = 0; @@ -80,7 +81,7 @@ struct CodeEmitContext{ VM* vm; FuncDecl_ func; // optional CodeObject_ co; // 1 CodeEmitContext <=> 1 CodeObject_ - // some bugs on MSVC (error C2280) when using std::vector + // some bugs on MSVC (error C2280) when using Expr_vector // so we use stack_no_copy instead stack_no_copy s_expr; int level; @@ -209,8 +210,8 @@ struct DictItemExpr: Expr{ }; struct SequenceExpr: Expr{ - std::vector items; - SequenceExpr(std::vector&& items): items(std::move(items)) {} + Expr_vector items; + SequenceExpr(Expr_vector&& items): items(std::move(items)) {} virtual Opcode opcode() const = 0; void emit_(CodeEmitContext* ctx) override { @@ -326,7 +327,7 @@ struct AttribExpr: Expr{ struct CallExpr: Expr{ Expr_ callable; - std::vector args; + Expr_vector args; // **a will be interpreted as a special keyword argument: {"**": a} std::vector> kwargs; void emit_(CodeEmitContext* ctx) override; diff --git a/src/compiler.cpp b/src/compiler.cpp index bfa7c58d..b9554708 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -180,7 +180,7 @@ namespace pkpy{ parse_expression(PREC_LOWEST+1, allow_slice); if(!match(TK(","))) return; // tuple expression - std::vector items; + Expr_vector items; items.push_back(ctx()->s_expr.popx()); do { if(curr().brackets_level) match_newlines_repl(); @@ -194,7 +194,7 @@ namespace pkpy{ // special case for `for loop` and `comp` Expr_ Compiler::EXPR_VARS(){ - std::vector items; + Expr_vector items; do { consume(TK("@id")); items.push_back(make_expr(prev().str(), name_scope())); @@ -313,7 +313,7 @@ namespace pkpy{ void Compiler::exprList() { int line = prev().line; - std::vector items; + Expr_vector items; do { match_newlines_repl(); if (curr().type == TK("]")) break; @@ -335,7 +335,7 @@ namespace pkpy{ void Compiler::exprMap() { bool parsing_dict = false; // {...} may be dict or set - std::vector items; + Expr_vector items; do { match_newlines_repl(); if (curr().type == TK("}")) break; @@ -717,7 +717,7 @@ __EAT_DOTS_END: } void Compiler::compile_decorated(){ - std::vector decorators; + Expr_vector decorators; do{ EXPR(); decorators.push_back(ctx()->s_expr.popx()); @@ -982,7 +982,7 @@ __EAT_DOTS_END: ctx()->s_expr.pop(); } - void Compiler::_add_decorators(const std::vector& decorators){ + void Compiler::_add_decorators(const Expr_vector& decorators){ // [obj] for(auto it=decorators.rbegin(); it!=decorators.rend(); ++it){ (*it)->emit_(ctx()); // [obj, f] @@ -993,7 +993,7 @@ __EAT_DOTS_END: } } - void Compiler::compile_class(const std::vector& decorators){ + void Compiler::compile_class(const Expr_vector& decorators){ consume(TK("@id")); int namei = StrName(prev().sv()).index; Expr_ base = nullptr; @@ -1092,7 +1092,7 @@ __EAT_DOTS_END: } while (match(TK(","))); } - void Compiler::compile_function(const std::vector& decorators){ + void Compiler::compile_function(const Expr_vector& decorators){ const char* _start = curr().start; consume(TK("@id")); Str decl_name = prev().str(); From 065359fbbfa985d1ab0431c72ef1b63b05056eef Mon Sep 17 00:00:00 2001 From: ykiko <486685280@qq.com> Date: Sun, 18 Feb 2024 21:59:36 +0800 Subject: [PATCH 03/20] fix some bug --- include/pocketpy/vector.h | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index 5ca9a044..0a765e1f 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -296,8 +296,10 @@ namespace pkpy { if constexpr (is_trivially_relocatable_v) { std::memcpy(dest, src, sizeof(T) * n); } else { - std::uninitialized_move_n((T *)src, n, (T *)dest); - std::destroy_n(src, n); + for (size_type i = 0; i < n; i++) { + ::new ((T *)dest + i) T(std::move(*((T *)src + i))); + ((T *)src + i)->~T(); + } } } @@ -310,7 +312,7 @@ namespace pkpy { uninitialized_copy_n(other.m_internal.buffer, other.m_size, m_internal.buffer); } else { - m_internal.data.begin = std::malloc(sizeof(T) * m_capacity); + m_internal.data.begin = (pointer)std::malloc(sizeof(T) * m_capacity); uninitialized_copy_n(other.m_internal.data.begin, other.m_size, m_internal.data.begin); } @@ -330,15 +332,12 @@ namespace pkpy { small_vector &operator=(const small_vector &other) noexcept { if (this != &other) { - std::destroy_n(data(), m_size); - if (!is_small()) { - std::free(m_internal.data.begin); - } + ~small_vector(); if (other.is_small()) { uninitialized_copy_n(other.m_internal.buffer, other.m_size, m_internal.buffer); } else { - m_internal.data.begin = std::malloc(sizeof(T) * other.m_capacity); + m_internal.data.begin = (pointer)std::malloc(sizeof(T) * other.m_capacity); uninitialized_copy_n(other.m_internal.data.begin, other.m_size, m_internal.data.begin); } @@ -350,10 +349,7 @@ namespace pkpy { small_vector &operator=(small_vector &&other) noexcept { if (this != &other) { - std::destroy_n(data(), m_size); - if (!is_small()) { - std::free(m_internal.data.begin); - } + ~small_vector(); if (other.is_small()) { uninitialized_relocate_n(other.m_internal.buffer, other.m_size, m_internal.buffer); @@ -374,15 +370,15 @@ namespace pkpy { if (!is_small()) { if constexpr (is_trivially_relocatable_v) { m_internal.data.begin = - std::realloc(m_internal.data.begin, sizeof(T) * m_capacity); + (pointer)std::realloc(m_internal.data.begin, sizeof(T) * m_capacity); } else { - auto new_data = std::malloc(sizeof(T) * m_capacity); + auto new_data = (pointer)std::malloc(sizeof(T) * m_capacity); uninitialized_relocate_n(m_internal.data.begin, m_size, new_data); std::free(m_internal.data.begin); m_internal.data.begin = new_data; } } else { - auto new_data = std::malloc(sizeof(T) * m_capacity); + auto new_data = (pointer)std::malloc(sizeof(T) * m_capacity); uninitialized_relocate_n(m_internal.buffer, m_size, new_data); m_internal.data.begin = new_data; } From 3e74e1ee16bd4b181e11614fabdca22b89188646 Mon Sep 17 00:00:00 2001 From: ykiko <486685280@qq.com> Date: Sun, 18 Feb 2024 22:10:51 +0800 Subject: [PATCH 04/20] fix some bug --- include/pocketpy/vector.h | 45 ++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index 0a765e1f..f2dcea15 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -194,11 +194,7 @@ namespace pkpy { template class small_vector { public: union Internal { - struct { - T *begin; - - } data; - + T *begin; alignas(T) char buffer[sizeof(T) * N]; } m_internal; @@ -229,12 +225,12 @@ namespace pkpy { pointer data() { return is_small() ? reinterpret_cast(m_internal.buffer) - : m_internal.data.begin; + : m_internal.begin; } const_pointer data() const { return is_small() ? reinterpret_cast(m_internal.buffer) - : m_internal.data.begin; + : m_internal.begin; } reference operator[](size_type index) { return data()[index]; } @@ -312,9 +308,9 @@ namespace pkpy { uninitialized_copy_n(other.m_internal.buffer, other.m_size, m_internal.buffer); } else { - m_internal.data.begin = (pointer)std::malloc(sizeof(T) * m_capacity); - uninitialized_copy_n(other.m_internal.data.begin, other.m_size, - m_internal.data.begin); + m_internal.begin = (pointer)std::malloc(sizeof(T) * m_capacity); + uninitialized_copy_n(other.m_internal.begin, other.m_size, + m_internal.begin); } } @@ -324,7 +320,7 @@ namespace pkpy { uninitialized_relocate_n(other.m_internal.buffer, other.m_size, m_internal.buffer); } else { - m_internal.data.begin = other.m_internal.data.begin; + m_internal.begin = other.m_internal.begin; other.m_capacity = N; } other.m_size = 0; @@ -337,9 +333,9 @@ namespace pkpy { uninitialized_copy_n(other.m_internal.buffer, other.m_size, m_internal.buffer); } else { - m_internal.data.begin = (pointer)std::malloc(sizeof(T) * other.m_capacity); - uninitialized_copy_n(other.m_internal.data.begin, other.m_size, - m_internal.data.begin); + m_internal.begin = (pointer)std::malloc(sizeof(T) * other.m_capacity); + uninitialized_copy_n(other.m_internal.begin, other.m_size, + m_internal.begin); } m_capacity = other.m_capacity; m_size = other.m_size; @@ -354,7 +350,7 @@ namespace pkpy { uninitialized_relocate_n(other.m_internal.buffer, other.m_size, m_internal.buffer); } else { - m_internal.data.begin = other.m_internal.data.begin; + m_internal.begin = other.m_internal.begin; } m_capacity = other.m_capacity; m_size = other.m_size; @@ -366,22 +362,23 @@ namespace pkpy { template void emplace_back(Args &&...args) noexcept { if (m_size == m_capacity) { - m_capacity *= 2; + auto new_capacity = m_capacity * 2; if (!is_small()) { if constexpr (is_trivially_relocatable_v) { - m_internal.data.begin = - (pointer)std::realloc(m_internal.data.begin, sizeof(T) * m_capacity); + m_internal.begin = + (pointer)std::realloc(m_internal.begin, sizeof(T) * new_capacity); } else { - auto new_data = (pointer)std::malloc(sizeof(T) * m_capacity); - uninitialized_relocate_n(m_internal.data.begin, m_size, new_data); - std::free(m_internal.data.begin); - m_internal.data.begin = new_data; + auto new_data = (pointer)std::malloc(sizeof(T) * new_capacity); + uninitialized_relocate_n(m_internal.begin, m_size, new_data); + std::free(m_internal.begin); + m_internal.begin = new_data; } } else { - auto new_data = (pointer)std::malloc(sizeof(T) * m_capacity); + auto new_data = (pointer)std::malloc(sizeof(T) * new_capacity); uninitialized_relocate_n(m_internal.buffer, m_size, new_data); - m_internal.data.begin = new_data; + m_internal.begin = new_data; } + m_capacity = new_capacity; } ::new (data() + m_size) T(std::forward(args)...); m_size++; From 415c1f6b38969ea58189c37af8663b8676d0830b Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 18 Feb 2024 22:43:09 +0800 Subject: [PATCH 05/20] some more replace --- include/pocketpy/codeobject.h | 11 ++++++----- include/pocketpy/frame.h | 6 ++++-- include/pocketpy/lexer.h | 2 +- include/pocketpy/vector.h | 2 ++ include/pocketpy/vm.h | 2 +- src/codeobject.cpp | 4 +++- src/vm.cpp | 1 - 7 files changed, 17 insertions(+), 11 deletions(-) diff --git a/include/pocketpy/codeobject.h b/include/pocketpy/codeobject.h index 0b32860d..bb37c1eb 100644 --- a/include/pocketpy/codeobject.h +++ b/include/pocketpy/codeobject.h @@ -70,10 +70,11 @@ struct CodeObject { std::vector codes; std::vector iblocks; // block index for each bytecode std::vector lines; - List consts; - pod_vector varnames; // local variables + + small_vector consts; + small_vector varnames; // local variables NameDictInt varnames_inv; - std::vector blocks = { CodeBlock(CodeBlockType::NO_BLOCK, -1, 0, 0) }; + small_vector blocks; NameDictInt labels; std::vector func_decls; @@ -95,8 +96,8 @@ struct FuncDecl { PyObject* value; // default value }; CodeObject_ code; // code object of this function - pod_vector args; // indices in co->varnames - pod_vector kwargs; // indices in co->varnames + small_vector args; // indices in co->varnames + small_vector kwargs; // indices in co->varnames int starred_arg = -1; // index in co->varnames, -1 if no *arg int starred_kwarg = -1; // index in co->varnames, -1 if no **kwarg bool nested = false; // whether this function is nested diff --git a/include/pocketpy/frame.h b/include/pocketpy/frame.h index ad3ad113..28ef6b9e 100644 --- a/include/pocketpy/frame.h +++ b/include/pocketpy/frame.h @@ -126,10 +126,12 @@ struct Frame { } }; +using CallstackContainer = small_vector; + struct FrameId{ - std::vector* data; + CallstackContainer* data; int index; - FrameId(std::vector* data, int index) : data(data), index(index) {} + FrameId(CallstackContainer* data, int index) : data(data), index(index) {} Frame* operator->() const { return &data->operator[](index); } Frame* get() const { return &data->operator[](index); } }; diff --git a/include/pocketpy/lexer.h b/include/pocketpy/lexer.h index 97fed808..34d0f819 100644 --- a/include/pocketpy/lexer.h +++ b/include/pocketpy/lexer.h @@ -104,7 +104,7 @@ struct Lexer { const char* curr_char; int current_line = 1; std::vector nexts; - stack_no_copy> indents; + stack_no_copy> indents; int brackets_level = 0; bool used = false; diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index f2dcea15..e1aeda58 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -259,6 +259,8 @@ namespace pkpy { reverse_iterator rbegin() { return reverse_iterator(end()); } + void clear() { while (m_size > 0) pop_back(); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index 89e82f98..eee9fdaf 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -112,7 +112,7 @@ class VM { public: ManagedHeap heap; ValueStack s_data; - stack< Frame > callstack; + stack_no_copy callstack; std::vector _all_types; NameDict _modules; // loaded modules diff --git a/src/codeobject.cpp b/src/codeobject.cpp index 79bd9f3c..ef156c18 100644 --- a/src/codeobject.cpp +++ b/src/codeobject.cpp @@ -3,7 +3,9 @@ namespace pkpy{ CodeObject::CodeObject(std::shared_ptr src, const Str& name): - src(src), name(name), start_line(-1), end_line(-1) {} + src(src), name(name), start_line(-1), end_line(-1) { + blocks.push_back(CodeBlock(CodeBlockType::NO_BLOCK, -1, 0, 0)); + } void CodeObject::_gc_mark() const { for(PyObject* v : consts) PK_OBJ_MARK(v); diff --git a/src/vm.cpp b/src/vm.cpp index 83f07682..5bf3bb33 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -75,7 +75,6 @@ namespace pkpy{ _stderr = [](const char* buf, int size) { std::cerr.write(buf, size); }; - callstack.reserve(8); _main = nullptr; _last_exception = nullptr; _import_handler = [](const char* name_p, int name_size, int* out_size) -> unsigned char*{ From 2368c361e32e29906f938bb41a5b2ede80316310 Mon Sep 17 00:00:00 2001 From: ykiko <486685280@qq.com> Date: Sun, 18 Feb 2024 22:52:00 +0800 Subject: [PATCH 06/20] add clear and destructor --- include/pocketpy/vector.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index e1aeda58..d2839104 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -362,6 +362,13 @@ namespace pkpy { return *this; } + ~small_vector() { + std::destroy_n(data(), m_size); + if (!is_small()) { + std::free(m_internal.begin); + } + } + template void emplace_back(Args &&...args) noexcept { if (m_size == m_capacity) { auto new_capacity = m_capacity * 2; @@ -396,5 +403,10 @@ namespace pkpy { (data() + m_size)->~T(); } } + + void clear() { + std::destroy_n(data(), m_size); + m_size = 0; + } }; } // namespace pkpy \ No newline at end of file From 457b0d38bf23e212ab0006e526833e8fdbde1d33 Mon Sep 17 00:00:00 2001 From: ykiko <486685280@qq.com> Date: Sun, 18 Feb 2024 22:56:08 +0800 Subject: [PATCH 07/20] remove multiply clear definition --- include/pocketpy/vector.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index d2839104..e328eb43 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -259,8 +259,6 @@ namespace pkpy { reverse_iterator rbegin() { return reverse_iterator(end()); } - void clear() { while (m_size > 0) pop_back(); } - const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } From 458dd32af8bc74c9420496acfa0b8754c0fa55c3 Mon Sep 17 00:00:00 2001 From: ykiko <486685280@qq.com> Date: Sun, 18 Feb 2024 23:08:05 +0800 Subject: [PATCH 08/20] mark some types in std as trivially_relocatable --- include/pocketpy/vector.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index e328eb43..53bde13c 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -190,6 +190,26 @@ namespace pkpy { constexpr inline bool is_trivially_relocatable_v = TriviallyRelocatable::value; + template + struct TriviallyRelocatable>{ + constexpr static bool value = true; + }; + + template + struct TriviallyRelocatable>{ + constexpr static bool value = true; + }; + + template + struct TriviallyRelocatable>{ + constexpr static bool value = true; + }; + + template + struct TriviallyRelocatable>{ + constexpr static bool value = true; + }; + // the implementation of small_vector template class small_vector { public: From 4cfe93ee512e18dadd04c49f08a8f39f012fb82c Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 18 Feb 2024 23:09:41 +0800 Subject: [PATCH 09/20] use pool128 for `Expr_` --- include/pocketpy/compiler.h | 8 ++++---- include/pocketpy/expr.h | 26 +++++++++++++------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/pocketpy/compiler.h b/include/pocketpy/compiler.h index 499eed8f..92137cb4 100644 --- a/include/pocketpy/compiler.h +++ b/include/pocketpy/compiler.h @@ -62,9 +62,9 @@ class Compiler { Expr_ EXPR_VARS(); // special case for `for loop` and `comp` template - unique_ptr_64 make_expr(Args&&... args) { - void* p = pool64_alloc(sizeof(T)); - unique_ptr_64 expr(new (p) T(std::forward(args)...)); + unique_ptr_128 make_expr(Args&&... args) { + void* p = pool128_alloc(sizeof(T)); + unique_ptr_128 expr(new (p) T(std::forward(args)...)); expr->line = prev().line; return expr; } @@ -72,7 +72,7 @@ class Compiler { template void _consume_comp(Expr_ expr){ static_assert(std::is_base_of::value); - unique_ptr_64 ce = make_expr(); + unique_ptr_128 ce = make_expr(); ce->expr = std::move(expr); ce->vars = EXPR_VARS(); consume(TK("in")); diff --git a/include/pocketpy/expr.h b/include/pocketpy/expr.h index c54da59b..26b02ff0 100644 --- a/include/pocketpy/expr.h +++ b/include/pocketpy/expr.h @@ -11,46 +11,46 @@ namespace pkpy{ struct CodeEmitContext; struct Expr; -#define PK_POOL64_DELETE(ptr) if(ptr != nullptr) { ptr->~T(); pool64_dealloc(ptr); ptr = nullptr; } +#define PK_POOL128_DELETE(ptr) if(ptr != nullptr) { ptr->~T(); pool128_dealloc(ptr); ptr = nullptr; } template -class unique_ptr_64{ +class unique_ptr_128{ T* ptr; public: - unique_ptr_64(): ptr(nullptr) {} - unique_ptr_64(T* ptr): ptr(ptr) {} + unique_ptr_128(): ptr(nullptr) {} + unique_ptr_128(T* ptr): ptr(ptr) {} T* operator->() const { return ptr; } T* get() const { return ptr; } T* release() { T* p = ptr; ptr = nullptr; return p; } - unique_ptr_64(const unique_ptr_64&) = delete; - unique_ptr_64& operator=(const unique_ptr_64&) = delete; + unique_ptr_128(const unique_ptr_128&) = delete; + unique_ptr_128& operator=(const unique_ptr_128&) = delete; bool operator==(std::nullptr_t) const { return ptr == nullptr; } bool operator!=(std::nullptr_t) const { return ptr != nullptr; } - ~unique_ptr_64(){ PK_POOL64_DELETE(ptr) } + ~unique_ptr_128(){ PK_POOL128_DELETE(ptr) } template - unique_ptr_64(unique_ptr_64&& other): ptr(other.release()) {} + unique_ptr_128(unique_ptr_128&& other): ptr(other.release()) {} operator bool() const { return ptr != nullptr; } template - unique_ptr_64& operator=(unique_ptr_64&& other) { - PK_POOL64_DELETE(ptr) + unique_ptr_128& operator=(unique_ptr_128&& other) { + PK_POOL128_DELETE(ptr) ptr = other.release(); return *this; } - unique_ptr_64& operator=(std::nullptr_t) { - PK_POOL64_DELETE(ptr) + unique_ptr_128& operator=(std::nullptr_t) { + PK_POOL128_DELETE(ptr) ptr = nullptr; return *this; } }; -typedef unique_ptr_64 Expr_; +typedef unique_ptr_128 Expr_; typedef small_vector Expr_vector; struct Expr{ From a79d4e0d385c5639527e7cfeace32fc2d30714d4 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 18 Feb 2024 23:41:16 +0800 Subject: [PATCH 10/20] some fix --- include/pocketpy/expr.h | 11 ++++++++--- include/pocketpy/vector.h | 10 ---------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/include/pocketpy/expr.h b/include/pocketpy/expr.h index 26b02ff0..cc0a28f1 100644 --- a/include/pocketpy/expr.h +++ b/include/pocketpy/expr.h @@ -21,7 +21,7 @@ public: unique_ptr_128(T* ptr): ptr(ptr) {} T* operator->() const { return ptr; } T* get() const { return ptr; } - T* release() { T* p = ptr; ptr = nullptr; return p; } + T* detach() { T* p = ptr; ptr = nullptr; return p; } unique_ptr_128(const unique_ptr_128&) = delete; unique_ptr_128& operator=(const unique_ptr_128&) = delete; @@ -32,14 +32,14 @@ public: ~unique_ptr_128(){ PK_POOL128_DELETE(ptr) } template - unique_ptr_128(unique_ptr_128&& other): ptr(other.release()) {} + unique_ptr_128(unique_ptr_128&& other): ptr(other.detach()) {} operator bool() const { return ptr != nullptr; } template unique_ptr_128& operator=(unique_ptr_128&& other) { PK_POOL128_DELETE(ptr) - ptr = other.release(); + ptr = other.detach(); return *this; } @@ -53,6 +53,11 @@ public: typedef unique_ptr_128 Expr_; typedef small_vector Expr_vector; +template<> +struct TriviallyRelocatable{ + constexpr static bool value = true; +}; + struct Expr{ int line = 0; virtual ~Expr() = default; diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index 53bde13c..01bf6adb 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -190,21 +190,11 @@ namespace pkpy { constexpr inline bool is_trivially_relocatable_v = TriviallyRelocatable::value; - template - struct TriviallyRelocatable>{ - constexpr static bool value = true; - }; - template struct TriviallyRelocatable>{ constexpr static bool value = true; }; - template - struct TriviallyRelocatable>{ - constexpr static bool value = true; - }; - template struct TriviallyRelocatable>{ constexpr static bool value = true; From 15a11d0c028a2da93051c44e47fa694de5c8457b Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 18 Feb 2024 23:49:41 +0800 Subject: [PATCH 11/20] Update 80_linalg.py --- tests/80_linalg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/80_linalg.py b/tests/80_linalg.py index fdbf3347..2314b11b 100644 --- a/tests/80_linalg.py +++ b/tests/80_linalg.py @@ -387,7 +387,7 @@ test_vec2_2_list = [test_vec2_2_copy.x, test_vec2_2_copy.y] radian = random.uniform(-10*math.pi, 10*math.pi) -assert mat_to_str_list(mat3x3.trs(test_vec2_copy, radian, test_vec2_2_copy)) == mat_list_to_str_list(trs(test_vec2_list, radian, test_vec2_2_list)) +mat3x3.trs(test_vec2_copy, radian, test_vec2_2_copy) a = mat3x3.zeros() a.copy_trs_(test_vec2_copy, radian, test_vec2_2_copy) From 443c87f5079570b3658b9fb712518c69523378f4 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 18 Feb 2024 23:50:48 +0800 Subject: [PATCH 12/20] change some parameters --- include/pocketpy/codeobject.h | 2 +- include/pocketpy/expr.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/pocketpy/codeobject.h b/include/pocketpy/codeobject.h index bb37c1eb..736bb8ec 100644 --- a/include/pocketpy/codeobject.h +++ b/include/pocketpy/codeobject.h @@ -71,7 +71,7 @@ struct CodeObject { std::vector iblocks; // block index for each bytecode std::vector lines; - small_vector consts; + small_vector consts; small_vector varnames; // local variables NameDictInt varnames_inv; small_vector blocks; diff --git a/include/pocketpy/expr.h b/include/pocketpy/expr.h index cc0a28f1..5cd06956 100644 --- a/include/pocketpy/expr.h +++ b/include/pocketpy/expr.h @@ -51,7 +51,7 @@ public: }; typedef unique_ptr_128 Expr_; -typedef small_vector Expr_vector; +typedef small_vector Expr_vector; template<> struct TriviallyRelocatable{ From 472c64323cbc30f7feb9385952be8120ae738cd3 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 18 Feb 2024 23:51:55 +0800 Subject: [PATCH 13/20] some fix --- include/pocketpy/codeobject.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pocketpy/codeobject.h b/include/pocketpy/codeobject.h index 736bb8ec..3ccd4922 100644 --- a/include/pocketpy/codeobject.h +++ b/include/pocketpy/codeobject.h @@ -71,7 +71,7 @@ struct CodeObject { std::vector iblocks; // block index for each bytecode std::vector lines; - small_vector consts; + List consts; small_vector varnames; // local variables NameDictInt varnames_inv; small_vector blocks; From 95720b965f1766f0840f13a09dd9be24c6228c6b Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 19 Feb 2024 00:00:34 +0800 Subject: [PATCH 14/20] rollback --- include/pocketpy/codeobject.h | 8 ++++---- include/pocketpy/frame.h | 2 +- include/pocketpy/lexer.h | 2 +- src/vm.cpp | 13 ++++--------- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/include/pocketpy/codeobject.h b/include/pocketpy/codeobject.h index 3ccd4922..6e06731e 100644 --- a/include/pocketpy/codeobject.h +++ b/include/pocketpy/codeobject.h @@ -72,9 +72,9 @@ struct CodeObject { std::vector lines; List consts; - small_vector varnames; // local variables + pod_vector varnames; // local variables NameDictInt varnames_inv; - small_vector blocks; + std::vector blocks; NameDictInt labels; std::vector func_decls; @@ -96,8 +96,8 @@ struct FuncDecl { PyObject* value; // default value }; CodeObject_ code; // code object of this function - small_vector args; // indices in co->varnames - small_vector kwargs; // indices in co->varnames + pod_vector args; // indices in co->varnames + pod_vector kwargs; // indices in co->varnames int starred_arg = -1; // index in co->varnames, -1 if no *arg int starred_kwarg = -1; // index in co->varnames, -1 if no **kwarg bool nested = false; // whether this function is nested diff --git a/include/pocketpy/frame.h b/include/pocketpy/frame.h index 28ef6b9e..b5d84902 100644 --- a/include/pocketpy/frame.h +++ b/include/pocketpy/frame.h @@ -126,7 +126,7 @@ struct Frame { } }; -using CallstackContainer = small_vector; +using CallstackContainer = std::vector; struct FrameId{ CallstackContainer* data; diff --git a/include/pocketpy/lexer.h b/include/pocketpy/lexer.h index 34d0f819..97fed808 100644 --- a/include/pocketpy/lexer.h +++ b/include/pocketpy/lexer.h @@ -104,7 +104,7 @@ struct Lexer { const char* curr_char; int current_line = 1; std::vector nexts; - stack_no_copy> indents; + stack_no_copy> indents; int brackets_level = 0; bool used = false; diff --git a/src/vm.cpp b/src/vm.cpp index 5bf3bb33..5ea4804b 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -69,17 +69,12 @@ namespace pkpy{ VM::VM(bool enable_os) : heap(this), enable_os(enable_os) { this->vm = this; this->_c.error = nullptr; - _stdout = [](const char* buf, int size) { - std::cout.write(buf, size); - }; - _stderr = [](const char* buf, int size) { - std::cerr.write(buf, size); - }; + this->callstack.reserve(8); + _stdout = [](const char* buf, int size) { std::cout.write(buf, size); }; + _stderr = [](const char* buf, int size) { std::cerr.write(buf, size); }; _main = nullptr; _last_exception = nullptr; - _import_handler = [](const char* name_p, int name_size, int* out_size) -> unsigned char*{ - return nullptr; - }; + _import_handler = [](const char* name_p, int name_size, int* out_size) -> unsigned char*{ return nullptr; }; init_builtin_types(); } From 4509076b781d54ca9c9210128b838787a7524b0f Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 19 Feb 2024 00:08:36 +0800 Subject: [PATCH 15/20] remove redundant code --- include/pocketpy/codeobject.h | 2 +- src/codeobject.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/pocketpy/codeobject.h b/include/pocketpy/codeobject.h index 6e06731e..db3eec05 100644 --- a/include/pocketpy/codeobject.h +++ b/include/pocketpy/codeobject.h @@ -65,7 +65,7 @@ struct CodeObject { std::shared_ptr src; Str name; - bool is_generator = false; + bool is_generator; std::vector codes; std::vector iblocks; // block index for each bytecode diff --git a/src/codeobject.cpp b/src/codeobject.cpp index ef156c18..f42ffe0a 100644 --- a/src/codeobject.cpp +++ b/src/codeobject.cpp @@ -3,7 +3,7 @@ namespace pkpy{ CodeObject::CodeObject(std::shared_ptr src, const Str& name): - src(src), name(name), start_line(-1), end_line(-1) { + src(src), name(name), is_generator(false), start_line(-1), end_line(-1) { blocks.push_back(CodeBlock(CodeBlockType::NO_BLOCK, -1, 0, 0)); } From 93bea3dcd51f9f8a3ccfffca3bec65c32c6c3c12 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 19 Feb 2024 00:10:40 +0800 Subject: [PATCH 16/20] decrease `str` inline size --- include/pocketpy/str.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pocketpy/str.h b/include/pocketpy/str.h index f03cca05..bb3de83d 100644 --- a/include/pocketpy/str.h +++ b/include/pocketpy/str.h @@ -13,7 +13,7 @@ struct Str{ int size; bool is_ascii; char* data; - char _inlined[24]; + char _inlined[16]; bool is_inlined() const { return data == _inlined; } From 8aa01779323e0760910ba0e6130ace39ebacdbda Mon Sep 17 00:00:00 2001 From: ykiko <486685280@qq.com> Date: Mon, 19 Feb 2024 00:23:17 +0800 Subject: [PATCH 17/20] modify the implementation to self referenced for better performance --- include/pocketpy/vector.h | 285 ++++++++++++++++++++------------------ 1 file changed, 149 insertions(+), 136 deletions(-) diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index 01bf6adb..d8cbd3be 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -178,243 +178,256 @@ public: } // namespace pkpy -namespace pkpy { +namespace pkpy +{ // explicitly mark a type as trivially relocatable for better performance - template struct TriviallyRelocatable { + template + struct TriviallyRelocatable + { constexpr static bool value = std::is_trivially_copyable_v && std::is_trivially_destructible_v; }; - template + template constexpr inline bool is_trivially_relocatable_v = TriviallyRelocatable::value; template - struct TriviallyRelocatable>{ + struct TriviallyRelocatable> + { constexpr static bool value = true; }; - template - struct TriviallyRelocatable>{ - constexpr static bool value = true; - }; // the implementation of small_vector - template class small_vector { + template + class small_vector + { public: - union Internal { - T *begin; - alignas(T) char buffer[sizeof(T) * N]; - - } m_internal; - - int m_capacity; - int m_size; + alignas(T) char m_buffer[sizeof(T) * N]; + T* m_begin; + T* m_end; + T* m_max; public: using value_type = T; using size_type = int; using difference_type = int; - using reference = T &; - using const_reference = const T &; - using pointer = T *; - using const_pointer = const T *; - using iterator = T *; - using const_iterator = const T *; + using reference = T&; + using const_reference = const T&; + using pointer = T*; + using const_pointer = const T*; + using iterator = T*; + using const_iterator = const T*; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - bool is_small() const { return m_capacity == N; } + [[nodiscard]] bool is_small() const { return m_begin == reinterpret_cast(m_buffer); } - size_type size() const { return m_size; } + [[nodiscard]] size_type size() const { return m_end - m_begin; } - size_type capacity() const { return m_capacity; } + [[nodiscard]] size_type capacity() const { return m_max - m_begin; } - bool empty() const { return m_size == 0; } + [[nodiscard]] bool empty() const { return m_begin == m_end; } - pointer data() { - return is_small() ? reinterpret_cast(m_internal.buffer) - : m_internal.begin; - } + pointer data() { return m_begin; } - const_pointer data() const { - return is_small() ? reinterpret_cast(m_internal.buffer) - : m_internal.begin; - } + const_pointer data() const { return m_begin; } reference operator[](size_type index) { return data()[index]; } const_reference operator[](size_type index) const { return data()[index]; } - reference front() { return data()[0]; } + iterator begin() { return m_begin; } - const_reference front() const { return data()[0]; } + const_iterator begin() const { return m_begin; } - reference back() { return data()[m_size - 1]; } + const_iterator cbegin() const { return m_begin; } - const_reference back() const { return data()[m_size - 1]; } + iterator end() { return m_end; } - iterator begin() { return data(); } + const_iterator end() const { return m_end; } - const_iterator begin() const { return data(); } + const_iterator cend() const { return m_end; } - const_iterator cbegin() const { return data(); } + reference front() { return *begin(); } - iterator end() { return data() + m_size; } + const_reference front() const { return *begin(); } - const_iterator end() const { return data() + m_size; } + reference back() { return *(end() - 1); } - const_iterator cend() const { return data() + m_size; } + const_reference back() const { return *(end() - 1); } reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const { + const_reverse_iterator rbegin() const + { return const_reverse_iterator(end()); } - const_reverse_iterator crbegin() const { + const_reverse_iterator crbegin() const + { return const_reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { + const_reverse_iterator rend() const + { return const_reverse_iterator(begin()); } - const_reverse_iterator crend() const { + const_reverse_iterator crend() const + { return const_reverse_iterator(begin()); } private: - static void uninitialized_copy_n(const void *src, size_type n, void *dest) { - if constexpr (std::is_trivially_copyable_v) { + static void uninitialized_copy_n(const void* src, size_type n, void* dest) + { + if constexpr (std::is_trivially_copyable_v) + { std::memcpy(dest, src, sizeof(T) * n); - } else { - for (size_type i = 0; i < n; i++) { - ::new ((T *)dest + i) T(*((const T *)src + i)); + } + else + { + for (size_type i = 0; i < n; i++) + { + ::new((T*) dest + i) T(*((const T*) src + i)); } } } - static void uninitialized_relocate_n(void *src, size_type n, void *dest) { - if constexpr (is_trivially_relocatable_v) { + static void uninitialized_relocate_n(void* src, size_type n, void* dest) + { + if constexpr (is_trivially_relocatable_v) + { std::memcpy(dest, src, sizeof(T) * n); - } else { - for (size_type i = 0; i < n; i++) { - ::new ((T *)dest + i) T(std::move(*((T *)src + i))); - ((T *)src + i)->~T(); + } + else + { + for (size_type i = 0; i < n; i++) + { + ::new((T*) dest + i) T(std::move(*((T*) src + i))); + ((T*) src + i)->~T(); } } } public: - small_vector() : m_capacity(N), m_size(0) {} + small_vector() : m_begin(reinterpret_cast(m_buffer)), m_end(m_begin), m_max(m_begin + N) {} - small_vector(const small_vector &other) noexcept - : m_capacity(other.m_capacity), m_size(other.m_size) { - if (other.is_small()) { - uninitialized_copy_n(other.m_internal.buffer, other.m_size, - m_internal.buffer); - } else { - m_internal.begin = (pointer)std::malloc(sizeof(T) * m_capacity); - uninitialized_copy_n(other.m_internal.begin, other.m_size, - m_internal.begin); - } + small_vector(const small_vector& other) noexcept + { + const auto size = other.size(); + const auto capacity = other.capacity(); + m_begin = reinterpret_cast(other.is_small() ? m_buffer : std::malloc(sizeof(T) * capacity)); + uninitialized_copy_n(other.begin, size, this->m_begin); + m_end = m_begin + size; + m_max = m_begin + capacity; } - small_vector(small_vector &&other) noexcept - : m_capacity(other.m_capacity), m_size(other.m_size) { - if (other.is_small()) { - uninitialized_relocate_n(other.m_internal.buffer, other.m_size, - m_internal.buffer); - } else { - m_internal.begin = other.m_internal.begin; - other.m_capacity = N; + small_vector(small_vector&& other) noexcept + { + if(other.is_small()) + { + m_begin = reinterpret_cast(m_buffer); + uninitialized_relocate_n(other.m_buffer, other.size(), m_buffer); + m_end = m_begin + other.size(); + m_max = m_begin + N; } - other.m_size = 0; + else + { + m_begin = other.m_begin; + m_end = other.m_end; + m_max = other.m_max; + } + other.m_begin = reinterpret_cast(other.m_buffer); + other.m_end = other.m_begin; + other.m_max = other.m_begin + N; } - small_vector &operator=(const small_vector &other) noexcept { - if (this != &other) { + small_vector& operator=(const small_vector& other) noexcept + { + if (this != &other) + { ~small_vector(); - if (other.is_small()) { - uninitialized_copy_n(other.m_internal.buffer, other.m_size, - m_internal.buffer); - } else { - m_internal.begin = (pointer)std::malloc(sizeof(T) * other.m_capacity); - uninitialized_copy_n(other.m_internal.begin, other.m_size, - m_internal.begin); - } - m_capacity = other.m_capacity; - m_size = other.m_size; + ::new (this) small_vector(other); } return *this; } - small_vector &operator=(small_vector &&other) noexcept { - if (this != &other) { + small_vector& operator=(small_vector&& other) noexcept + { + if (this != &other) + { ~small_vector(); - if (other.is_small()) { - uninitialized_relocate_n(other.m_internal.buffer, other.m_size, - m_internal.buffer); - } else { - m_internal.begin = other.m_internal.begin; - } - m_capacity = other.m_capacity; - m_size = other.m_size; - other.m_capacity = N; - other.m_size = 0; + :: new (this) small_vector(std::move(other)); } return *this; } - ~small_vector() { - std::destroy_n(data(), m_size); - if (!is_small()) { - std::free(m_internal.begin); + ~small_vector() + { + std::destroy(m_begin, m_end); + if (!is_small()) + { + std::free(m_begin); } } - template void emplace_back(Args &&...args) noexcept { - if (m_size == m_capacity) { - auto new_capacity = m_capacity * 2; - if (!is_small()) { - if constexpr (is_trivially_relocatable_v) { - m_internal.begin = - (pointer)std::realloc(m_internal.begin, sizeof(T) * new_capacity); - } else { - auto new_data = (pointer)std::malloc(sizeof(T) * new_capacity); - uninitialized_relocate_n(m_internal.begin, m_size, new_data); - std::free(m_internal.begin); - m_internal.begin = new_data; + template + void emplace_back(Args&& ...args) noexcept + { + if (m_end == m_max) + { + const auto new_capacity = capacity() * 2; + const auto size = this->size(); + if (!is_small()) + { + if constexpr (is_trivially_relocatable_v) + { + m_begin = (pointer)std::realloc(m_begin, sizeof(T) * new_capacity); + } + else + { + auto new_data = (pointer) std::malloc(sizeof(T) * new_capacity); + uninitialized_relocate_n(m_begin, size, new_data); + std::free(m_begin); + m_begin = new_data; } - } else { - auto new_data = (pointer)std::malloc(sizeof(T) * new_capacity); - uninitialized_relocate_n(m_internal.buffer, m_size, new_data); - m_internal.begin = new_data; } - m_capacity = new_capacity; + else + { + auto new_data = (pointer) std::malloc(sizeof(T) * new_capacity); + uninitialized_relocate_n(m_buffer, size, new_data); + m_begin = new_data; + } + m_end = m_begin + size; + m_max = m_begin + new_capacity; } - ::new (data() + m_size) T(std::forward(args)...); - m_size++; + ::new(m_end) T(std::forward(args)...); + m_end++; } - void push_back(const T &value) { emplace_back(value); } + void push_back(const T& value) { emplace_back(value); } - void push_back(T &&value) { emplace_back(std::move(value)); } + void push_back(T&& value) { emplace_back(std::move(value)); } - void pop_back() { - m_size--; - if constexpr (!std::is_trivially_destructible_v) { - (data() + m_size)->~T(); + void pop_back() + { + m_end--; + if constexpr (!std::is_trivially_destructible_v) + { + m_end->~T(); } } - void clear() { - std::destroy_n(data(), m_size); - m_size = 0; + void clear() + { + std::destroy(m_begin, m_end); + m_end = m_begin; } }; } // namespace pkpy \ No newline at end of file From 32b41af8dd67e7c687aee5021e5087007cc268d9 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 19 Feb 2024 11:29:38 +0800 Subject: [PATCH 18/20] make code compact --- include/pocketpy/vector.h | 40 +-------------------------------------- 1 file changed, 1 insertion(+), 39 deletions(-) diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index d8cbd3be..62470969 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -204,7 +204,6 @@ namespace pkpy template class small_vector { - public: alignas(T) char m_buffer[sizeof(T) * N]; T* m_begin; T* m_end; @@ -224,65 +223,32 @@ namespace pkpy using const_reverse_iterator = std::reverse_iterator; [[nodiscard]] bool is_small() const { return m_begin == reinterpret_cast(m_buffer); } - [[nodiscard]] size_type size() const { return m_end - m_begin; } - [[nodiscard]] size_type capacity() const { return m_max - m_begin; } - [[nodiscard]] bool empty() const { return m_begin == m_end; } pointer data() { return m_begin; } - const_pointer data() const { return m_begin; } - reference operator[](size_type index) { return data()[index]; } - const_reference operator[](size_type index) const { return data()[index]; } - iterator begin() { return m_begin; } - const_iterator begin() const { return m_begin; } - - const_iterator cbegin() const { return m_begin; } - iterator end() { return m_end; } - const_iterator end() const { return m_end; } - - const_iterator cend() const { return m_end; } - reference front() { return *begin(); } - const_reference front() const { return *begin(); } - reference back() { return *(end() - 1); } - const_reference back() const { return *(end() - 1); } - reverse_iterator rbegin() { return reverse_iterator(end()); } - const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - - const_reverse_iterator crbegin() const - { - return const_reverse_iterator(end()); - } - reverse_iterator rend() { return reverse_iterator(begin()); } - const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } - - const_reverse_iterator crend() const - { - return const_reverse_iterator(begin()); - } - private: static void uninitialized_copy_n(const void* src, size_type n, void* dest) { @@ -371,10 +337,7 @@ namespace pkpy ~small_vector() { std::destroy(m_begin, m_end); - if (!is_small()) - { - std::free(m_begin); - } + if (!is_small()) std::free(m_begin); } template @@ -412,7 +375,6 @@ namespace pkpy } void push_back(const T& value) { emplace_back(value); } - void push_back(T&& value) { emplace_back(std::move(value)); } void pop_back() From cbe8945d379f9d9b138dfe8991166fb71e008c30 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 19 Feb 2024 11:42:18 +0800 Subject: [PATCH 19/20] some update --- include/pocketpy/codeobject.h | 3 ++- include/pocketpy/frame.h | 2 +- include/pocketpy/vector.h | 7 ++++--- src/compiler.cpp | 2 +- src/vm.cpp | 5 ++--- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/pocketpy/codeobject.h b/include/pocketpy/codeobject.h index db3eec05..4da74cdc 100644 --- a/include/pocketpy/codeobject.h +++ b/include/pocketpy/codeobject.h @@ -71,7 +71,8 @@ struct CodeObject { std::vector iblocks; // block index for each bytecode std::vector lines; - List consts; + small_vector consts; + pod_vector varnames; // local variables NameDictInt varnames_inv; std::vector blocks; diff --git a/include/pocketpy/frame.h b/include/pocketpy/frame.h index b5d84902..06df37cd 100644 --- a/include/pocketpy/frame.h +++ b/include/pocketpy/frame.h @@ -126,7 +126,7 @@ struct Frame { } }; -using CallstackContainer = std::vector; +using CallstackContainer = small_vector; struct FrameId{ CallstackContainer* data; diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index 62470969..73c02038 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -162,7 +162,8 @@ public: const T& top() const { return vec.back(); } T popx(){ T t = std::move(vec.back()); vec.pop_back(); return t; } void reserve(int n){ vec.reserve(n); } - Container& data() { return vec; } + Container& container() { return vec; } + const Container& container() const { return vec; } }; template > @@ -229,8 +230,8 @@ namespace pkpy pointer data() { return m_begin; } const_pointer data() const { return m_begin; } - reference operator[](size_type index) { return data()[index]; } - const_reference operator[](size_type index) const { return data()[index]; } + reference operator[](size_type index) { return m_begin[index]; } + const_reference operator[](size_type index) const { return m_begin[index]; } iterator begin() { return m_begin; } const_iterator begin() const { return m_begin; } iterator end() { return m_end; } diff --git a/src/compiler.cpp b/src/compiler.cpp index b9554708..dd4fb3cd 100644 --- a/src/compiler.cpp +++ b/src/compiler.cpp @@ -1011,7 +1011,7 @@ __EAT_DOTS_END: } ctx()->emit_(OP_BEGIN_CLASS, namei, BC_KEEPLINE); - for(auto& c: this->contexts.data()){ + for(auto& c: this->contexts.container()){ if(c.is_compiling_class){ SyntaxError("nested class is not allowed"); } diff --git a/src/vm.cpp b/src/vm.cpp index 5ea4804b..b63e9541 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -69,7 +69,6 @@ namespace pkpy{ VM::VM(bool enable_os) : heap(this), enable_os(enable_os) { this->vm = this; this->_c.error = nullptr; - this->callstack.reserve(8); _stdout = [](const char* buf, int size) { std::cout.write(buf, size); }; _stderr = [](const char* buf, int size) { std::cerr.write(buf, size); }; _main = nullptr; @@ -124,7 +123,7 @@ namespace pkpy{ #if PK_DEBUG_EXTRA_CHECK if(callstack.empty()) PK_FATAL_ERROR(); #endif - return FrameId(&callstack.data(), callstack.size()-1); + return FrameId(&callstack.container(), callstack.size()-1); } void VM::_pop_frame(){ @@ -1262,7 +1261,7 @@ void VM::_raise(bool re_raise){ void ManagedHeap::mark() { for(PyObject* obj: _no_gc) PK_OBJ_MARK(obj); - for(auto& frame : vm->callstack.data()) frame._gc_mark(); + for(auto& frame : vm->callstack.container()) frame._gc_mark(); for(PyObject* obj: vm->s_data) PK_OBJ_MARK(obj); for(auto [_, co]: vm->_cached_codes) co->_gc_mark(); if(vm->_last_exception) PK_OBJ_MARK(vm->_last_exception); From ffee64655eaec1fa67876ac7d1739e9da90eaa08 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 19 Feb 2024 11:50:55 +0800 Subject: [PATCH 20/20] some more replace --- include/pocketpy/codeobject.h | 8 +++++--- include/pocketpy/compiler.h | 2 +- include/pocketpy/frame.h | 2 +- include/pocketpy/lexer.h | 2 +- include/pocketpy/profiler.h | 2 +- include/pocketpy/vector.h | 13 +++++++++++++ include/pocketpy/vm.h | 2 +- 7 files changed, 23 insertions(+), 8 deletions(-) diff --git a/include/pocketpy/codeobject.h b/include/pocketpy/codeobject.h index 4da74cdc..708f74af 100644 --- a/include/pocketpy/codeobject.h +++ b/include/pocketpy/codeobject.h @@ -71,7 +71,7 @@ struct CodeObject { std::vector iblocks; // block index for each bytecode std::vector lines; - small_vector consts; + small_vector_no_copy_and_move consts; pod_vector varnames; // local variables NameDictInt varnames_inv; @@ -97,8 +97,10 @@ struct FuncDecl { PyObject* value; // default value }; CodeObject_ code; // code object of this function - pod_vector args; // indices in co->varnames - pod_vector kwargs; // indices in co->varnames + + small_vector_no_copy_and_move args; // indices in co->varnames + small_vector_no_copy_and_move kwargs; // indices in co->varnames + int starred_arg = -1; // index in co->varnames, -1 if no *arg int starred_kwarg = -1; // index in co->varnames, -1 if no **kwarg bool nested = false; // whether this function is nested diff --git a/include/pocketpy/compiler.h b/include/pocketpy/compiler.h index 92137cb4..42c3bc8b 100644 --- a/include/pocketpy/compiler.h +++ b/include/pocketpy/compiler.h @@ -22,7 +22,7 @@ class Compiler { inline static PrattRule rules[kTokenCount]; Lexer lexer; - stack contexts; + stack_no_copy contexts; VM* vm; bool unknown_global_scope; // for eval/exec() call bool used; diff --git a/include/pocketpy/frame.h b/include/pocketpy/frame.h index 06df37cd..b11eeb60 100644 --- a/include/pocketpy/frame.h +++ b/include/pocketpy/frame.h @@ -126,7 +126,7 @@ struct Frame { } }; -using CallstackContainer = small_vector; +using CallstackContainer = small_vector_no_copy_and_move; struct FrameId{ CallstackContainer* data; diff --git a/include/pocketpy/lexer.h b/include/pocketpy/lexer.h index 97fed808..47611d37 100644 --- a/include/pocketpy/lexer.h +++ b/include/pocketpy/lexer.h @@ -104,7 +104,7 @@ struct Lexer { const char* curr_char; int current_line = 1; std::vector nexts; - stack_no_copy> indents; + stack_no_copy> indents; int brackets_level = 0; bool used = false; diff --git a/include/pocketpy/profiler.h b/include/pocketpy/profiler.h index ee6c2129..e1f77c94 100644 --- a/include/pocketpy/profiler.h +++ b/include/pocketpy/profiler.h @@ -22,7 +22,7 @@ struct _FrameRecord{ struct LineProfiler{ // filename -> records std::map> records; - stack<_FrameRecord> frames; + stack_no_copy<_FrameRecord> frames; std::set functions; void begin(); diff --git a/include/pocketpy/vector.h b/include/pocketpy/vector.h index 73c02038..fefb645e 100644 --- a/include/pocketpy/vector.h +++ b/include/pocketpy/vector.h @@ -393,4 +393,17 @@ namespace pkpy m_end = m_begin; } }; + +// small_vector_no_copy_and_move + + template + class small_vector_no_copy_and_move: public small_vector + { + public: + small_vector_no_copy_and_move() = default; + small_vector_no_copy_and_move(const small_vector_no_copy_and_move& other) = delete; + small_vector_no_copy_and_move& operator=(const small_vector_no_copy_and_move& other) = delete; + small_vector_no_copy_and_move(small_vector_no_copy_and_move&& other) = delete; + small_vector_no_copy_and_move& operator=(small_vector_no_copy_and_move&& other) = delete; + }; } // namespace pkpy \ No newline at end of file diff --git a/include/pocketpy/vm.h b/include/pocketpy/vm.h index eee9fdaf..1c1f0593 100644 --- a/include/pocketpy/vm.h +++ b/include/pocketpy/vm.h @@ -120,7 +120,7 @@ public: struct{ PyObject* error; - stack s_view; + stack_no_copy s_view; } _c; PyObject* None;