blueloveTH 2 ani în urmă
părinte
comite
c9926cdcea
4 a modificat fișierele cu 68 adăugiri și 38 ștergeri
  1. 1 1
      run_profile.sh
  2. 13 2
      src/ceval.h
  3. 6 34
      src/pocketpy.h
  4. 48 1
      src/vm.h

+ 1 - 1
run_profile.sh

@@ -1,5 +1,5 @@
 clang++ -pg -O2 -std=c++17 -fno-rtti -stdlib=libc++ -Wall -o pocketpy src/main.cpp
-time ./pocketpy benchmarks/fib.py
+time ./pocketpy benchmarks/sort.py
 mv benchmarks/gmon.out .
 gprof pocketpy gmon.out > gprof.txt
 rm gmon.out

+ 13 - 2
src/ceval.h

@@ -13,6 +13,7 @@ inline PyObject* VM::_run_top_frame(){
 
     // shared registers
     PyObject *_0, *_1, *_2;
+    const PyTypeInfo* _ti;
     StrName _name;
 
     while(true){
@@ -146,7 +147,12 @@ __NEXT_STEP:;
     TARGET(LOAD_SUBSCR)
         _1 = POPX();    // b
         _0 = TOP();     // a
-        TOP() = call_method(_0, __getitem__, _1);
+        _ti = _inst_type_info(_0);
+        if(_ti->m__getitem__){
+            TOP() = _ti->m__getitem__(this, _0, _1);
+        }else{
+            TOP() = call_method(_0, __getitem__, _1);
+        }
         DISPATCH();
     TARGET(STORE_FAST)
         frame->_locals[byte.arg] = POPX();
@@ -174,7 +180,12 @@ __NEXT_STEP:;
         _2 = POPX();        // b
         _1 = POPX();        // a
         _0 = POPX();        // val
-        call_method(_1, __setitem__, _2, _0);
+        _ti = _inst_type_info(_1);
+        if(_ti->m__setitem__){
+            _ti->m__setitem__(this, _1, _2, _0);
+        }else{
+            call_method(_1, __setitem__, _2, _0);
+        }
         DISPATCH();
     TARGET(DELETE_FAST)
         _0 = frame->_locals[byte.arg];

+ 6 - 34
src/pocketpy.h

@@ -551,29 +551,13 @@ inline void init_builtins(VM* _vm) {
     });
 
     _vm->bind_method<1>("list", "__getitem__", [](VM* vm, ArgsView args) {
-        const List& self = _CAST(List&, args[0]);
-
-        if(is_type(args[1], vm->tp_slice)){
-            const Slice& s = _CAST(Slice&, args[1]);
-            int start, stop, step;
-            vm->parse_int_slice(s, self.size(), start, stop, step);
-            List new_list;
-            for(int i=start; step>0?i<stop:i>stop; i+=step) new_list.push_back(self[i]);
-            return VAR(std::move(new_list));
-        }
-
-        int index = CAST(int, args[1]);
-        index = vm->normalized_index(index, self.size());
-        return self[index];
+        return PyArrayGetItem<List>(vm, args[0], args[1]);
     });
-
     _vm->bind_method<2>("list", "__setitem__", [](VM* vm, ArgsView args) {
-        List& self = _CAST(List&, args[0]);
-        int index = CAST(int, args[1]);
-        index = vm->normalized_index(index, self.size());
-        self[index] = args[2];
-        return vm->None;
+        return PyListSetItem(vm, args[0], args[1], args[2]);
     });
+    _vm->_type_info("list")->m__getitem__ = PyArrayGetItem<List>;
+    _vm->_type_info("list")->m__setitem__ = PyListSetItem;
 
     _vm->bind_method<1>("list", "__delitem__", [](VM* vm, ArgsView args) {
         List& self = _CAST(List&, args[0]);
@@ -594,21 +578,9 @@ inline void init_builtins(VM* _vm) {
     });
 
     _vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, ArgsView args) {
-        const Tuple& self = _CAST(Tuple&, args[0]);
-
-        if(is_type(args[1], vm->tp_slice)){
-            const Slice& s = _CAST(Slice&, args[1]);
-            int start, stop, step;
-            vm->parse_int_slice(s, self.size(), start, stop, step);
-            List new_list;
-            for(int i=start; step>0?i<stop:i>stop; i+=step) new_list.push_back(self[i]);
-            return VAR(Tuple(std::move(new_list)));
-        }
-
-        int index = CAST(int, args[1]);
-        index = vm->normalized_index(index, self.size());
-        return self[index];
+        return PyArrayGetItem<Tuple>(vm, args[0], args[1]);
     });
+    _vm->_type_info("tuple")->m__getitem__ = PyArrayGetItem<Tuple>;
 
     _vm->bind_method<0>("tuple", "__len__", [](VM* vm, ArgsView args) {
         const Tuple& self = _CAST(Tuple&, args[0]);

+ 48 - 1
src/vm.h

@@ -65,6 +65,9 @@ struct PyTypeInfo{
     Type base;
     Str name;
     bool subclass_enabled;
+    // cached special methods
+    PyObject* (*m__getitem__)(VM* vm, PyObject*, PyObject*) = nullptr;
+    PyObject* (*m__setitem__)(VM* vm, PyObject*, PyObject*, PyObject*) = nullptr;
 };
 
 struct FrameId{
@@ -265,6 +268,21 @@ public:
         return obj;
     }
 
+    PyTypeInfo* _type_info(const Str& type){
+        PyObject* obj = builtins->attr().try_get(type);
+        if(obj == nullptr){
+            for(auto& t: _all_types) if(t.name == type) return &t;
+            FATAL_ERROR();
+        }
+        return &_all_types[OBJ_GET(Type, obj)];
+    }
+
+    const PyTypeInfo* _inst_type_info(PyObject* obj){
+        if(is_int(obj)) return &_all_types[tp_int];
+        if(is_float(obj)) return &_all_types[tp_float];
+        return &_all_types[obj->type];
+    }
+
     template<int ARGC>
     void bind_func(Str type, Str name, NativeFuncC fn) {
         bind_func<ARGC>(_find_type(type), name, fn);
@@ -370,7 +388,7 @@ public:
     PyObject* _t(PyObject* obj){
         if(is_int(obj)) return _t(tp_int);
         if(is_float(obj)) return _t(tp_float);
-        return _all_types[OBJ_GET(Type, _t(obj->type)).index].obj;
+        return _all_types[obj->type].obj;
     }
 
     ~VM() {
@@ -1216,4 +1234,33 @@ inline Str obj_type_name(VM *vm, Type type){
 #undef PY_VAR_INT
 #undef PY_VAR_FLOAT
 
+/***************************************************/
+
+template<typename T>
+PyObject* PyArrayGetItem(VM* vm, PyObject* obj, PyObject* index){
+    static_assert(std::is_same_v<T, List> || std::is_same_v<T, Tuple>);
+    const T& self = _CAST(T&, obj);
+
+    if(is_type(index, vm->tp_slice)){
+        const Slice& s = _CAST(Slice&, index);
+        int start, stop, step;
+        vm->parse_int_slice(s, self.size(), start, stop, step);
+        List new_list;
+        for(int i=start; step>0?i<stop:i>stop; i+=step) new_list.push_back(self[i]);
+        return VAR(T(std::move(new_list)));
+    }
+
+    int i = CAST(int, index);
+    i = vm->normalized_index(i, self.size());
+    return self[i];
+}
+
+inline PyObject* PyListSetItem(VM* vm, PyObject* obj, PyObject* index, PyObject* value){
+    List& self = _CAST(List&, obj);
+    int i = CAST(int, index);
+    i = vm->normalized_index(i, self.size());
+    self[i] = value;
+    return vm->None;
+}
+
 }   // namespace pkpy