mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-22 04:20:17 +00:00
object pool impl
This commit is contained in:
parent
01be71f0ef
commit
e816ceee6c
19
src/common.h
19
src/common.h
@ -31,8 +31,23 @@
|
|||||||
#define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
|
#define UNREACHABLE() throw std::runtime_error( __FILE__ + std::string(":") + std::to_string(__LINE__) + " UNREACHABLE()!");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PK_VERSION "0.8.3"
|
#define PK_VERSION "0.8.4"
|
||||||
|
|
||||||
typedef int64_t i64;
|
typedef int64_t i64;
|
||||||
typedef double f64;
|
typedef double f64;
|
||||||
#define DUMMY_VAL (i64)0
|
#define DUMMY_VAL (char)1
|
||||||
|
#define DUMMY_VAL_TP char
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void* tid() {
|
||||||
|
static volatile int8_t _x;
|
||||||
|
return (void*)(&_x);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This does not ensure to be unique when the pointer of obj->type is deleted & reused.
|
||||||
|
// But it is good enough for now.
|
||||||
|
template<typename T>
|
||||||
|
void* obj_tid(void* alt){
|
||||||
|
if constexpr(std::is_same_v<T, DUMMY_VAL_TP>) return alt;
|
||||||
|
return tid<T>();
|
||||||
|
}
|
14
src/iter.h
14
src/iter.h
@ -22,16 +22,14 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class VectorIter : public BaseIter {
|
template <typename T>
|
||||||
|
class ArrayIter : public BaseIter {
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
const PyVarList* vec;
|
const T* p;
|
||||||
public:
|
public:
|
||||||
VectorIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) {
|
ArrayIter(VM* vm, PyVar _ref) : BaseIter(vm, _ref) { p = &OBJ_GET(T, _ref);}
|
||||||
vec = &OBJ_GET(PyVarList, _ref);
|
bool hasNext(){ return index < p->size(); }
|
||||||
}
|
PyVar next(){ return p->operator[](index++); }
|
||||||
|
|
||||||
bool hasNext(){ return index < vec->size(); }
|
|
||||||
PyVar next(){ return vec->operator[](index++); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class StringIter : public BaseIter {
|
class StringIter : public BaseIter {
|
||||||
|
12
src/memory.h
12
src/memory.h
@ -3,17 +3,25 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
template<typename T>
|
||||||
|
struct sp_deleter {
|
||||||
|
inline static void call(int* counter){
|
||||||
|
((T*)(counter + 1))->~T();
|
||||||
|
free(counter);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class shared_ptr {
|
class shared_ptr {
|
||||||
int* counter = nullptr;
|
int* counter = nullptr;
|
||||||
|
|
||||||
#define _t() ((T*)(counter + 1))
|
#define _t() ((T*)(counter + 1))
|
||||||
#define _inc_counter() if(counter) ++(*counter)
|
#define _inc_counter() if(counter) ++(*counter)
|
||||||
#define _dec_counter() if(counter && --(*counter) == 0){ _t()->~T(); free(counter); }
|
#define _dec_counter() if(counter && --(*counter) == 0){ pkpy::sp_deleter<T>::call(counter); }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
shared_ptr() {}
|
shared_ptr() {}
|
||||||
shared_ptr(int* block) : counter(block) {}
|
shared_ptr(int* counter) : counter(counter) {}
|
||||||
shared_ptr(const shared_ptr& other) : counter(other.counter) {
|
shared_ptr(const shared_ptr& other) : counter(other.counter) {
|
||||||
_inc_counter();
|
_inc_counter();
|
||||||
}
|
}
|
||||||
|
26
src/obj.h
26
src/obj.h
@ -78,7 +78,8 @@ struct PyObject {
|
|||||||
PyVarDict attribs;
|
PyVarDict attribs;
|
||||||
|
|
||||||
inline bool is_type(const PyVar& type) const noexcept{ return this->type == type; }
|
inline bool is_type(const PyVar& type) const noexcept{ return this->type == type; }
|
||||||
inline virtual void* value() = 0;
|
virtual void* value() = 0;
|
||||||
|
virtual void* type_id() = 0;
|
||||||
|
|
||||||
PyObject(const PyVar& type) : type(type) {}
|
PyObject(const PyVar& type) : type(type) {}
|
||||||
virtual ~PyObject() = default;
|
virtual ~PyObject() = default;
|
||||||
@ -89,7 +90,8 @@ struct Py_ : PyObject {
|
|||||||
T _value;
|
T _value;
|
||||||
|
|
||||||
Py_(const PyVar& type, T val) : PyObject(type), _value(val) {}
|
Py_(const PyVar& type, T val) : PyObject(type), _value(val) {}
|
||||||
virtual void* value() override { return &_value; }
|
void* value() override { return &_value; }
|
||||||
|
void* type_id() override { return obj_tid<T>((void*)type.get()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Unsafe cast from PyObject to C++ type
|
// Unsafe cast from PyObject to C++ type
|
||||||
@ -103,3 +105,23 @@ struct Py_ : PyObject {
|
|||||||
inline static const char* _name() { return #name; }
|
inline static const char* _name() { return #name; }
|
||||||
|
|
||||||
#define PY_BUILTIN_CLASS(name) inline static PyVar _type(VM* vm) { return vm->_tp_##name; }
|
#define PY_BUILTIN_CLASS(name) inline static PyVar _type(VM* vm) { return vm->_tp_##name; }
|
||||||
|
|
||||||
|
|
||||||
|
// memory pool _tp -> [obj1, obj2, ...]
|
||||||
|
static thread_local emhash8::HashMap<void*, std::vector<int*>> _obj_pool;
|
||||||
|
|
||||||
|
namespace pkpy {
|
||||||
|
template<>
|
||||||
|
struct sp_deleter<PyObject> {
|
||||||
|
inline static void call(int* counter) {
|
||||||
|
PyObject* obj = (PyObject*)(counter + 1);
|
||||||
|
std::vector<int*>& pool = _obj_pool[obj->type_id()];
|
||||||
|
if(pool.size() > 100){
|
||||||
|
obj->~PyObject();
|
||||||
|
free(counter);
|
||||||
|
}else{
|
||||||
|
pool.push_back(counter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
@ -370,20 +370,23 @@ void init_builtins(VM* _vm) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<1>("str", "join", [](VM* vm, const pkpy::Args& args) {
|
_vm->bind_method<1>("str", "join", [](VM* vm, const pkpy::Args& args) {
|
||||||
const _Str& _self = vm->PyStr_AS_C(args[0]);
|
const _Str& self = vm->PyStr_AS_C(args[0]);
|
||||||
PyVarList* _list = nullptr;
|
_StrStream ss;
|
||||||
if(args[1]->is_type(vm->_tp_list)){
|
if(args[1]->is_type(vm->_tp_list)){
|
||||||
_list = &vm->PyList_AS_C(args[1]);
|
const PyVarList& a = vm->PyList_AS_C(args[1]);
|
||||||
|
for(int i = 0; i < a.size(); i++){
|
||||||
|
if(i > 0) ss << self;
|
||||||
|
ss << vm->PyStr_AS_C(vm->asStr(a[i]));
|
||||||
|
}
|
||||||
}else if(args[1]->is_type(vm->_tp_tuple)){
|
}else if(args[1]->is_type(vm->_tp_tuple)){
|
||||||
_list = &vm->PyTuple_AS_C(args[1]);
|
const _Tuple& a = vm->PyTuple_AS_C(args[1]);
|
||||||
|
for(int i = 0; i < a.size(); i++){
|
||||||
|
if(i > 0) ss << self;
|
||||||
|
ss << vm->PyStr_AS_C(vm->asStr(a[i]));
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
vm->TypeError("can only join a list or tuple");
|
vm->TypeError("can only join a list or tuple");
|
||||||
}
|
}
|
||||||
_StrStream ss;
|
|
||||||
for(int i = 0; i < _list->size(); i++){
|
|
||||||
if(i > 0) ss << _self;
|
|
||||||
ss << vm->PyStr_AS_C(vm->asStr(_list->operator[](i)));
|
|
||||||
}
|
|
||||||
return vm->PyStr(ss.str());
|
return vm->PyStr(ss.str());
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -426,25 +429,24 @@ void init_builtins(VM* _vm) {
|
|||||||
return vm->PyInt(_self.size());
|
return vm->PyInt(_self.size());
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->_bind_methods<0>({"list", "tuple"}, "__iter__", [](VM* vm, const pkpy::Args& args) {
|
_vm->bind_method<0>("list", "__iter__", [](VM* vm, const pkpy::Args& args) {
|
||||||
return vm->PyIter(pkpy::make_shared<BaseIter, VectorIter>(vm, args[0]));
|
return vm->PyIter(pkpy::make_shared<BaseIter, ArrayIter<PyVarList>>(vm, args[0]));
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->_bind_methods<1>({"list", "tuple"}, "__getitem__", [](VM* vm, const pkpy::Args& args) {
|
_vm->bind_method<1>("list", "__getitem__", [](VM* vm, const pkpy::Args& args) {
|
||||||
bool list = args[0]->is_type(vm->_tp_list);
|
const PyVarList& self = vm->PyList_AS_C(args[0]);
|
||||||
const PyVarList& _self = list ? vm->PyList_AS_C(args[0]) : vm->PyTuple_AS_C(args[0]);
|
|
||||||
|
|
||||||
if(args[1]->is_type(vm->_tp_slice)){
|
if(args[1]->is_type(vm->_tp_slice)){
|
||||||
_Slice s = vm->PySlice_AS_C(args[1]);
|
_Slice s = vm->PySlice_AS_C(args[1]);
|
||||||
s.normalize(_self.size());
|
s.normalize(self.size());
|
||||||
PyVarList _new_list;
|
PyVarList new_list;
|
||||||
for(size_t i = s.start; i < s.stop; i++) _new_list.push_back(_self[i]);
|
for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]);
|
||||||
return list ? vm->PyList(_new_list) : vm->PyTuple(_new_list);
|
return vm->PyList(std::move(new_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
int _index = (int)vm->PyInt_AS_C(args[1]);
|
int index = (int)vm->PyInt_AS_C(args[1]);
|
||||||
_index = vm->normalized_index(_index, _self.size());
|
index = vm->normalized_index(index, self.size());
|
||||||
return _self[_index];
|
return self[index];
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<2>("list", "__setitem__", [](VM* vm, const pkpy::Args& args) {
|
_vm->bind_method<2>("list", "__setitem__", [](VM* vm, const pkpy::Args& args) {
|
||||||
@ -466,12 +468,32 @@ void init_builtins(VM* _vm) {
|
|||||||
/************ PyTuple ************/
|
/************ PyTuple ************/
|
||||||
_vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, const pkpy::Args& args) {
|
_vm->bind_static_method<1>("tuple", "__new__", [](VM* vm, const pkpy::Args& args) {
|
||||||
PyVarList _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args));
|
PyVarList _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args));
|
||||||
return vm->PyTuple(_list);
|
return vm->PyTuple(std::move(_list));
|
||||||
|
});
|
||||||
|
|
||||||
|
_vm->bind_method<0>("tuple", "__iter__", [](VM* vm, const pkpy::Args& args) {
|
||||||
|
return vm->PyIter(pkpy::make_shared<BaseIter, ArrayIter<pkpy::Args>>(vm, args[0]));
|
||||||
|
});
|
||||||
|
|
||||||
|
_vm->bind_method<1>("tuple", "__getitem__", [](VM* vm, const pkpy::Args& args) {
|
||||||
|
const _Tuple& self = vm->PyTuple_AS_C(args[0]);
|
||||||
|
|
||||||
|
if(args[1]->is_type(vm->_tp_slice)){
|
||||||
|
_Slice s = vm->PySlice_AS_C(args[1]);
|
||||||
|
s.normalize(self.size());
|
||||||
|
PyVarList new_list;
|
||||||
|
for(size_t i = s.start; i < s.stop; i++) new_list.push_back(self[i]);
|
||||||
|
return vm->PyTuple(std::move(new_list));
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = (int)vm->PyInt_AS_C(args[1]);
|
||||||
|
index = vm->normalized_index(index, self.size());
|
||||||
|
return self[index];
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_method<0>("tuple", "__len__", [](VM* vm, const pkpy::Args& args) {
|
_vm->bind_method<0>("tuple", "__len__", [](VM* vm, const pkpy::Args& args) {
|
||||||
const PyVarList& _self = vm->PyTuple_AS_C(args[0]);
|
const _Tuple& self = vm->PyTuple_AS_C(args[0]);
|
||||||
return vm->PyInt(_self.size());
|
return vm->PyInt(self.size());
|
||||||
});
|
});
|
||||||
|
|
||||||
/************ PyBool ************/
|
/************ PyBool ************/
|
||||||
|
15
src/ref.h
15
src/ref.h
@ -17,8 +17,10 @@ enum NameScope {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct NameRef : BaseRef {
|
struct NameRef : BaseRef {
|
||||||
const std::pair<_Str, NameScope>* pair;
|
std::pair<_Str, NameScope>* _pair;
|
||||||
NameRef(const std::pair<_Str, NameScope>& pair) : pair(&pair) {}
|
inline const _Str& name() const { return _pair->first; }
|
||||||
|
inline NameScope scope() const { return _pair->second; }
|
||||||
|
NameRef(std::pair<_Str, NameScope>& pair) : _pair(&pair) {}
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
@ -27,8 +29,8 @@ struct NameRef : BaseRef {
|
|||||||
|
|
||||||
struct AttrRef : BaseRef {
|
struct AttrRef : BaseRef {
|
||||||
mutable PyVar obj;
|
mutable PyVar obj;
|
||||||
const NameRef attr;
|
NameRef attr;
|
||||||
AttrRef(PyVar obj, const NameRef attr) : obj(obj), attr(attr) {}
|
AttrRef(PyVar obj, NameRef attr) : obj(obj), attr(attr) {}
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
@ -46,9 +48,8 @@ struct IndexRef : BaseRef {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct TupleRef : BaseRef {
|
struct TupleRef : BaseRef {
|
||||||
PyVarList varRefs;
|
_Tuple objs;
|
||||||
TupleRef(const PyVarList& varRefs) : varRefs(varRefs) {}
|
TupleRef(_Tuple&& objs) : objs(std::move(objs)) {}
|
||||||
TupleRef(PyVarList&& varRefs) : varRefs(std::move(varRefs)) {}
|
|
||||||
|
|
||||||
PyVar get(VM* vm, Frame* frame) const;
|
PyVar get(VM* vm, Frame* frame) const;
|
||||||
void set(VM* vm, Frame* frame, PyVar val) const;
|
void set(VM* vm, Frame* frame, PyVar val) const;
|
||||||
|
@ -58,7 +58,7 @@ namespace pkpy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _release(){
|
void _free(){
|
||||||
if(_size == 0 || _args == nullptr) return;
|
if(_size == 0 || _args == nullptr) return;
|
||||||
if(_size >= kMaxPoolSize || _args_pool[_size].size() > 32){
|
if(_size >= kMaxPoolSize || _args_pool[_size].size() > 32){
|
||||||
delete[] _args;
|
delete[] _args;
|
||||||
@ -76,6 +76,12 @@ namespace pkpy {
|
|||||||
for(int i=0; i<_size; i++) _args[i] = other._args[i];
|
for(int i=0; i<_size; i++) _args[i] = other._args[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Args(std::initializer_list<PyVar> a){
|
||||||
|
_alloc(a.size());
|
||||||
|
int i = 0;
|
||||||
|
for(auto& v: a) _args[i++] = v;
|
||||||
|
}
|
||||||
|
|
||||||
Args(Args&& other) noexcept {
|
Args(Args&& other) noexcept {
|
||||||
this->_args = other._args;
|
this->_args = other._args;
|
||||||
this->_size = other._size;
|
this->_size = other._size;
|
||||||
@ -93,7 +99,7 @@ namespace pkpy {
|
|||||||
const PyVar& operator[](int i) const { return _args[i]; }
|
const PyVar& operator[](int i) const { return _args[i]; }
|
||||||
|
|
||||||
Args& operator=(Args&& other) noexcept {
|
Args& operator=(Args&& other) noexcept {
|
||||||
_release();
|
_free();
|
||||||
this->_args = other._args;
|
this->_args = other._args;
|
||||||
this->_size = other._size;
|
this->_size = other._size;
|
||||||
other._args = nullptr;
|
other._args = nullptr;
|
||||||
@ -126,7 +132,7 @@ namespace pkpy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~Args(){ _release(); }
|
~Args(){ _free(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
const Args& no_arg(){
|
const Args& no_arg(){
|
||||||
@ -149,3 +155,5 @@ namespace pkpy {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef pkpy::Args _Tuple;
|
@ -117,8 +117,10 @@ public:
|
|||||||
|
|
||||||
_Str& operator=(const _Str& s){
|
_Str& operator=(const _Str& s){
|
||||||
this->std::string::operator=(s);
|
this->std::string::operator=(s);
|
||||||
if(_u8_index != nullptr) delete _u8_index;
|
if(_u8_index != nullptr){
|
||||||
this->_u8_index = s._u8_index;
|
delete _u8_index;
|
||||||
|
_u8_index = new std::vector<uint16_t>(*s._u8_index);
|
||||||
|
}
|
||||||
this->hash_initialized = s.hash_initialized;
|
this->hash_initialized = s.hash_initialized;
|
||||||
this->_hash = s._hash;
|
this->_hash = s._hash;
|
||||||
return *this;
|
return *this;
|
||||||
@ -128,6 +130,7 @@ public:
|
|||||||
this->std::string::operator=(std::move(s));
|
this->std::string::operator=(std::move(s));
|
||||||
if(_u8_index != nullptr) delete _u8_index;
|
if(_u8_index != nullptr) delete _u8_index;
|
||||||
this->_u8_index = s._u8_index;
|
this->_u8_index = s._u8_index;
|
||||||
|
s._u8_index = nullptr;
|
||||||
this->hash_initialized = s.hash_initialized;
|
this->hash_initialized = s.hash_initialized;
|
||||||
this->_hash = s._hash;
|
this->_hash = s._hash;
|
||||||
return *this;
|
return *this;
|
||||||
|
116
src/vm.h
116
src/vm.h
@ -20,14 +20,14 @@
|
|||||||
|
|
||||||
|
|
||||||
class VM {
|
class VM {
|
||||||
std::vector<PyVar> _small_integers; // [-5, 256]
|
// std::vector<PyVar> _small_integers; // [-5, 256]
|
||||||
std::stack< std::unique_ptr<Frame> > callstack;
|
std::stack< std::unique_ptr<Frame> > callstack;
|
||||||
PyVar _py_op_call;
|
PyVar _py_op_call;
|
||||||
|
|
||||||
PyVar run_frame(Frame* frame){
|
PyVar run_frame(Frame* frame){
|
||||||
while(frame->has_next_bytecode()){
|
while(frame->has_next_bytecode()){
|
||||||
const Bytecode& byte = frame->next_bytecode();
|
const Bytecode& byte = frame->next_bytecode();
|
||||||
// if(frame->_module != builtins){
|
// if(true || frame->_module != builtins){
|
||||||
// printf("%d: %s (%d) %s\n", frame->_ip, OP_NAMES[byte.op], byte.arg, frame->stack_info().c_str());
|
// printf("%d: %s (%d) %s\n", frame->_ip, OP_NAMES[byte.op], byte.arg, frame->stack_info().c_str());
|
||||||
// }
|
// }
|
||||||
switch (byte.op)
|
switch (byte.op)
|
||||||
@ -46,11 +46,11 @@ class VM {
|
|||||||
frame->push(NameRef(frame->co->names[byte.arg]).get(this, frame));
|
frame->push(NameRef(frame->co->names[byte.arg]).get(this, frame));
|
||||||
} break;
|
} break;
|
||||||
case OP_STORE_NAME: {
|
case OP_STORE_NAME: {
|
||||||
const auto& p = frame->co->names[byte.arg];
|
auto& p = frame->co->names[byte.arg];
|
||||||
NameRef(p).set(this, frame, frame->pop_value(this));
|
NameRef(p).set(this, frame, frame->pop_value(this));
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_ATTR_REF: {
|
case OP_BUILD_ATTR_REF: {
|
||||||
const auto& attr = frame->co->names[byte.arg];
|
auto& attr = frame->co->names[byte.arg];
|
||||||
PyVar obj = frame->pop_value(this);
|
PyVar obj = frame->pop_value(this);
|
||||||
frame->push(PyRef(AttrRef(obj, NameRef(attr))));
|
frame->push(PyRef(AttrRef(obj, NameRef(attr))));
|
||||||
} break;
|
} break;
|
||||||
@ -75,14 +75,13 @@ class VM {
|
|||||||
for(int i=0; i<items.size(); i++){
|
for(int i=0; i<items.size(); i++){
|
||||||
if(!items[i]->is_type(_tp_ref)) {
|
if(!items[i]->is_type(_tp_ref)) {
|
||||||
done = true;
|
done = true;
|
||||||
PyVarList values = items.to_list();
|
for(int j=i; j<items.size(); j++) frame->try_deref(this, items[j]);
|
||||||
for(int j=i; j<values.size(); j++) frame->try_deref(this, values[j]);
|
frame->push(PyTuple(std::move(items)));
|
||||||
frame->push(PyTuple(values));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(done) break;
|
if(done) break;
|
||||||
frame->push(PyRef(TupleRef(items.to_list())));
|
frame->push(PyRef(TupleRef(std::move(items))));
|
||||||
} break;
|
} break;
|
||||||
case OP_BUILD_STRING:
|
case OP_BUILD_STRING:
|
||||||
{
|
{
|
||||||
@ -364,10 +363,9 @@ public:
|
|||||||
this->_stdout = new _StrStream();
|
this->_stdout = new _StrStream();
|
||||||
this->_stderr = new _StrStream();
|
this->_stderr = new _StrStream();
|
||||||
}
|
}
|
||||||
initializeBuiltinClasses();
|
|
||||||
|
|
||||||
_small_integers.reserve(270);
|
init_builtin_types();
|
||||||
for(i64 i=-5; i<=256; i++) _small_integers.push_back(new_object(_tp_int, i));
|
// for(i64 i=-5; i<=256; i++) _small_integers.push_back(new_object(_tp_int, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
PyVar asStr(const PyVar& obj){
|
PyVar asStr(const PyVar& obj){
|
||||||
@ -473,8 +471,7 @@ public:
|
|||||||
|
|
||||||
std::vector<_Str> positional_overrided_keys;
|
std::vector<_Str> positional_overrided_keys;
|
||||||
if(!fn->starredArg.empty()){
|
if(!fn->starredArg.empty()){
|
||||||
// handle *args
|
PyVarList vargs; // handle *args
|
||||||
PyVarList vargs;
|
|
||||||
while(i < args.size()) vargs.push_back(args[i++]);
|
while(i < args.size()) vargs.push_back(args[i++]);
|
||||||
locals.emplace(fn->starredArg, PyTuple(std::move(vargs)));
|
locals.emplace(fn->starredArg, PyTuple(std::move(vargs)));
|
||||||
}else{
|
}else{
|
||||||
@ -608,7 +605,14 @@ public:
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
inline PyVar new_object(PyVar type, T _value) {
|
inline PyVar new_object(PyVar type, T _value) {
|
||||||
if(!type->is_type(_tp_type)) UNREACHABLE();
|
if(!type->is_type(_tp_type)) UNREACHABLE();
|
||||||
return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
|
std::vector<int*>& pool = _obj_pool[obj_tid<T>((void*)type.get())];
|
||||||
|
if(pool.empty()) return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
|
||||||
|
int* counter = pool.back(); pool.pop_back();
|
||||||
|
*counter = 1;
|
||||||
|
Py_<T>* obj = (Py_<T>*)(counter + 1);
|
||||||
|
obj->_value = std::move(_value);
|
||||||
|
obj->attribs.clear();
|
||||||
|
return PyVar(counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
@ -810,16 +814,11 @@ public:
|
|||||||
return (const BaseRef*)(obj->value());
|
return (const BaseRef*)(obj->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
__DEF_PY_AS_C(Int, i64, _tp_int)
|
DEF_NATIVE(Int, i64, _tp_int)
|
||||||
inline PyVar PyInt(i64 value) {
|
|
||||||
if(value >= -5 && value <= 256) return _small_integers[value + 5];
|
|
||||||
return new_object(_tp_int, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
DEF_NATIVE(Float, f64, _tp_float)
|
DEF_NATIVE(Float, f64, _tp_float)
|
||||||
DEF_NATIVE(Str, _Str, _tp_str)
|
DEF_NATIVE(Str, _Str, _tp_str)
|
||||||
DEF_NATIVE(List, PyVarList, _tp_list)
|
DEF_NATIVE(List, PyVarList, _tp_list)
|
||||||
DEF_NATIVE(Tuple, PyVarList, _tp_tuple)
|
DEF_NATIVE(Tuple, _Tuple, _tp_tuple)
|
||||||
DEF_NATIVE(Function, _Func, _tp_function)
|
DEF_NATIVE(Function, _Func, _tp_function)
|
||||||
DEF_NATIVE(NativeFunction, _CppFunc, _tp_native_function)
|
DEF_NATIVE(NativeFunction, _CppFunc, _tp_native_function)
|
||||||
DEF_NATIVE(Iter, pkpy::shared_ptr<BaseIter>, _tp_native_iterator)
|
DEF_NATIVE(Iter, pkpy::shared_ptr<BaseIter>, _tp_native_iterator)
|
||||||
@ -832,7 +831,7 @@ public:
|
|||||||
inline bool PyBool_AS_C(const PyVar& obj){return obj == True;}
|
inline bool PyBool_AS_C(const PyVar& obj){return obj == True;}
|
||||||
inline const PyVar& PyBool(bool value){return value ? True : False;}
|
inline const PyVar& PyBool(bool value){return value ? True : False;}
|
||||||
|
|
||||||
void initializeBuiltinClasses(){
|
void init_builtin_types(){
|
||||||
_tp_object = pkpy::make_shared<PyObject, Py_<i64>>(nullptr, DUMMY_VAL);
|
_tp_object = pkpy::make_shared<PyObject, Py_<i64>>(nullptr, DUMMY_VAL);
|
||||||
_tp_type = pkpy::make_shared<PyObject, Py_<i64>>(nullptr, DUMMY_VAL);
|
_tp_type = pkpy::make_shared<PyObject, Py_<i64>>(nullptr, DUMMY_VAL);
|
||||||
_types["object"] = _tp_object;
|
_types["object"] = _tp_object;
|
||||||
@ -890,8 +889,9 @@ public:
|
|||||||
if (obj->is_type(_tp_type)) return (i64)obj.get();
|
if (obj->is_type(_tp_type)) return (i64)obj.get();
|
||||||
if (obj->is_type(_tp_tuple)) {
|
if (obj->is_type(_tp_tuple)) {
|
||||||
i64 x = 1000003;
|
i64 x = 1000003;
|
||||||
for (const auto& item : PyTuple_AS_C(obj)) {
|
const _Tuple& items = PyTuple_AS_C(obj);
|
||||||
i64 y = hash(item);
|
for (int i=0; i<items.size(); i++) {
|
||||||
|
i64 y = hash(items[i]);
|
||||||
x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2)); // recommended by Github Copilot
|
x = x ^ (y + 0x9e3779b9 + (x << 6) + (x >> 2)); // recommended by Github Copilot
|
||||||
}
|
}
|
||||||
return x;
|
return x;
|
||||||
@ -964,26 +964,26 @@ public:
|
|||||||
/***** Pointers' Impl *****/
|
/***** Pointers' Impl *****/
|
||||||
PyVar NameRef::get(VM* vm, Frame* frame) const{
|
PyVar NameRef::get(VM* vm, Frame* frame) const{
|
||||||
PyVar* val;
|
PyVar* val;
|
||||||
val = frame->f_locals().try_get(pair->first);
|
val = frame->f_locals().try_get(name());
|
||||||
if(val) return *val;
|
if(val) return *val;
|
||||||
val = frame->f_globals().try_get(pair->first);
|
val = frame->f_globals().try_get(name());
|
||||||
if(val) return *val;
|
if(val) return *val;
|
||||||
val = vm->builtins->attribs.try_get(pair->first);
|
val = vm->builtins->attribs.try_get(name());
|
||||||
if(val) return *val;
|
if(val) return *val;
|
||||||
vm->NameError(pair->first);
|
vm->NameError(name());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NameRef::set(VM* vm, Frame* frame, PyVar val) const{
|
void NameRef::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
switch(pair->second) {
|
switch(scope()) {
|
||||||
case NAME_LOCAL: frame->f_locals()[pair->first] = std::move(val); break;
|
case NAME_LOCAL: frame->f_locals()[name()] = std::move(val); break;
|
||||||
case NAME_GLOBAL:
|
case NAME_GLOBAL:
|
||||||
{
|
{
|
||||||
PyVar* existing = frame->f_locals().try_get(pair->first);
|
PyVar* existing = frame->f_locals().try_get(name());
|
||||||
if(existing != nullptr){
|
if(existing != nullptr){
|
||||||
*existing = std::move(val);
|
*existing = std::move(val);
|
||||||
}else{
|
}else{
|
||||||
frame->f_globals()[pair->first] = std::move(val);
|
frame->f_globals()[name()] = std::move(val);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
default: UNREACHABLE();
|
default: UNREACHABLE();
|
||||||
@ -991,23 +991,23 @@ void NameRef::set(VM* vm, Frame* frame, PyVar val) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void NameRef::del(VM* vm, Frame* frame) const{
|
void NameRef::del(VM* vm, Frame* frame) const{
|
||||||
switch(pair->second) {
|
switch(scope()) {
|
||||||
case NAME_LOCAL: {
|
case NAME_LOCAL: {
|
||||||
if(frame->f_locals().contains(pair->first)){
|
if(frame->f_locals().contains(name())){
|
||||||
frame->f_locals().erase(pair->first);
|
frame->f_locals().erase(name());
|
||||||
}else{
|
}else{
|
||||||
vm->NameError(pair->first);
|
vm->NameError(name());
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case NAME_GLOBAL:
|
case NAME_GLOBAL:
|
||||||
{
|
{
|
||||||
if(frame->f_locals().contains(pair->first)){
|
if(frame->f_locals().contains(name())){
|
||||||
frame->f_locals().erase(pair->first);
|
frame->f_locals().erase(name());
|
||||||
}else{
|
}else{
|
||||||
if(frame->f_globals().contains(pair->first)){
|
if(frame->f_globals().contains(name())){
|
||||||
frame->f_globals().erase(pair->first);
|
frame->f_globals().erase(name());
|
||||||
}else{
|
}else{
|
||||||
vm->NameError(pair->first);
|
vm->NameError(name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -1016,11 +1016,11 @@ void NameRef::del(VM* vm, Frame* frame) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar AttrRef::get(VM* vm, Frame* frame) const{
|
PyVar AttrRef::get(VM* vm, Frame* frame) const{
|
||||||
return vm->getattr(obj, attr.pair->first);
|
return vm->getattr(obj, attr.name());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttrRef::set(VM* vm, Frame* frame, PyVar val) const{
|
void AttrRef::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
vm->setattr(obj, attr.pair->first, val);
|
vm->setattr(obj, attr.name(), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttrRef::del(VM* vm, Frame* frame) const{
|
void AttrRef::del(VM* vm, Frame* frame) const{
|
||||||
@ -1040,27 +1040,33 @@ void IndexRef::del(VM* vm, Frame* frame) const{
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar TupleRef::get(VM* vm, Frame* frame) const{
|
PyVar TupleRef::get(VM* vm, Frame* frame) const{
|
||||||
PyVarList args(varRefs.size());
|
_Tuple args(objs.size());
|
||||||
for (int i = 0; i < varRefs.size(); i++) {
|
for (int i = 0; i < objs.size(); i++) {
|
||||||
args[i] = vm->PyRef_AS_C(varRefs[i])->get(vm, frame);
|
args[i] = vm->PyRef_AS_C(objs[i])->get(vm, frame);
|
||||||
}
|
}
|
||||||
return vm->PyTuple(args);
|
return vm->PyTuple(std::move(args));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{
|
void TupleRef::set(VM* vm, Frame* frame, PyVar val) const{
|
||||||
if(!val->is_type(vm->_tp_tuple) && !val->is_type(vm->_tp_list)){
|
#define TUPLE_REF_SET() \
|
||||||
|
if(args.size() > objs.size()) vm->ValueError("too many values to unpack"); \
|
||||||
|
if(args.size() < objs.size()) vm->ValueError("not enough values to unpack"); \
|
||||||
|
for (int i = 0; i < objs.size(); i++) vm->PyRef_AS_C(objs[i])->set(vm, frame, args[i]);
|
||||||
|
|
||||||
|
if(val->is_type(vm->_tp_tuple)){
|
||||||
|
const _Tuple& args = OBJ_GET(_Tuple, val);
|
||||||
|
TUPLE_REF_SET()
|
||||||
|
}else if(val->is_type(vm->_tp_list)){
|
||||||
|
const PyVarList& args = OBJ_GET(PyVarList, val);
|
||||||
|
TUPLE_REF_SET()
|
||||||
|
}else{
|
||||||
vm->TypeError("only tuple or list can be unpacked");
|
vm->TypeError("only tuple or list can be unpacked");
|
||||||
}
|
}
|
||||||
const PyVarList& args = OBJ_GET(PyVarList, val);
|
#undef TUPLE_REF_SET
|
||||||
if(args.size() > varRefs.size()) vm->ValueError("too many values to unpack");
|
|
||||||
if(args.size() < varRefs.size()) vm->ValueError("not enough values to unpack");
|
|
||||||
for (int i = 0; i < varRefs.size(); i++) {
|
|
||||||
vm->PyRef_AS_C(varRefs[i])->set(vm, frame, args[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TupleRef::del(VM* vm, Frame* frame) const{
|
void TupleRef::del(VM* vm, Frame* frame) const{
|
||||||
for (auto& r : varRefs) vm->PyRef_AS_C(r)->del(vm, frame);
|
for(int i=0; i<objs.size(); i++) vm->PyRef_AS_C(objs[i])->del(vm, frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***** Frame's Impl *****/
|
/***** Frame's Impl *****/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user