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;
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)
: co(co), _module(_module), _locals(_locals), id(kFrameGlobalId++) { }

View File

@ -76,49 +76,39 @@ public:
struct PyObject {
PyVar type;
pkpy::NameDict attribs;
void* _tid;
pkpy::NameDict* _attr;
//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; }
virtual void* value() = 0;
PyObject(const PyVar& type, void* _tid) : type(type), _tid(_tid) {}
virtual ~PyObject() = default;
PyObject(const PyVar& type) : type(type) {}
virtual ~PyObject() { delete _attr; }
};
template <typename T>
struct Py_ : PyObject {
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; }
};
#define OBJ_GET(T, obj) (((Py_<T>*)((obj).get()))->_value)
#define OBJ_NAME(obj) OBJ_GET(Str, (obj)->attribs[__name__])
#define OBJ_TP_NAME(obj) OBJ_GET(Str, (obj)->type->attribs[__name__])
#define OBJ_NAME(obj) OBJ_GET(Str, (obj)->attr(__name__))
#define OBJ_TP_NAME(obj) OBJ_GET(Str, (obj)->type->attr(__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* _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) {
std::vector<Str> names;
for (auto& [k, _] : args[0]->attribs) names.push_back(k);
for (auto& [k, _] : args[0]->type->attribs) {
for (auto& [k, _] : args[0]->attr()) names.push_back(k);
for (auto& [k, _] : args[0]->type->attr()) {
if (k.find("__") == 0) continue;
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) {
const Str& _self = vm->PyStr_AS_C(args[0]);
return vm->PyInt(_self.u8_length());
const Str& self = vm->PyStr_AS_C(args[0]);
return vm->PyInt(self.u8_length());
});
_vm->bind_method<1>("str", "__contains__", [](VM* vm, const pkpy::Args& args) {
const Str& _self = vm->PyStr_AS_C(args[0]);
const Str& _other = vm->PyStr_AS_C(args[1]);
return vm->PyBool(_self.find(_other) != Str::npos);
const Str& self = vm->PyStr_AS_C(args[0]);
const Str& other = vm->PyStr_AS_C(args[1]);
return vm->PyBool(self.find(other) != Str::npos);
});
_vm->bind_method<0>("str", "__str__", CPP_LAMBDA(args[0]));
@ -476,7 +476,7 @@ void init_builtins(VM* _vm) {
/************ PyTuple ************/
_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));
});
@ -763,8 +763,8 @@ extern "C" {
/// Return `__repr__` of the result.
/// If the variable is not found, return `nullptr`.
char* pkpy_vm_get_global(VM* vm, const char* name){
auto it = vm->_main->attribs.find(name);
if(it == vm->_main->attribs.end()) return nullptr;
auto it = vm->_main->attr().find(name);
if(it == vm->_main->attr().end()) return nullptr;
try{
Str _repr = vm->PyStr_AS_C(vm->asRepr(it->second));
return strdup(_repr.c_str());

View File

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

View File

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