This commit is contained in:
blueloveTH 2023-02-22 18:11:26 +08:00
parent d9c04e6da6
commit 88b6b8066b
7 changed files with 58 additions and 37 deletions

View File

@ -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()

View File

@ -65,7 +65,7 @@ struct CodeObject {
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);

View File

@ -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;

View File

@ -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
};

View File

@ -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;
}

View File

@ -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

View File

@ -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){