mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
up
This commit is contained in:
parent
d9c04e6da6
commit
88b6b8066b
@ -210,7 +210,7 @@ list.__new__ = lambda obj: [i for i in obj]
|
|||||||
|
|
||||||
# https://github.com/python/cpython/blob/main/Objects/dictobject.c
|
# https://github.com/python/cpython/blob/main/Objects/dictobject.c
|
||||||
class dict:
|
class dict:
|
||||||
def __init__(self, capacity=16):
|
def __init__(self, capacity=12):
|
||||||
self._capacity = capacity
|
self._capacity = capacity
|
||||||
self._a = [None] * self._capacity
|
self._a = [None] * self._capacity
|
||||||
self._len = 0
|
self._len = 0
|
||||||
@ -243,7 +243,7 @@ class dict:
|
|||||||
else:
|
else:
|
||||||
self._a[i] = [key, value]
|
self._a[i] = [key, value]
|
||||||
self._len += 1
|
self._len += 1
|
||||||
if self._len > self._capacity * 0.8:
|
if self._len > self._capacity * 0.67:
|
||||||
self._capacity *= 2
|
self._capacity *= 2
|
||||||
self.__rehash()
|
self.__rehash()
|
||||||
|
|
||||||
|
@ -64,8 +64,8 @@ struct CodeObject {
|
|||||||
std::map<StrName, int> global_names;
|
std::map<StrName, int> global_names;
|
||||||
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
|
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
|
||||||
std::map<StrName, int> labels;
|
std::map<StrName, int> labels;
|
||||||
|
|
||||||
int recommended_hashmap_capacity = 8;
|
int ideal_locals_capacity = 4;
|
||||||
|
|
||||||
void optimize(VM* vm);
|
void optimize(VM* vm);
|
||||||
|
|
||||||
|
@ -47,7 +47,9 @@ typedef int64_t i64;
|
|||||||
typedef double f64;
|
typedef double f64;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct Dummy { char _; };
|
struct Dummy { };
|
||||||
|
struct DummyInstance { };
|
||||||
|
struct DummyModule { };
|
||||||
#define DUMMY_VAL Dummy()
|
#define DUMMY_VAL Dummy()
|
||||||
|
|
||||||
struct Type {
|
struct Type {
|
||||||
@ -67,4 +69,6 @@ struct Type {
|
|||||||
|
|
||||||
#define RAW(T) std::remove_const_t<std::remove_reference_t<T>>
|
#define RAW(T) std::remove_const_t<std::remove_reference_t<T>>
|
||||||
|
|
||||||
const float kNameDictLoadFactor = 0.8;
|
const float kLocalsLoadFactor = 0.8;
|
||||||
|
const float kInstAttrLoadFactor = 0.67;
|
||||||
|
const float kTypeAttrLoadFactor = 0.34;
|
@ -11,9 +11,11 @@ struct NameDictNode{
|
|||||||
struct NameDict {
|
struct NameDict {
|
||||||
int _capacity;
|
int _capacity;
|
||||||
int _size;
|
int _size;
|
||||||
|
float _load_factor;
|
||||||
NameDictNode* _a;
|
NameDictNode* _a;
|
||||||
|
|
||||||
NameDict(int capacity=2): _capacity(capacity), _size(0) {
|
NameDict(int capacity=4, float load_factor=0.67):
|
||||||
|
_capacity(capacity), _size(0), _load_factor(load_factor) {
|
||||||
_a = new NameDictNode[_capacity];
|
_a = new NameDictNode[_capacity];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -38,12 +40,13 @@ struct NameDict {
|
|||||||
|
|
||||||
int size() const { return _size; }
|
int size() const { return _size; }
|
||||||
|
|
||||||
|
//https://github.com/python/cpython/blob/main/Objects/dictobject.c#L175
|
||||||
#define HASH_PROBE(key, ok, i) \
|
#define HASH_PROBE(key, ok, i) \
|
||||||
int i = (key).index % _capacity; \
|
int i = (key).index % _capacity; \
|
||||||
bool ok = false; \
|
bool ok = false; \
|
||||||
while(!_a[i].empty()) { \
|
while(!_a[i].empty()) { \
|
||||||
if(_a[i].first == (key)) { ok = true; break; } \
|
if(_a[i].first == (key)) { ok = true; break; } \
|
||||||
i = (i + 1) % _capacity; \
|
i = (5*i + 1) % _capacity; \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define HASH_PROBE_OVERRIDE(key, ok, i) \
|
#define HASH_PROBE_OVERRIDE(key, ok, i) \
|
||||||
@ -51,7 +54,7 @@ struct NameDict {
|
|||||||
ok = false; \
|
ok = false; \
|
||||||
while(!_a[i].empty()) { \
|
while(!_a[i].empty()) { \
|
||||||
if(_a[i].first == (key)) { ok = true; break; } \
|
if(_a[i].first == (key)) { ok = true; break; } \
|
||||||
i = (i + 1) % _capacity; \
|
i = (5*i + 1) % _capacity; \
|
||||||
}
|
}
|
||||||
|
|
||||||
const PyVar& operator[](StrName key) const {
|
const PyVar& operator[](StrName key) const {
|
||||||
@ -65,15 +68,15 @@ struct NameDict {
|
|||||||
if(!ok) {
|
if(!ok) {
|
||||||
_a[i].first = key;
|
_a[i].first = key;
|
||||||
_size++;
|
_size++;
|
||||||
if(_size > _capacity * kNameDictLoadFactor){
|
if(_size > _capacity * _load_factor){
|
||||||
__rehash_2x();
|
_rehash_2x();
|
||||||
HASH_PROBE_OVERRIDE(key, ok, i);
|
HASH_PROBE_OVERRIDE(key, ok, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _a[i].second;
|
return _a[i].second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __rehash_2x(){
|
void _rehash_2x(){
|
||||||
NameDictNode* old_a = _a;
|
NameDictNode* old_a = _a;
|
||||||
int old_capacity = _capacity;
|
int old_capacity = _capacity;
|
||||||
_capacity *= 2;
|
_capacity *= 2;
|
||||||
@ -122,8 +125,8 @@ struct NameDict {
|
|||||||
if(!ok) {
|
if(!ok) {
|
||||||
_a[i].first = key;
|
_a[i].first = key;
|
||||||
_size++;
|
_size++;
|
||||||
if(_size > _capacity * kNameDictLoadFactor){
|
if(_size > _capacity * _load_factor){
|
||||||
__rehash_2x();
|
_rehash_2x();
|
||||||
HASH_PROBE_OVERRIDE(key, ok, i);
|
HASH_PROBE_OVERRIDE(key, ok, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,4 +154,7 @@ struct NameDict {
|
|||||||
|
|
||||||
inline iterator begin() const { return iterator(this, 0); }
|
inline iterator begin() const { return iterator(this, 0); }
|
||||||
inline iterator end() const { return iterator(this, _capacity); }
|
inline iterator end() const { return iterator(this, _capacity); }
|
||||||
|
|
||||||
|
#undef HASH_PROBE
|
||||||
|
#undef HASH_PROBE_OVERRIDE
|
||||||
};
|
};
|
@ -25,7 +25,7 @@ struct Function {
|
|||||||
CodeObject_ code;
|
CodeObject_ code;
|
||||||
std::vector<StrName> args;
|
std::vector<StrName> args;
|
||||||
StrName starred_arg; // empty if no *arg
|
StrName starred_arg; // empty if no *arg
|
||||||
pkpy::NameDict kwargs; // empty if no k=v
|
pkpy::NameDict kwargs; // empty if no k=v
|
||||||
std::vector<StrName> kwargs_order;
|
std::vector<StrName> kwargs_order;
|
||||||
|
|
||||||
// runtime settings
|
// runtime settings
|
||||||
@ -97,8 +97,10 @@ struct Py_ : PyObject {
|
|||||||
Py_(Type type, T&& val): PyObject(type), _value(std::move(val)) { _init(); }
|
Py_(Type type, T&& val): PyObject(type), _value(std::move(val)) { _init(); }
|
||||||
|
|
||||||
inline void _init() noexcept {
|
inline void _init() noexcept {
|
||||||
if constexpr (std::is_same_v<T, Dummy> || std::is_same_v<T, Type>) {
|
if constexpr (std::is_same_v<T, Type> || std::is_same_v<T, DummyModule>) {
|
||||||
_attr = new pkpy::NameDict();
|
_attr = new pkpy::NameDict(8, kTypeAttrLoadFactor);
|
||||||
|
}else if constexpr(std::is_same_v<T, DummyInstance>){
|
||||||
|
_attr = new pkpy::NameDict(4, kInstAttrLoadFactor);
|
||||||
}else{
|
}else{
|
||||||
_attr = nullptr;
|
_attr = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -774,6 +774,22 @@ void add_module_random(VM* vm){
|
|||||||
vm->_exec(code, mod);
|
vm->_exec(code, mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VM::post_init(){
|
||||||
|
init_builtins(this);
|
||||||
|
add_module_sys(this);
|
||||||
|
add_module_time(this);
|
||||||
|
add_module_json(this);
|
||||||
|
add_module_math(this);
|
||||||
|
add_module_re(this);
|
||||||
|
add_module_dis(this);
|
||||||
|
add_module_random(this);
|
||||||
|
add_module_io(this);
|
||||||
|
add_module_os(this);
|
||||||
|
|
||||||
|
CodeObject_ code = compile(kBuiltinsCode, "<builtins>", EXEC_MODE);
|
||||||
|
this->_exec(code, this->builtins);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class _PkExported{
|
class _PkExported{
|
||||||
public:
|
public:
|
||||||
@ -879,21 +895,7 @@ extern "C" {
|
|||||||
__EXPORT
|
__EXPORT
|
||||||
/// Create a virtual machine.
|
/// Create a virtual machine.
|
||||||
VM* pkpy_new_vm(bool use_stdio){
|
VM* pkpy_new_vm(bool use_stdio){
|
||||||
VM* vm = PKPY_ALLOCATE(VM, use_stdio);
|
return PKPY_ALLOCATE(VM, use_stdio);
|
||||||
init_builtins(vm);
|
|
||||||
add_module_sys(vm);
|
|
||||||
add_module_time(vm);
|
|
||||||
add_module_json(vm);
|
|
||||||
add_module_math(vm);
|
|
||||||
add_module_re(vm);
|
|
||||||
add_module_dis(vm);
|
|
||||||
add_module_random(vm);
|
|
||||||
add_module_io(vm);
|
|
||||||
add_module_os(vm);
|
|
||||||
|
|
||||||
CodeObject_ code = vm->compile(kBuiltinsCode, "<builtins>", EXEC_MODE);
|
|
||||||
vm->_exec(code, vm->builtins);
|
|
||||||
return vm;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__EXPORT
|
__EXPORT
|
||||||
|
17
src/vm.h
17
src/vm.h
@ -131,7 +131,7 @@ public:
|
|||||||
if(new_f != nullptr){
|
if(new_f != nullptr){
|
||||||
obj = call(*new_f, args, kwargs, false);
|
obj = call(*new_f, args, kwargs, false);
|
||||||
}else{
|
}else{
|
||||||
obj = new_object(_callable, DUMMY_VAL);
|
obj = new_object(_callable, DummyInstance());
|
||||||
PyVarOrNull init_f = getattr(obj, __init__, false);
|
PyVarOrNull init_f = getattr(obj, __init__, false);
|
||||||
if (init_f != nullptr) call(init_f, args, kwargs, false);
|
if (init_f != nullptr) call(init_f, args, kwargs, false);
|
||||||
}
|
}
|
||||||
@ -151,7 +151,9 @@ public:
|
|||||||
return f(this, args);
|
return f(this, args);
|
||||||
} else if(is_type(*callable, tp_function)){
|
} else if(is_type(*callable, tp_function)){
|
||||||
const pkpy::Function& fn = PyFunction_AS_C(*callable);
|
const pkpy::Function& fn = PyFunction_AS_C(*callable);
|
||||||
auto _locals = pkpy::make_shared<pkpy::NameDict>(fn.code->recommended_hashmap_capacity);
|
auto _locals = pkpy::make_shared<pkpy::NameDict>(
|
||||||
|
fn.code->ideal_locals_capacity, kLocalsLoadFactor
|
||||||
|
);
|
||||||
pkpy::NameDict& locals = *_locals;
|
pkpy::NameDict& locals = *_locals;
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@ -323,7 +325,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyVar new_module(StrName name) {
|
PyVar new_module(StrName name) {
|
||||||
PyVar obj = new_object(tp_module, DUMMY_VAL);
|
PyVar obj = new_object(tp_module, DummyModule());
|
||||||
setattr(obj, __name__, PyStr(name.str()));
|
setattr(obj, __name__, PyStr(name.str()));
|
||||||
_modules[name] = obj;
|
_modules[name] = obj;
|
||||||
return obj;
|
return obj;
|
||||||
@ -635,8 +637,12 @@ public:
|
|||||||
for (auto& name : pb_types) {
|
for (auto& name : pb_types) {
|
||||||
setattr(builtins, name, _types[name]);
|
setattr(builtins, name, _types[name]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
post_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void post_init();
|
||||||
|
|
||||||
i64 hash(const PyVar& obj){
|
i64 hash(const PyVar& obj){
|
||||||
if (is_type(obj, tp_str)) return PyStr_AS_C(obj).hash();
|
if (is_type(obj, tp_str)) return PyStr_AS_C(obj).hash();
|
||||||
if (is_int(obj)) return PyInt_AS_C(obj);
|
if (is_int(obj)) return PyInt_AS_C(obj);
|
||||||
@ -860,8 +866,9 @@ PyVar pkpy::NativeFunc::operator()(VM* vm, pkpy::Args& args) const{
|
|||||||
void CodeObject::optimize(VM* vm){
|
void CodeObject::optimize(VM* vm){
|
||||||
int n = 0;
|
int n = 0;
|
||||||
for(auto& p: names) if(p.second == NAME_LOCAL) n++;
|
for(auto& p: names) if(p.second == NAME_LOCAL) n++;
|
||||||
recommended_hashmap_capacity = (int)(n / kNameDictLoadFactor + 1.5);
|
int base_n = (int)(n / kLocalsLoadFactor + 1.5);
|
||||||
if(recommended_hashmap_capacity < 2) recommended_hashmap_capacity = 2;
|
ideal_locals_capacity = 2;
|
||||||
|
while(ideal_locals_capacity < base_n) ideal_locals_capacity *= 2;
|
||||||
|
|
||||||
for(int i=1; i<codes.size(); i++){
|
for(int i=1; i<codes.size(); i++){
|
||||||
if(codes[i].op == OP_UNARY_NEGATIVE && codes[i-1].op == OP_LOAD_CONST){
|
if(codes[i].op == OP_UNARY_NEGATIVE && codes[i-1].op == OP_LOAD_CONST){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user