blueloveTH преди 1 година
родител
ревизия
4d66290529
променени са 6 файла, в които са добавени 114 реда и са изтрити 198 реда
  1. 3 3
      include/pocketpy/interpreter/gc.hpp
  2. 24 0
      include/pocketpy/objects/namedict.h
  3. 68 30
      include/pocketpy/objects/namedict.hpp
  4. 7 0
      src/interpreter/vm.cpp
  5. 12 0
      src/objects/namedict.c
  6. 0 165
      src/objects/namedict.cpp

+ 3 - 3
include/pocketpy/interpreter/gc.hpp

@@ -50,11 +50,11 @@ struct ManagedHeap {
 
         // backdoor for important builtin types
         if constexpr(std::is_same_v<__T, DummyInstance>) {
-            p->_attr = new NameDict(PK_INST_ATTR_LOAD_FACTOR);
+            p->_attr = new NameDict();
         } else if constexpr(std::is_same_v<__T, Type>) {
-            p->_attr = new NameDict(PK_TYPE_ATTR_LOAD_FACTOR);
+            p->_attr = new NameDict();
         } else if constexpr(std::is_same_v<__T, DummyModule>) {
-            p->_attr = new NameDict(PK_TYPE_ATTR_LOAD_FACTOR);
+            p->_attr = new NameDict();
         }
         return p;
     }

+ 24 - 0
include/pocketpy/objects/namedict.h

@@ -0,0 +1,24 @@
+#pragma once
+
+#include "pocketpy/common/vector.h"
+#include "pocketpy/common/str.h"
+#include <stdint.h>
+
+#include "pocketpy/objects/pyvar.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define SMALLMAP_T__HEADER
+#define K uint16_t
+#define V pkpy_Var
+#define TAG n2v
+#include "pocketpy/xmacros/smallmap.h"
+#undef SMALLMAP_T__HEADER
+
+typedef c11_smallmap_n2v pkpy_NameDict;
+
+#ifdef __cplusplus
+}
+#endif

+ 68 - 30
include/pocketpy/objects/namedict.hpp

@@ -4,58 +4,96 @@
 #include "pocketpy/common/str.hpp"
 #include "pocketpy/common/utils.h"
 #include "pocketpy/objects/object.hpp"
+#include "pocketpy/objects/namedict.h"
 
 namespace pkpy {
 
-struct NameDict {
+struct NameDict: pkpy_NameDict {
     PK_ALWAYS_PASS_BY_POINTER(NameDict)
 
     using Item = pair<StrName, PyVar>;
 
-    constexpr static uint16_t kInitialCapacity = 16;
-
-    float _load_factor;
-    uint16_t _size;
-
-    uint16_t _capacity;
-    uint16_t _critical_size;
-    uint16_t _mask;
-
-    Item* _items;
+    NameDict() {
+        c11_smallmap_n2v__ctor(this);
+    }
 
-    NameDict(float load_factor = PK_INST_ATTR_LOAD_FACTOR) : _load_factor(load_factor), _size(0) {
-        _set_capacity_and_alloc_items(kInitialCapacity);
+    ~NameDict() {
+        c11_smallmap_n2v__dtor(this);
     }
 
-    ~NameDict() { std::free(_items); }
+    uint16_t size() const {
+        return count;
+    }
 
-    uint16_t size() const { return _size; }
+    void set(StrName key, PyVar val){
+        pkpy_Var* p = (pkpy_Var*)&val;
+        c11_smallmap_n2v__set(this, key.index, *p);
+    }
 
-    uint16_t capacity() const { return _capacity; }
+    PyVar try_get(StrName key) const{
+        PyVar* p = try_get_2(key);
+        return p ? *p : nullptr;
+    }
 
-    void _set_capacity_and_alloc_items(uint16_t val);
+    PyVar* try_get_2(StrName key) const{
+        pkpy_Var* p = c11_smallmap_n2v__try_get(this, key.index);
+        return p ? (PyVar*)p : nullptr;
+    }
 
-    void set(StrName key, PyVar val);
+    PyVar try_get_likely_found(StrName key) const{
+        return try_get(key);
+    }
 
-    void _rehash_2x();
+    PyVar* try_get_2_likely_found(StrName key) const{
+        return try_get_2(key);
+    }
 
-    PyVar try_get(StrName key) const;
+    bool del(StrName key){
+        return c11_smallmap_n2v__del(this, key.index);
+    }
 
-    PyVar* try_get_2(StrName key) const;
+    bool contains(StrName key) const{
+        return c11_smallmap_n2v__contains(this, key.index);
+    }
 
-    PyVar try_get_likely_found(StrName key) const;
+    PyVar operator[] (StrName key) const{
+        PyVar* val = try_get_2_likely_found(key);
+        if(val == nullptr){
+            PK_FATAL_ERROR("NameDict key not found: %d (%s)\n", (int)key.index, key.escape().c_str())
+        }
+        return *val;
+    }
 
-    PyVar* try_get_2_likely_found(StrName key) const;
+    void clear(){
+        c11_smallmap_n2v__clear(this);
+    }
 
-    bool del(StrName key);
+    array<StrName> keys() const{
+        array<StrName> retval((int)size());
+        for(int i=0; i<size(); i++){
+            auto it = c11__at(c11_smallmap_entry_n2v, this, i);
+            retval[i] = StrName(it->key);
+        }
+        return retval;
+    }
 
-    bool contains(StrName key) const;
-    PyVar operator[] (StrName key) const;
-    array<StrName> keys() const;
-    array<Item> items() const;
-    void clear();
+    array<Item> items() const{
+        array<Item> retval((int)size());
+        for(int i=0; i<size(); i++){
+            auto it = c11__at(c11_smallmap_entry_n2v, this, i);
+            PyVar* p = (PyVar*)&it->value;
+            retval[i] = Item(StrName(it->key), *p);
+        }
+        return retval;
+    }
 
-    void apply(void (*f)(StrName, PyVar, void*), void* data);
+    void apply(void (*f)(StrName, PyVar, void*), void* data){
+        for(int i=0; i<size(); i++){
+            auto it = c11__at(c11_smallmap_entry_n2v, this, i);
+            PyVar* p = (PyVar*)&it->value;
+            f(StrName(it->key), *p, data);
+        }
+    }
 };
 
 static_assert(sizeof(NameDict) <= 128);

+ 7 - 0
src/interpreter/vm.cpp

@@ -1796,6 +1796,13 @@ void VM::__breakpoint() {
 #endif
 }
 
+/**************************************************************************/
+
+PyVar PyObject::attr(StrName name) const {
+    assert(is_attr_valid());
+    return (*_attr)[name];
+}
+
 /**************************************************************************/
 void Function::_gc_mark(VM* vm) const {
     decl->_gc_mark(vm);

+ 12 - 0
src/objects/namedict.c

@@ -0,0 +1,12 @@
+#include "pocketpy/common/vector.h"
+#include "pocketpy/common/str.h"
+#include <stdint.h>
+
+#include "pocketpy/objects/pyvar.h"
+
+#define SMALLMAP_T__SOURCE
+#define K uint16_t
+#define V pkpy_Var
+#define TAG n2v
+#include "pocketpy/xmacros/smallmap.h"
+#undef SMALLMAP_T__SOURCE

+ 0 - 165
src/objects/namedict.cpp

@@ -1,165 +0,0 @@
-#include "pocketpy/objects/namedict.hpp"
-
-namespace pkpy {
-
-#define HASH_PROBE_1(key, ok, i)                                                                                       \
-    ok = false;                                                                                                        \
-    i = key.index & _mask;                                                                                             \
-    while(!_items[i].first.empty()) {                                                                                  \
-        if(_items[i].first == (key)) {                                                                                 \
-            ok = true;                                                                                                 \
-            break;                                                                                                     \
-        }                                                                                                              \
-        i = (i + 1) & _mask;                                                                                           \
-    }
-
-#define HASH_PROBE_0 HASH_PROBE_1
-
-void NameDict::_set_capacity_and_alloc_items(uint16_t val) {
-    _capacity = val;
-    _critical_size = val * _load_factor;
-    _mask = val - 1;
-
-    _items = (Item*)std::malloc(_capacity * sizeof(Item));
-    std::memset(_items, 0, _capacity * sizeof(Item));
-}
-
-void NameDict::set(StrName key, PyVar val) {
-    bool ok;
-    uint16_t i;
-    HASH_PROBE_1(key, ok, i);
-    if(!ok) {
-        _size++;
-        if(_size > _critical_size) {
-            _rehash_2x();
-            HASH_PROBE_1(key, ok, i);
-        }
-        _items[i].first = key;
-    }
-    _items[i].second = val;
-}
-
-void NameDict::_rehash_2x() {
-    Item* old_items = _items;
-    uint16_t old_capacity = _capacity;
-    _set_capacity_and_alloc_items(_capacity * 2);
-    for(uint16_t i = 0; i < old_capacity; i++) {
-        if(old_items[i].first.empty()) continue;
-        bool ok;
-        uint16_t j;
-        HASH_PROBE_1(old_items[i].first, ok, j);
-        assert(!ok);
-        _items[j] = old_items[i];
-    }
-    std::free(old_items);
-}
-
-PyVar NameDict::try_get(StrName key) const {
-    bool ok;
-    uint16_t i;
-    HASH_PROBE_0(key, ok, i);
-    if(!ok) return nullptr;
-    return _items[i].second;
-}
-
-PyVar* NameDict::try_get_2(StrName key) const {
-    bool ok;
-    uint16_t i;
-    HASH_PROBE_0(key, ok, i);
-    if(!ok) return nullptr;
-    return &_items[i].second;
-}
-
-PyVar NameDict::try_get_likely_found(StrName key) const {
-    uint16_t i = key.index & _mask;
-    if(_items[i].first == key) return _items[i].second;
-    i = (i + 1) & _mask;
-    if(_items[i].first == key) return _items[i].second;
-    return try_get(key);
-}
-
-PyVar* NameDict::try_get_2_likely_found(StrName key) const {
-    uint16_t i = key.index & _mask;
-    if(_items[i].first == key) return &_items[i].second;
-    i = (i + 1) & _mask;
-    if(_items[i].first == key) return &_items[i].second;
-    return try_get_2(key);
-}
-
-bool NameDict::del(StrName key) {
-    bool ok;
-    uint16_t i;
-    HASH_PROBE_0(key, ok, i);
-    if(!ok) return false;
-    _items[i].first = StrName();
-    _items[i].second = nullptr;
-    _size--;
-    // tidy
-    uint16_t pre_z = i;
-    uint16_t z = (i + 1) & _mask;
-    while(!_items[z].first.empty()) {
-        uint16_t h = _items[z].first.index & _mask;
-        if(h != i) break;
-        std::swap(_items[pre_z], _items[z]);
-        pre_z = z;
-        z = (z + 1) & _mask;
-    }
-    return true;
-}
-
-bool NameDict::contains(StrName key) const {
-    bool ok;
-    uint16_t i;
-    HASH_PROBE_0(key, ok, i);
-    return ok;
-}
-
-PyVar NameDict::operator[] (StrName key) const {
-    PyVar* val = try_get_2_likely_found(key);
-    if(val == nullptr){
-        PK_FATAL_ERROR("NameDict key not found: %d (%s)\n", (int)key.index, key.escape().c_str())
-    }
-    return *val;
-}
-
-array<StrName> NameDict::keys() const {
-    array<StrName> v(_size);
-    int j = 0;
-    for(uint16_t i = 0; i < _capacity; i++) {
-        if(_items[i].first.empty()) continue;
-        new (&v[j++]) StrName(_items[i].first);
-    }
-    return v;
-}
-
-array<NameDict::Item> NameDict::items() const {
-    array<Item> v(_size);
-    int j = 0;
-    for(uint16_t i = 0; i < _capacity; i++) {
-        if(_items[i].first.empty()) continue;
-        new (&v[j++]) Item(_items[i].first, _items[i].second);
-    }
-    return v;
-}
-
-void NameDict::clear() {
-    std::memset(_items, 0, _capacity * sizeof(Item));
-    _size = 0;
-}
-
-void NameDict::apply (void (*f)(StrName, PyVar, void*), void* data) {
-    for(uint16_t i = 0; i < _capacity; i++) {
-        if(_items[i].first.empty()) continue;
-        f(_items[i].first, _items[i].second, data);
-    }
-}
-
-#undef HASH_PROBE_0
-#undef HASH_PROBE_1
-
-PyVar PyObject::attr(StrName name) const {
-    assert(is_attr_valid());
-    return (*_attr)[name];
-}
-
-}  // namespace pkpy