mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
some optimize
This commit is contained in:
parent
bf26464089
commit
340f1bb15c
@ -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++) { }
|
||||
|
46
src/obj.h
46
src/obj.h
@ -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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -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());
|
||||
|
17
src/str.h
17
src/str.h
@ -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 {
|
||||
|
70
src/vm.h
70
src/vm.h
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user