some optimize

This commit is contained in:
blueloveTH 2023-02-11 19:14:10 +08:00
parent bf26464089
commit 340f1bb15c
5 changed files with 69 additions and 86 deletions

View File

@ -123,7 +123,7 @@ struct Frame {
std::stack<std::pair<int, std::vector<PyVar>>> s_try_block; std::stack<std::pair<int, std::vector<PyVar>>> s_try_block;
inline pkpy::NameDict& f_locals() noexcept { return *_locals; } inline pkpy::NameDict& f_locals() noexcept { return *_locals; }
inline pkpy::NameDict& f_globals() noexcept { return _module->attribs; } inline pkpy::NameDict& f_globals() noexcept { return _module->attr(); }
Frame(const CodeObject_ co, PyVar _module, pkpy::shared_ptr<pkpy::NameDict> _locals) Frame(const CodeObject_ co, PyVar _module, pkpy::shared_ptr<pkpy::NameDict> _locals)
: co(co), _module(_module), _locals(_locals), id(kFrameGlobalId++) { } : co(co), _module(_module), _locals(_locals), id(kFrameGlobalId++) { }

View File

@ -76,49 +76,39 @@ public:
struct PyObject { struct PyObject {
PyVar type; PyVar type;
pkpy::NameDict attribs; pkpy::NameDict* _attr;
void* _tid; //void* _tid;
inline bool is_attr_valid() const noexcept { return _attr != nullptr; }
inline pkpy::NameDict& attr() noexcept { return *_attr; }
inline PyVar& attr(const Str& name) noexcept { return (*_attr)[name]; }
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; }
virtual void* value() = 0; virtual void* value() = 0;
PyObject(const PyVar& type, void* _tid) : type(type), _tid(_tid) {} PyObject(const PyVar& type) : type(type) {}
virtual ~PyObject() = default; virtual ~PyObject() { delete _attr; }
}; };
template <typename T> template <typename T>
struct Py_ : PyObject { struct Py_ : PyObject {
T _value; T _value;
Py_(const PyVar& type, T val) : PyObject(type, tid<T>()), _value(val) {} Py_(const PyVar& type, T val) : PyObject(type), _value(val) {
if constexpr (std::is_same_v<T, Dummy>
|| std::is_same_v<T, pkpy::Function_> || std::is_same_v<T, pkpy::NativeFunc>) {
_attr = new pkpy::NameDict();
}else{
_attr = nullptr;
}
}
void* value() override { return &_value; } void* value() override { return &_value; }
}; };
#define OBJ_GET(T, obj) (((Py_<T>*)((obj).get()))->_value) #define OBJ_GET(T, obj) (((Py_<T>*)((obj).get()))->_value)
#define OBJ_NAME(obj) OBJ_GET(Str, (obj)->attribs[__name__]) #define OBJ_NAME(obj) OBJ_GET(Str, (obj)->attr(__name__))
#define OBJ_TP_NAME(obj) OBJ_GET(Str, (obj)->type->attribs[__name__]) #define OBJ_TP_NAME(obj) OBJ_GET(Str, (obj)->type->attr(__name__))
#define PY_CLASS(mod, name) \ #define PY_CLASS(mod, name) \
inline static PyVar _type(VM* vm) { return vm->_modules[#mod]->attribs[#name]; } \ inline static PyVar _type(VM* vm) { return vm->_modules[#mod]->attr(#name); } \
inline static const char* _mod() { return #mod; } \ inline static const char* _mod() { return #mod; } \
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; }
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->_tid];
if(obj->_tid==tid<Dummy>() || pool.size() > 32){
obj->~PyObject();
free(counter);
}else{
pool.push_back(counter);
}
}
};
}

View File

@ -122,8 +122,8 @@ void init_builtins(VM* _vm) {
_vm->bind_builtin_func<1>("dir", [](VM* vm, const pkpy::Args& args) { _vm->bind_builtin_func<1>("dir", [](VM* vm, const pkpy::Args& args) {
std::vector<Str> names; std::vector<Str> names;
for (auto& [k, _] : args[0]->attribs) names.push_back(k); for (auto& [k, _] : args[0]->attr()) names.push_back(k);
for (auto& [k, _] : args[0]->type->attribs) { for (auto& [k, _] : args[0]->type->attr()) {
if (k.find("__") == 0) continue; if (k.find("__") == 0) continue;
if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k); if (std::find(names.begin(), names.end(), k) == names.end()) names.push_back(k);
} }
@ -279,14 +279,14 @@ void init_builtins(VM* _vm) {
}); });
_vm->bind_method<0>("str", "__len__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<0>("str", "__len__", [](VM* vm, const pkpy::Args& args) {
const Str& _self = vm->PyStr_AS_C(args[0]); const Str& self = vm->PyStr_AS_C(args[0]);
return vm->PyInt(_self.u8_length()); return vm->PyInt(self.u8_length());
}); });
_vm->bind_method<1>("str", "__contains__", [](VM* vm, const pkpy::Args& args) { _vm->bind_method<1>("str", "__contains__", [](VM* vm, const pkpy::Args& args) {
const Str& _self = vm->PyStr_AS_C(args[0]); const Str& self = vm->PyStr_AS_C(args[0]);
const Str& _other = vm->PyStr_AS_C(args[1]); const Str& other = vm->PyStr_AS_C(args[1]);
return vm->PyBool(_self.find(_other) != Str::npos); return vm->PyBool(self.find(other) != Str::npos);
}); });
_vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0])); _vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0]));
@ -476,7 +476,7 @@ 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) {
pkpy::List _list = vm->PyList_AS_C(vm->call(vm->builtins->attribs["list"], args)); pkpy::List _list = vm->PyList_AS_C(vm->call(vm->builtins->attr("list"), args));
return vm->PyTuple(std::move(_list)); return vm->PyTuple(std::move(_list));
}); });
@ -763,8 +763,8 @@ extern "C" {
/// Return `__repr__` of the result. /// Return `__repr__` of the result.
/// If the variable is not found, return `nullptr`. /// If the variable is not found, return `nullptr`.
char* pkpy_vm_get_global(VM* vm, const char* name){ char* pkpy_vm_get_global(VM* vm, const char* name){
auto it = vm->_main->attribs.find(name); auto it = vm->_main->attr().find(name);
if(it == vm->_main->attribs.end()) return nullptr; if(it == vm->_main->attr().end()) return nullptr;
try{ try{
Str _repr = vm->PyStr_AS_C(vm->asRepr(it->second)); Str _repr = vm->PyStr_AS_C(vm->asRepr(it->second));
return strdup(_repr.c_str()); return strdup(_repr.c_str());

View File

@ -13,11 +13,10 @@ class Str : public std::string {
if(_u8_index != nullptr) return; if(_u8_index != nullptr) return;
_u8_index = new std::vector<uint16_t>(); _u8_index = new std::vector<uint16_t>();
_u8_index->reserve(size()); _u8_index->reserve(size());
if(size() > 65535) throw std::runtime_error("String has more than 65535 bytes."); if(size() > 65535) throw std::runtime_error("str has more than 65535 bytes.");
for(uint16_t i = 0; i < size(); i++){ for(uint16_t i = 0; i < size(); i++){
// https://stackoverflow.com/questions/3911536/utf-8-unicode-whats-with-0xc0-and-0x80 // https://stackoverflow.com/questions/3911536/utf-8-unicode-whats-with-0xc0-and-0x80
if((at(i) & 0xC0) != 0x80) if((at(i) & 0xC0) != 0x80) _u8_index->push_back(i);
_u8_index->push_back(i);
} }
} }
public: public:
@ -35,7 +34,7 @@ public:
} }
} }
Str(Str&& s) : std::string(std::move(s)) { Str(Str&& s) : std::string(std::move(s)) {
if(_u8_index != nullptr) delete _u8_index; delete _u8_index;
_u8_index = s._u8_index; _u8_index = s._u8_index;
s._u8_index = nullptr; s._u8_index = nullptr;
if(s.hash_initialized){ if(s.hash_initialized){
@ -117,8 +116,8 @@ 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; delete _u8_index;
if(s._u8_index != nullptr){
_u8_index = new std::vector<uint16_t>(*s._u8_index); _u8_index = new std::vector<uint16_t>(*s._u8_index);
} }
this->hash_initialized = s.hash_initialized; this->hash_initialized = s.hash_initialized;
@ -128,7 +127,7 @@ public:
Str& operator=(Str&& s){ Str& operator=(Str&& s){
this->std::string::operator=(std::move(s)); this->std::string::operator=(std::move(s));
if(_u8_index != nullptr) delete _u8_index; delete _u8_index;
this->_u8_index = s._u8_index; this->_u8_index = s._u8_index;
s._u8_index = nullptr; s._u8_index = nullptr;
this->hash_initialized = s.hash_initialized; this->hash_initialized = s.hash_initialized;
@ -136,9 +135,7 @@ public:
return *this; return *this;
} }
~Str(){ ~Str(){ delete _u8_index;}
if(_u8_index != nullptr) delete _u8_index;
}
}; };
namespace std { namespace std {

View File

@ -17,7 +17,7 @@
class VM { class VM {
std::stack< std::unique_ptr<Frame> > callstack; std::stack< std::unique_ptr<Frame> > callstack;
PyVar _py_op_call; PyVar _py_op_call;
PyVar _ascii_str_pool[128]; // PyVar _ascii_str_pool[128];
PyVar run_frame(Frame* frame){ PyVar run_frame(Frame* frame){
while(frame->has_next_bytecode()){ while(frame->has_next_bytecode()){
@ -91,7 +91,7 @@ class VM {
frame->push(PyStr(ss.str())); frame->push(PyStr(ss.str()));
} break; } break;
case OP_LOAD_EVAL_FN: { case OP_LOAD_EVAL_FN: {
frame->push(builtins->attribs[m_eval]); frame->push(builtins->attr(m_eval));
} break; } break;
case OP_LIST_APPEND: { case OP_LIST_APPEND: {
pkpy::Args args(2); pkpy::Args args(2);
@ -206,7 +206,7 @@ class VM {
case OP_BUILD_MAP: case OP_BUILD_MAP:
{ {
pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg*2); pkpy::Args items = frame->pop_n_values_reversed(this, byte.arg*2);
PyVar obj = call(builtins->attribs["dict"]); PyVar obj = call(builtins->attr("dict"));
for(int i=0; i<items.size(); i+=2){ for(int i=0; i<items.size(); i+=2){
call(obj, __setitem__, pkpy::two_args(items[i], items[i+1])); call(obj, __setitem__, pkpy::two_args(items[i], items[i+1]));
} }
@ -217,7 +217,7 @@ class VM {
PyVar list = PyList( PyVar list = PyList(
frame->pop_n_values_reversed(this, byte.arg).to_list() frame->pop_n_values_reversed(this, byte.arg).to_list()
); );
PyVar obj = call(builtins->attribs["set"], pkpy::one_arg(list)); PyVar obj = call(builtins->attr("set"), pkpy::one_arg(list));
frame->push(obj); frame->push(obj);
} break; } break;
case OP_DUP_TOP: frame->push(frame->top_value(this)); break; case OP_DUP_TOP: frame->push(frame->top_value(this)); break;
@ -363,7 +363,7 @@ public:
} }
init_builtin_types(); init_builtin_types();
for(int i=0; i<128; i++) _ascii_str_pool[i] = new_object(tp_str, std::string(1, (char)i)); // for(int i=0; i<128; i++) _ascii_str_pool[i] = new_object(tp_str, std::string(1, (char)i));
} }
PyVar asStr(const PyVar& obj){ PyVar asStr(const PyVar& obj){
@ -378,7 +378,7 @@ public:
} }
PyVar asRepr(const PyVar& obj){ PyVar asRepr(const PyVar& obj){
if(obj->is_type(tp_type)) return PyStr("<class '" + OBJ_GET(Str, obj->attribs[__name__]) + "'>"); if(obj->is_type(tp_type)) return PyStr("<class '" + OBJ_GET(Str, obj->attr(__name__)) + "'>");
return call(obj, __repr__); return call(obj, __repr__);
} }
@ -398,9 +398,9 @@ public:
PyVar fast_call(const Str& name, pkpy::Args&& args){ PyVar fast_call(const Str& name, pkpy::Args&& args){
PyObject* cls = args[0]->type.get(); PyObject* cls = args[0]->type.get();
while(cls != None.get()) { while(cls != None.get()) {
PyVar* val = cls->attribs.try_get(name); PyVar* val = cls->attr().try_get(name);
if(val != nullptr) return call(*val, std::move(args)); if(val != nullptr) return call(*val, std::move(args));
cls = cls->attribs[__base__].get(); cls = cls->attr(__base__).get();
} }
AttributeError(args[0], name); AttributeError(args[0], name);
return nullptr; return nullptr;
@ -428,14 +428,14 @@ public:
PyVar call(const PyVar& _callable, pkpy::Args args, const pkpy::Args& kwargs, bool opCall){ PyVar call(const PyVar& _callable, pkpy::Args args, const pkpy::Args& kwargs, bool opCall){
if(_callable->is_type(tp_type)){ if(_callable->is_type(tp_type)){
auto it = _callable->attribs.find(__new__); PyVar* new_f = _callable->attr().try_get(__new__);
PyVar obj; PyVar obj;
if(it != _callable->attribs.end()){ if(new_f != nullptr){
obj = call(it->second, args, kwargs, false); obj = call(*new_f, args, kwargs, false);
}else{ }else{
obj = new_object(_callable, DUMMY_VAL); obj = new_object(_callable, DUMMY_VAL);
PyVarOrNull init_fn = getattr(obj, __init__, false); PyVarOrNull init_f = getattr(obj, __init__, false);
if (init_fn != nullptr) call(init_fn, args, kwargs, false); if (init_f != nullptr) call(init_f, args, kwargs, false);
} }
return obj; return obj;
} }
@ -500,7 +500,7 @@ public:
locals[key] = val; locals[key] = val;
} }
PyVar* it_m = (*callable)->attribs.try_get(__module__); PyVar* it_m = (*callable)->attr().try_get(__module__);
PyVar _module = it_m != nullptr ? *it_m : top_frame()->_module; PyVar _module = it_m != nullptr ? *it_m : top_frame()->_module;
if(opCall){ if(opCall){
_new_frame(fn->code, _module, _locals); _new_frame(fn->code, _module, _locals);
@ -604,15 +604,7 @@ 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();
if constexpr (std::is_same_v<T, Dummy>) return pkpy::make_shared<PyObject, Py_<T>>(type, _value); return pkpy::make_shared<PyObject, Py_<T>>(type, _value);
std::vector<int*>& pool = _obj_pool[tid<T>()];
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>
@ -640,19 +632,21 @@ public:
depth++; depth++;
} }
cls = (*root)->type.get(); cls = (*root)->type.get();
for(int i=0; i<depth; i++) cls = cls->attribs[__base__].get(); for(int i=0; i<depth; i++) cls = cls->attr(__base__).get();
it = (*root)->attribs.find(name); it = (*root)->attr().find(name);
if(it != (*root)->attribs.end()) return it->second; if(it != (*root)->attr().end()) return it->second;
}else{ }else{
it = obj->attribs.find(name); if(obj->is_attr_valid()){
if(it != obj->attribs.end()) return it->second; it = obj->attr().find(name);
if(it != obj->attr().end()) return it->second;
}
cls = obj->type.get(); cls = obj->type.get();
} }
while(cls != None.get()) { while(cls != None.get()) {
it = cls->attribs.find(name); it = cls->attr().find(name);
if(it != cls->attribs.end()){ if(it != cls->attr().end()){
PyVar valueFromCls = it->second; PyVar valueFromCls = it->second;
if(valueFromCls->is_type(tp_function) || valueFromCls->is_type(tp_native_function)){ if(valueFromCls->is_type(tp_function) || valueFromCls->is_type(tp_native_function)){
return PyBoundMethod({obj, std::move(valueFromCls)}); return PyBoundMethod({obj, std::move(valueFromCls)});
@ -660,7 +654,7 @@ public:
return valueFromCls; return valueFromCls;
} }
} }
cls = cls->attribs[__base__].get(); cls = cls->attr()[__base__].get();
} }
if(throw_err) AttributeError(obj, name); if(throw_err) AttributeError(obj, name);
return nullptr; return nullptr;
@ -670,7 +664,8 @@ public:
inline void setattr(PyVar& obj, const Str& name, T&& value) { inline void setattr(PyVar& obj, const Str& name, T&& value) {
PyObject* p = obj.get(); PyObject* p = obj.get();
while(p->is_type(tp_super)) p = static_cast<PyVar*>(p->value())->get(); while(p->is_type(tp_super)) p = static_cast<PyVar*>(p->value())->get();
p->attribs[name] = std::forward<T>(value); if(!p->is_attr_valid()) TypeError("cannot set attribute");
p->attr()[name] = std::forward<T>(value);
} }
template<int ARGC> template<int ARGC>
@ -819,10 +814,11 @@ public:
return OBJ_GET(Str, obj); return OBJ_GET(Str, obj);
} }
inline PyVar PyStr(const Str& value) { inline PyVar PyStr(const Str& value) {
if(value.size() == 1){ // some BUGs here
char c = value.c_str()[0]; // if(value.size() == 1){
if(c > 0) return _ascii_str_pool[(int)c]; // char c = value.c_str()[0];
} // if(c >= 0) return _ascii_str_pool[(int)c];
// }
return new_object(tp_str, value); return new_object(tp_str, value);
} }
@ -980,7 +976,7 @@ PyVar NameRef::get(VM* vm, Frame* frame) const{
if(val) return *val; if(val) return *val;
val = frame->f_globals().try_get(name()); val = frame->f_globals().try_get(name());
if(val) return *val; if(val) return *val;
val = vm->builtins->attribs.try_get(name()); val = vm->builtins->attr().try_get(name());
if(val) return *val; if(val) return *val;
vm->NameError(name()); vm->NameError(name());
return nullptr; return nullptr;