diff --git a/run_profile.sh b/run_profile.sh index 559f34d5..fd2e0594 100644 --- a/run_profile.sh +++ b/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 diff --git a/src/ceval.h b/src/ceval.h index 85d27ab0..a8bee5a3 100644 --- a/src/ceval.h +++ b/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]; diff --git a/src/pocketpy.h b/src/pocketpy.h index 561dbebd..32d32c52 100644 --- a/src/pocketpy.h +++ b/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?istop; 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(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; + _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?istop; 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(vm, args[0], args[1]); }); + _vm->_type_info("tuple")->m__getitem__ = PyArrayGetItem; _vm->bind_method<0>("tuple", "__len__", [](VM* vm, ArgsView args) { const Tuple& self = _CAST(Tuple&, args[0]); diff --git a/src/vm.h b/src/vm.h index 702e675d..b2e19f7c 100644 --- a/src/vm.h +++ b/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 void bind_func(Str type, Str name, NativeFuncC fn) { bind_func(_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 +PyObject* PyArrayGetItem(VM* vm, PyObject* obj, PyObject* index){ + static_assert(std::is_same_v || std::is_same_v); + 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?istop; 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 \ No newline at end of file