diff --git a/src/codeobject.h b/src/codeobject.h index eafaf293..d285a53c 100644 --- a/src/codeobject.h +++ b/src/codeobject.h @@ -169,6 +169,11 @@ public: return __deref_pointer(vm, s_data.back()); } + inline PyVar& __top(){ + if(s_data.empty()) throw std::runtime_error("s_data.empty() is true"); + return s_data.back(); + } + inline PyVar __topValueN(VM* vm, int n=-1){ return __deref_pointer(vm, s_data[s_data.size() + n]); } @@ -219,7 +224,7 @@ public: PyVarList __popNReversed(int n){ PyVarList v(n); - for(int i=n-1; i>=0; i--) v[i] = __pop(); + for(int i=n-1; i>=0; i--) v[i] = std::move(__pop()); return v; } }; \ No newline at end of file diff --git a/src/obj.h b/src/obj.h index 9c06f8bf..7c79c600 100644 --- a/src/obj.h +++ b/src/obj.h @@ -106,5 +106,6 @@ struct PyObject { return _type->getName(); } - PyObject(_Value val): _native(val) {} + PyObject(const _Value& val): _native(val) {} + PyObject(_Value&& val): _native(std::move(val)) {} }; diff --git a/src/shared_ptr.h b/src/shared_ptr.h new file mode 100644 index 00000000..a8165f2d --- /dev/null +++ b/src/shared_ptr.h @@ -0,0 +1,95 @@ +#pragma once + +#include "__stl__.h" + +// sooo slow! do not use this +namespace pkpy{ + template + class shared_ptr { + int* count; + T* ptr; + const std::function* deleter = nullptr; + + void _delete(){ + delete count; + if(deleter != nullptr) deleter->operator()(ptr); + else delete ptr; + } + + public: + shared_ptr() : count(nullptr), ptr(nullptr) {} + shared_ptr(T* ptr) : count(new int(1)), ptr(ptr) {} + shared_ptr(T* ptr, const std::function*) : count(new int(1)), ptr(ptr), deleter(deleter) {} + shared_ptr(const shared_ptr& other) : count(other.count), ptr(other.ptr) { + if (count) { + ++(*count); + } + } + shared_ptr(shared_ptr&& other) : count(other.count), ptr(other.ptr) { + other.count = nullptr; + other.ptr = nullptr; + } + ~shared_ptr() { + if (count && --(*count) == 0) _delete(); + } + + bool operator==(const shared_ptr& other) const { + return ptr == other.ptr; + } + + bool operator!=(const shared_ptr& other) const { + return ptr != other.ptr; + } + + bool operator==(std::nullptr_t) const { + return ptr == nullptr; + } + + bool operator!=(std::nullptr_t) const { + return ptr != nullptr; + } + + shared_ptr& operator=(const shared_ptr& other) { + if (this != &other) { + if (count && --(*count) == 0) _delete(); + count = other.count; + ptr = other.ptr; + if (count) { + ++(*count); + } + } + return *this; + } + shared_ptr& operator=(shared_ptr&& other) { + if (this != &other) { + if (count && --(*count) == 0) _delete(); + count = other.count; + ptr = other.ptr; + other.count = nullptr; + other.ptr = nullptr; + } + return *this; + } + + T& operator*() const { + return *ptr; + } + T* operator->() const { + return ptr; + } + T* get() const { + return ptr; + } + int use_count() const { + return count ? *count : 0; + } + explicit operator bool() const { + return ptr != nullptr; + } + }; + + template + shared_ptr make_shared(Args&&... args) { + return shared_ptr(new T(std::forward(args)...)); + } +}; \ No newline at end of file diff --git a/src/vm.h b/src/vm.h index 3baa0cdd..7fe41d59 100644 --- a/src/vm.h +++ b/src/vm.h @@ -25,11 +25,11 @@ PyObject* _raw = nullptr; \ if(_pool##name.size() > 0) { \ _raw = _pool##name.back(); \ - _raw->_native = _native; \ + _raw->_native = std::move(_native); \ _pool##name.pop_back(); \ }else{ \ __checkType(ptype, _tp_type); \ - _raw = new PyObject(_native); \ + _raw = new PyObject(std::move(_native));\ _raw->setType(ptype); \ } \ return PyVar(_raw, [this](PyObject* p){ \ @@ -82,11 +82,11 @@ private: } break; case OP_STORE_PTR: { PyVar obj = frame->popValue(this); - _Pointer p = PyPointer_AS_C(frame->__pop()); + const _Pointer& p = PyPointer_AS_C(frame->__pop()); p->set(this, frame, std::move(obj)); } break; case OP_DELETE_PTR: { - _Pointer p = PyPointer_AS_C(frame->__pop()); + const _Pointer& p = PyPointer_AS_C(frame->__pop()); p->del(this, frame); } break; case OP_BUILD_SMART_TUPLE: @@ -188,7 +188,7 @@ private: { PyVar rhs = frame->popValue(this); PyVar lhs = frame->popValue(this); - bool ret_c = PyBool_AS_C(call(rhs, __contains__, {lhs})); + bool ret_c = PyBool_AS_C(call(std::move(rhs), __contains__, {std::move(lhs)})); if(byte.arg == 1) ret_c = !ret_c; frame->push(PyBool(ret_c)); } break; @@ -200,7 +200,7 @@ private: case OP_UNARY_NOT: { PyVar obj = frame->popValue(this); - PyVar obj_bool = asBool(obj); + const PyVar& obj_bool = asBool(obj); frame->push(PyBool(!PyBool_AS_C(obj_bool))); } break; case OP_POP_JUMP_IF_FALSE: @@ -260,8 +260,8 @@ private: PyVarOrNull iter_fn = getAttr(obj, __iter__, false); if(iter_fn != nullptr){ PyVar tmp = call(iter_fn, {obj}); - PyIter_AS_C(tmp)->var = PyPointer_AS_C(frame->__pop()); - frame->push(tmp); + PyIter_AS_C(tmp)->var = std::move(PyPointer_AS_C(frame->__pop())); + frame->push(std::move(tmp)); }else{ typeError("'" + obj->getTypeName() + "' object is not iterable"); } @@ -269,8 +269,8 @@ private: case OP_FOR_ITER: { frame->__reportForIter(); - const PyVar& iter = frame->topValue(this); - auto& it = PyIter_AS_C(iter); + // __top() must be PyIter, so no need to __deref() + auto& it = PyIter_AS_C(frame->__top()); if(it->hasNext()){ it->var->set(this, frame, it->next()); } @@ -368,20 +368,20 @@ public: return call(obj, __json__, {}); } - PyVar asBool(const PyVar& obj){ + const PyVar& asBool(const PyVar& obj){ if(obj == None) return False; if(obj->_type == _tp_bool) return obj; if(obj->_type == _tp_int) return PyBool(PyInt_AS_C(obj) != 0); if(obj->_type == _tp_float) return PyBool(PyFloat_AS_C(obj) != 0.0); PyVarOrNull len_fn = getAttr(obj, __len__, false); if(len_fn != nullptr){ - PyVar ret = call(len_fn, {}); + PyVar ret = call(std::move(len_fn), {}); return PyBool(PyInt_AS_C(ret) > 0); } return True; } - PyVar fastCall(const PyVar& obj, const _Str& name, PyVarList args){ + PyVar fastCall(const PyVar& obj, const _Str& name, PyVarList&& args){ PyObject* cls = obj->_type.get(); while(cls != None.get()) { auto it = cls->attribs.find(name); @@ -418,7 +418,7 @@ public: } if(callable->isType(_tp_native_function)){ - auto f = std::get<_CppFunc>(callable->_native); + const auto& f = std::get<_CppFunc>(callable->_native); return f(this, args); } else if(callable->isType(_tp_function)){ const _Func& fn = PyFunction_AS_C(callable); @@ -664,8 +664,9 @@ public: DEF_NATIVE(Range, _Range, _tp_range) DEF_NATIVE(Slice, _Slice, _tp_slice) - inline bool PyBool_AS_C(PyVar obj){return obj == True;} - inline PyVar PyBool(bool value){return value ? True : False;} + // there is only one True/False, so no need to copy them! + inline bool PyBool_AS_C(const PyVar& obj){return obj == True;} + inline const PyVar& PyBool(bool value){return value ? True : False;} void initializeBuiltinClasses(){ _tp_object = std::make_shared((_Int)0); @@ -821,13 +822,13 @@ PyVar NamePointer::get(VM* vm, Frame* frame) const{ void NamePointer::set(VM* vm, Frame* frame, PyVar val) const{ switch(scope) { - case NAME_LOCAL: frame->f_locals[name] = val; break; + case NAME_LOCAL: frame->f_locals[name] = std::move(val); break; case NAME_GLOBAL: { if(frame->f_locals.count(name) > 0){ - frame->f_locals[name] = val; + frame->f_locals[name] = std::move(val); }else{ - frame->f_globals()[name] = val; + frame->f_globals()[name] = std::move(val); } } break; default: UNREACHABLE();