diff --git a/include/pocketpy/common/algorithm.h b/include/pocketpy/common/algorithm.h index 6a093047..a3ce50b8 100644 --- a/include/pocketpy/common/algorithm.h +++ b/include/pocketpy/common/algorithm.h @@ -8,7 +8,7 @@ extern "C" { #define c11__less(a, b) ((a) < (b)) -#define c11__lower_bound(T, ptr, count, key, less, out) \ +#define c11__lower_bound(T, ptr, count, key, less, out_index) \ do { \ T* __first = ptr; \ int __len = count; \ @@ -22,7 +22,7 @@ extern "C" { __len = __l2; \ } \ } \ - *(out) = __first; \ + *(out_index) = __first - (T*)(ptr); \ } while(0) #ifdef __cplusplus diff --git a/include/pocketpy/common/vector.h b/include/pocketpy/common/vector.h index d984a21d..19d3b3d4 100644 --- a/include/pocketpy/common/vector.h +++ b/include/pocketpy/common/vector.h @@ -1,8 +1,11 @@ #pragma once +#include "pocketpy/common/algorithm.h" + #include #include -#include "pocketpy/common/algorithm.h" +#include +#include #ifdef __cplusplus extern "C" { @@ -17,7 +20,6 @@ typedef struct c11_array{ void c11_array__ctor(c11_array* self, int elem_size, int count); void c11_array__dtor(c11_array* self); c11_array c11_array__copy(const c11_array* self); -void* c11_array__at(c11_array* self, int index); typedef struct c11_vector{ void* data; @@ -29,12 +31,12 @@ typedef struct c11_vector{ void c11_vector__ctor(c11_vector* self, int elem_size); void c11_vector__dtor(c11_vector* self); c11_vector c11_vector__copy(const c11_vector* self); -void* c11_vector__at(c11_vector* self, int index); void c11_vector__reserve(c11_vector* self, int capacity); void c11_vector__clear(c11_vector* self); -#define c11__getitem(T, self, index) ((T*)(self)->data)[index] +#define c11__getitem(T, self, index) (((T*)(self)->data)[index]) #define c11__setitem(T, self, index, value) ((T*)(self)->data)[index] = value; +#define c11__at(T, self, index) ((T*)(self)->data + index) #define c11_vector__push(T, self, elem) \ do{ \ @@ -56,19 +58,19 @@ void c11_vector__clear(c11_vector* self); }while(0) -#define c11_vector__insert(T, self, p, elem) \ +#define c11_vector__insert(T, self, index, elem) \ do{ \ if((self)->count == (self)->capacity) c11_vector__reserve((self), (self)->capacity*2); \ - int __n = (self)->count - (p - (T*)(self)->data); \ - memmove(p + 1, p, __n * sizeof(T)); \ + T* p = (T*)(self)->data + (index); \ + memmove(p + 1, p, ((self)->count - (index)) * sizeof(T)); \ *p = (elem); \ (self)->count++; \ }while(0) -#define c11_vector__erase(T, self, p) \ +#define c11_vector__erase(T, self, index) \ do{ \ - int __n = (self)->count - (p - (T*)(self)->data) - 1; \ - memmove(p, p + 1, __n * sizeof(T)); \ + T* p = (T*)(self)->data + (index); \ + memmove(p, p + 1, ((self)->count - (index) - 1) * sizeof(T)); \ (self)->count--; \ }while(0) diff --git a/include/pocketpy/interpreter/vm.hpp b/include/pocketpy/interpreter/vm.hpp index cb5276f6..b814a69d 100644 --- a/include/pocketpy/interpreter/vm.hpp +++ b/include/pocketpy/interpreter/vm.hpp @@ -189,7 +189,6 @@ public: PyObject* __last_exception; PyObject* __curr_class; PyVar __cached_object_new; - small_map __cached_codes; small_map __cached_op_funcs; FuncDecl_ __dynamic_func_decl; PyVar __vectorcall_buffer[PK_MAX_CO_VARNAMES]; diff --git a/include/pocketpy/objects/codeobject.hpp b/include/pocketpy/objects/codeobject.hpp index 7bf95080..f4b5c743 100644 --- a/include/pocketpy/objects/codeobject.hpp +++ b/include/pocketpy/objects/codeobject.hpp @@ -4,6 +4,7 @@ #include "pocketpy/objects/tuplelist.hpp" #include "pocketpy/objects/namedict.hpp" #include "pocketpy/objects/sourcedata.hpp" +#include "pocketpy/common/smallmap.h" namespace pkpy { @@ -126,15 +127,22 @@ struct FuncDecl { const char* docstring; // docstring of this function (weak ref) FuncType type = FuncType::UNSET; - - small_map kw_to_index; + c11_smallmap_uint16_t_int kw_to_index; void add_kwarg(int index, StrName key, PyVar value) { - kw_to_index.insert(key, index); + c11_smallmap_uint16_t_int__set(&kw_to_index, key.index, index); kwargs.push_back(KwArg{index, key, value}); } void _gc_mark(VM*) const; + + FuncDecl(){ + c11_smallmap_uint16_t_int__ctor(&kw_to_index); + } + + ~FuncDecl(){ + c11_smallmap_uint16_t_int__dtor(&kw_to_index); + } }; struct NativeFunc { diff --git a/include/pocketpy/xmacros/smallmap.h b/include/pocketpy/xmacros/smallmap.h new file mode 100644 index 00000000..37517ec1 --- /dev/null +++ b/include/pocketpy/xmacros/smallmap.h @@ -0,0 +1,108 @@ +#pragma once + +#if !defined(SMALLMAP_T__HEADER) && !defined(SMALLMAP_T__SOURCE) + #include "pocketpy/common/vector.h" + + /* Input */ + #define K int + #define V float +#endif + +/* Optional Input */ +#ifndef less + #define less(a, b) ((a.key) < (b)) +#endif + +/* Temprary macros */ +#define CONCAT(A, B) CONCAT_(A, B) +#define CONCAT_(A, B) A##B + +#define KV CONCAT(CONCAT(c11_smallmap_entry_, K), CONCAT(_, V)) +#define SMALLMAP CONCAT(CONCAT(c11_smallmap_, K), CONCAT(_, V)) +#define SMALLMAP_METHOD(name) CONCAT(SMALLMAP, CONCAT(__, name)) + +typedef struct { + K key; + V value; +} KV; + +typedef struct{ + c11_vector entries; +} SMALLMAP; + +void SMALLMAP_METHOD(ctor)(SMALLMAP* self); +void SMALLMAP_METHOD(dtor)(SMALLMAP* self); +void SMALLMAP_METHOD(set)(SMALLMAP* self, K key, V value); +V* SMALLMAP_METHOD(try_get)(SMALLMAP* self, K key); +V SMALLMAP_METHOD(get)(SMALLMAP* self, K key, V default_value); +bool SMALLMAP_METHOD(contains)(SMALLMAP* self, K key); +bool SMALLMAP_METHOD(del)(SMALLMAP* self, K key); +void SMALLMAP_METHOD(clear)(SMALLMAP* self); + +#ifdef SMALLMAP_T__SOURCE +/* Implementation */ + +void SMALLMAP_METHOD(ctor)(SMALLMAP* self) { + c11_vector__ctor(&self->entries, sizeof(KV)); +} + +void SMALLMAP_METHOD(dtor)(SMALLMAP* self) { + c11_vector__dtor(&self->entries); +} + +void SMALLMAP_METHOD(set)(SMALLMAP* self, K key, V value) { + int index; + c11__lower_bound(KV, self->entries.data, self->entries.count, key, less, &index); + KV* it = c11__at(KV, &self->entries, index); + if(index != self->entries.count && it->key == key) { + it->value = value; + } else { + KV kv = {key, value}; + c11_vector__insert(KV, &self->entries, index, kv); + } +} + +V* SMALLMAP_METHOD(try_get)(SMALLMAP* self, K key) { + int index; + c11__lower_bound(KV, self->entries.data, self->entries.count, key, less, &index); + KV* it = c11__at(KV, &self->entries, index); + if(index != self->entries.count && it->key == key) { + return &it->value; + } else { + return NULL; + } +} + +V SMALLMAP_METHOD(get)(SMALLMAP* self, K key, V default_value) { + V* p = SMALLMAP_METHOD(try_get)(self, key); + return p ? *p : default_value; +} + +bool SMALLMAP_METHOD(contains)(SMALLMAP* self, K key) { + return SMALLMAP_METHOD(try_get)(self, key) != NULL; +} + +bool SMALLMAP_METHOD(del)(SMALLMAP* self, K key) { + int index; + c11__lower_bound(KV, self->entries.data, self->entries.count, key, less, &index); + KV* it = c11__at(KV, &self->entries, index); + if(index != self->entries.count && it->key == key) { + c11_vector__erase(KV, &self->entries, index); + return true; + } + return false; +} + +void SMALLMAP_METHOD(clear)(SMALLMAP* self) { + c11_vector__clear(&self->entries); +} + +#endif + +#undef KV +#undef SMALLMAP +#undef SMALLMAP_METHOD + +#undef K +#undef V +#undef less diff --git a/src/common/smallmap.c b/src/common/smallmap.c new file mode 100644 index 00000000..19b340f0 --- /dev/null +++ b/src/common/smallmap.c @@ -0,0 +1,8 @@ +#include "pocketpy/common/vector.h" +#include + +#define SMALLMAP_T__SOURCE +#define K uint16_t +#define V int +#include "pocketpy/xmacros/smallmap.h" +#undef SMALLMAP_T__SOURCE diff --git a/src/common/str.c b/src/common/str.c index dd164919..3a21f342 100644 --- a/src/common/str.c +++ b/src/common/str.c @@ -386,9 +386,8 @@ static const int kLoRangeB[] = {170,186,443,451,660,1514,1522,1599,1610,1647,174 bool c11__is_unicode_Lo_char(int c){ if(c == 0x1f955) return true; - const int* p; - c11__lower_bound(const int, kLoRangeA, 476, c, c11__less, &p); - int index = p - kLoRangeA; + int index; + c11__lower_bound(const int, kLoRangeA, 476, c, c11__less, &index); if(c == kLoRangeA[index]) return true; index -= 1; if(index < 0) return false; diff --git a/src/common/vector.c b/src/common/vector.c index b28b75fe..44e76d66 100644 --- a/src/common/vector.c +++ b/src/common/vector.c @@ -22,10 +22,6 @@ c11_array c11_array__copy(const c11_array* self){ return retval; } -void* c11_array__at(c11_array* self, int index){ - return (char*)self->data + self->elem_size * index; -} - void c11_vector__ctor(c11_vector* self, int elem_size){ self->data = NULL; self->count = 0; @@ -49,10 +45,6 @@ c11_vector c11_vector__copy(const c11_vector* self){ return retval; } -void* c11_vector__at(c11_vector* self, int index){ - return (char*)self->data + self->elem_size * index; -} - void c11_vector__reserve(c11_vector* self, int capacity){ if(capacity < 4) capacity = 4; if(capacity <= self->capacity) return; diff --git a/src/interpreter/ceval.cpp b/src/interpreter/ceval.cpp index 978d296e..cc040851 100644 --- a/src/interpreter/ceval.cpp +++ b/src/interpreter/ceval.cpp @@ -789,14 +789,8 @@ PyVar VM::__run_top_frame() { case OP_FSTRING_EVAL: { PyVar _0 = frame->co->consts[byte.arg]; std::string_view string = CAST(Str&, _0).sv(); - auto it = __cached_codes.try_get(string); - CodeObject_ code; - if(it == nullptr) { - code = vm->compile(string, "", EVAL_MODE, true); - __cached_codes.insert(string, code); - } else { - code = *it; - } + // TODO: optimize this + CodeObject_ code = vm->compile(string, "", EVAL_MODE, true); _0 = vm->_exec(code.get(), frame->_module, frame->_callable, frame->_locals); PUSH(_0); } diff --git a/src/interpreter/vm.cpp b/src/interpreter/vm.cpp index 148663b5..3f2edb76 100644 --- a/src/interpreter/vm.cpp +++ b/src/interpreter/vm.cpp @@ -1009,7 +1009,7 @@ void VM::__prepare_py_call(PyVar* buffer, ArgsView args, ArgsView kwargs, const for(int j = 0; j < kwargs.size(); j += 2) { StrName key(_CAST(uint16_t, kwargs[j])); - int index = decl->kw_to_index.get(key, -1); + int index = c11_smallmap_uint16_t_int__get(&decl->kw_to_index, key.index, -1); // if key is an explicit key, set as local variable if(index >= 0) { buffer[index] = kwargs[j + 1]; @@ -1865,8 +1865,6 @@ void ManagedHeap::mark() { vm->callstack.apply([this](Frame& frame) { frame._gc_mark(vm); }); - for(auto [_, co]: vm->__cached_codes) - co->_gc_mark(vm); vm->obj_gc_mark(vm->__last_exception); vm->obj_gc_mark(vm->__curr_class); vm->obj_gc_mark(vm->__c.error); diff --git a/src/modules/random.cpp b/src/modules/random.cpp index 4e43c3e0..ad3942cd 100644 --- a/src/modules/random.cpp +++ b/src/modules/random.cpp @@ -199,9 +199,9 @@ struct Random { List result(k); for(int i = 0; i < k; i++) { f64 key = self.gen.uniform(0.0, cum_weights[size - 1]); - f64* p; - c11__lower_bound(f64, cum_weights.begin(), cum_weights.size(), key, c11__less, &p); - result[i] = data[p - cum_weights.begin()]; + int index; + c11__lower_bound(f64, cum_weights.begin(), cum_weights.size(), key, c11__less, &index); + result[i] = data[index]; } return VAR(std::move(result)); });