mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20: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
|
||||
class dict:
|
||||
def __init__(self, capacity=16):
|
||||
def __init__(self, capacity=12):
|
||||
self._capacity = capacity
|
||||
self._a = [None] * self._capacity
|
||||
self._len = 0
|
||||
@ -243,7 +243,7 @@ class dict:
|
||||
else:
|
||||
self._a[i] = [key, value]
|
||||
self._len += 1
|
||||
if self._len > self._capacity * 0.8:
|
||||
if self._len > self._capacity * 0.67:
|
||||
self._capacity *= 2
|
||||
self.__rehash()
|
||||
|
||||
|
@ -64,8 +64,8 @@ struct CodeObject {
|
||||
std::map<StrName, int> global_names;
|
||||
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
|
||||
std::map<StrName, int> labels;
|
||||
|
||||
int recommended_hashmap_capacity = 8;
|
||||
|
||||
int ideal_locals_capacity = 4;
|
||||
|
||||
void optimize(VM* vm);
|
||||
|
||||
|
@ -47,7 +47,9 @@ typedef int64_t i64;
|
||||
typedef double f64;
|
||||
#endif
|
||||
|
||||
struct Dummy { char _; };
|
||||
struct Dummy { };
|
||||
struct DummyInstance { };
|
||||
struct DummyModule { };
|
||||
#define DUMMY_VAL Dummy()
|
||||
|
||||
struct Type {
|
||||
@ -67,4 +69,6 @@ struct Type {
|
||||
|
||||
#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 {
|
||||
int _capacity;
|
||||
int _size;
|
||||
float _load_factor;
|
||||
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];
|
||||
}
|
||||
|
||||
@ -38,12 +40,13 @@ struct NameDict {
|
||||
|
||||
int size() const { return _size; }
|
||||
|
||||
//https://github.com/python/cpython/blob/main/Objects/dictobject.c#L175
|
||||
#define HASH_PROBE(key, ok, i) \
|
||||
int i = (key).index % _capacity; \
|
||||
bool ok = false; \
|
||||
while(!_a[i].empty()) { \
|
||||
if(_a[i].first == (key)) { ok = true; break; } \
|
||||
i = (i + 1) % _capacity; \
|
||||
i = (5*i + 1) % _capacity; \
|
||||
}
|
||||
|
||||
#define HASH_PROBE_OVERRIDE(key, ok, i) \
|
||||
@ -51,7 +54,7 @@ struct NameDict {
|
||||
ok = false; \
|
||||
while(!_a[i].empty()) { \
|
||||
if(_a[i].first == (key)) { ok = true; break; } \
|
||||
i = (i + 1) % _capacity; \
|
||||
i = (5*i + 1) % _capacity; \
|
||||
}
|
||||
|
||||
const PyVar& operator[](StrName key) const {
|
||||
@ -65,15 +68,15 @@ struct NameDict {
|
||||
if(!ok) {
|
||||
_a[i].first = key;
|
||||
_size++;
|
||||
if(_size > _capacity * kNameDictLoadFactor){
|
||||
__rehash_2x();
|
||||
if(_size > _capacity * _load_factor){
|
||||
_rehash_2x();
|
||||
HASH_PROBE_OVERRIDE(key, ok, i);
|
||||
}
|
||||
}
|
||||
return _a[i].second;
|
||||
}
|
||||
|
||||
void __rehash_2x(){
|
||||
void _rehash_2x(){
|
||||
NameDictNode* old_a = _a;
|
||||
int old_capacity = _capacity;
|
||||
_capacity *= 2;
|
||||
@ -122,8 +125,8 @@ struct NameDict {
|
||||
if(!ok) {
|
||||
_a[i].first = key;
|
||||
_size++;
|
||||
if(_size > _capacity * kNameDictLoadFactor){
|
||||
__rehash_2x();
|
||||
if(_size > _capacity * _load_factor){
|
||||
_rehash_2x();
|
||||
HASH_PROBE_OVERRIDE(key, ok, i);
|
||||
}
|
||||
}
|
||||
@ -151,4 +154,7 @@ struct NameDict {
|
||||
|
||||
inline iterator begin() const { return iterator(this, 0); }
|
||||
inline iterator end() const { return iterator(this, _capacity); }
|
||||
|
||||
#undef HASH_PROBE
|
||||
#undef HASH_PROBE_OVERRIDE
|
||||
};
|
@ -25,7 +25,7 @@ struct Function {
|
||||
CodeObject_ code;
|
||||
std::vector<StrName> args;
|
||||
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;
|
||||
|
||||
// runtime settings
|
||||
@ -97,8 +97,10 @@ struct Py_ : PyObject {
|
||||
Py_(Type type, T&& val): PyObject(type), _value(std::move(val)) { _init(); }
|
||||
|
||||
inline void _init() noexcept {
|
||||
if constexpr (std::is_same_v<T, Dummy> || std::is_same_v<T, Type>) {
|
||||
_attr = new pkpy::NameDict();
|
||||
if constexpr (std::is_same_v<T, Type> || std::is_same_v<T, DummyModule>) {
|
||||
_attr = new pkpy::NameDict(8, kTypeAttrLoadFactor);
|
||||
}else if constexpr(std::is_same_v<T, DummyInstance>){
|
||||
_attr = new pkpy::NameDict(4, kInstAttrLoadFactor);
|
||||
}else{
|
||||
_attr = nullptr;
|
||||
}
|
||||
|
@ -774,6 +774,22 @@ void add_module_random(VM* vm){
|
||||
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{
|
||||
public:
|
||||
@ -879,21 +895,7 @@ extern "C" {
|
||||
__EXPORT
|
||||
/// Create a virtual machine.
|
||||
VM* pkpy_new_vm(bool use_stdio){
|
||||
VM* vm = 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;
|
||||
return PKPY_ALLOCATE(VM, use_stdio);
|
||||
}
|
||||
|
||||
__EXPORT
|
||||
|
17
src/vm.h
17
src/vm.h
@ -131,7 +131,7 @@ public:
|
||||
if(new_f != nullptr){
|
||||
obj = call(*new_f, args, kwargs, false);
|
||||
}else{
|
||||
obj = new_object(_callable, DUMMY_VAL);
|
||||
obj = new_object(_callable, DummyInstance());
|
||||
PyVarOrNull init_f = getattr(obj, __init__, false);
|
||||
if (init_f != nullptr) call(init_f, args, kwargs, false);
|
||||
}
|
||||
@ -151,7 +151,9 @@ public:
|
||||
return f(this, args);
|
||||
} else if(is_type(*callable, tp_function)){
|
||||
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;
|
||||
|
||||
int i = 0;
|
||||
@ -323,7 +325,7 @@ public:
|
||||
}
|
||||
|
||||
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()));
|
||||
_modules[name] = obj;
|
||||
return obj;
|
||||
@ -635,8 +637,12 @@ public:
|
||||
for (auto& name : pb_types) {
|
||||
setattr(builtins, name, _types[name]);
|
||||
}
|
||||
|
||||
post_init();
|
||||
}
|
||||
|
||||
void post_init();
|
||||
|
||||
i64 hash(const PyVar& obj){
|
||||
if (is_type(obj, tp_str)) return PyStr_AS_C(obj).hash();
|
||||
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){
|
||||
int n = 0;
|
||||
for(auto& p: names) if(p.second == NAME_LOCAL) n++;
|
||||
recommended_hashmap_capacity = (int)(n / kNameDictLoadFactor + 1.5);
|
||||
if(recommended_hashmap_capacity < 2) recommended_hashmap_capacity = 2;
|
||||
int base_n = (int)(n / kLocalsLoadFactor + 1.5);
|
||||
ideal_locals_capacity = 2;
|
||||
while(ideal_locals_capacity < base_n) ideal_locals_capacity *= 2;
|
||||
|
||||
for(int i=1; i<codes.size(); i++){
|
||||
if(codes[i].op == OP_UNARY_NEGATIVE && codes[i-1].op == OP_LOAD_CONST){
|
||||
|
Loading…
x
Reference in New Issue
Block a user