diff --git a/include/pocketpy/namedict.h b/include/pocketpy/namedict.h index e7db76d4..de5907b7 100644 --- a/include/pocketpy/namedict.h +++ b/include/pocketpy/namedict.h @@ -184,6 +184,26 @@ while(!_items[i].first.empty()) { \ return &_items[i].second; } + T try_get_likely_found(StrName key) const{ + uint16_t i = key.index & _mask; + if(_items[i].first == key) return _items[i].second; + i = (i + 1) & _mask; + if(_items[i].first == key) return _items[i].second; + i = (i + 1) & _mask; + if(_items[i].first == key) return _items[i].second; + return try_get(key); + } + + T* try_get_2_likely_found(StrName key) { + uint16_t i = key.index & _mask; + if(_items[i].first == key) return &_items[i].second; + i = (i + 1) & _mask; + if(_items[i].first == key) return &_items[i].second; + i = (i + 1) & _mask; + if(_items[i].first == key) return &_items[i].second; + return try_get_2(key); + } + bool contains(StrName key) const { bool ok; uint16_t i; HASH_PROBE_0(key, ok, i); @@ -279,8 +299,11 @@ struct NameDictImpl{ bool contains(StrName key) const { return is_small() ?_small.contains(key) : _large.contains(key); } bool del(StrName key){ return is_small() ?_small.del(key) : _large.del(key); } + V try_get_likely_found(StrName key) const { return is_small() ?_small.try_get(key) : _large.try_get_likely_found(key); } + V* try_get_2_likely_found(StrName key) { return is_small() ?_small.try_get_2(key) : _large.try_get_2_likely_found(key); } + V operator[](StrName key) const { - V val = try_get(key); + V val = try_get_likely_found(key); if(val == default_invalid_value()){ throw std::runtime_error(fmt("NameDict key not found: ", key.escape())); } diff --git a/src/ceval.cpp b/src/ceval.cpp index 25b61a9e..d0a71366 100644 --- a/src/ceval.cpp +++ b/src/ceval.cpp @@ -121,9 +121,9 @@ __NEXT_STEP:; } _0 = frame->f_closure_try_get(_name); if(_0 != nullptr) { PUSH(_0); DISPATCH(); } - _0 = frame->f_globals().try_get(_name); + _0 = frame->f_globals().try_get_likely_found(_name); if(_0 != nullptr) { PUSH(_0); DISPATCH(); } - _0 = vm->builtins->attr().try_get(_name); + _0 = vm->builtins->attr().try_get_likely_found(_name); if(_0 != nullptr) { PUSH(_0); DISPATCH(); } vm->NameError(_name); } DISPATCH(); @@ -132,18 +132,18 @@ __NEXT_STEP:; _name = StrName(byte.arg); _0 = frame->f_closure_try_get(_name); if(_0 != nullptr) { PUSH(_0); DISPATCH(); } - _0 = frame->f_globals().try_get(_name); + _0 = frame->f_globals().try_get_likely_found(_name); if(_0 != nullptr) { PUSH(_0); DISPATCH(); } - _0 = vm->builtins->attr().try_get(_name); + _0 = vm->builtins->attr().try_get_likely_found(_name); if(_0 != nullptr) { PUSH(_0); DISPATCH(); } vm->NameError(_name); } DISPATCH(); TARGET(LOAD_GLOBAL) heap._auto_collect(); _name = StrName(byte.arg); - _0 = frame->f_globals().try_get(_name); + _0 = frame->f_globals().try_get_likely_found(_name); if(_0 != nullptr) { PUSH(_0); DISPATCH(); } - _0 = vm->builtins->attr().try_get(_name); + _0 = vm->builtins->attr().try_get_likely_found(_name); if(_0 != nullptr) { PUSH(_0); DISPATCH(); } vm->NameError(_name); DISPATCH(); @@ -236,7 +236,7 @@ __NEXT_STEP:; /*****************************************/ TARGET(BUILD_LONG) { PK_LOCAL_STATIC const StrName m_long("long"); - _0 = builtins->attr().try_get(m_long); + _0 = builtins->attr().try_get_likely_found(m_long); if(_0 == nullptr) AttributeError(builtins, m_long); TOP() = call(_0, TOP()); } DISPATCH(); @@ -493,7 +493,7 @@ __NEXT_STEP:; DISPATCH(); TARGET(GOTO) { _name = StrName(byte.arg); - int index = co->labels.try_get(_name); + int index = co->labels.try_get_likely_found(_name); if(index < 0) _error("KeyError", fmt("label ", _name.escape(), " not found")); frame->jump_abs_break(index); } DISPATCH(); @@ -607,7 +607,7 @@ __NEXT_STEP:; if(_1 != nullptr){ for(PyObject* key: CAST(List&, _1)){ _name = StrName::get(CAST(Str&, key).sv()); - PyObject* value = _0->attr().try_get(_name); + PyObject* value = _0->attr().try_get_likely_found(_name); if(value == nullptr){ ImportError(fmt("cannot import name ", _name.escape())); }else{ @@ -716,13 +716,13 @@ __NEXT_STEP:; } DISPATCH(); TARGET(INC_GLOBAL){ _name = StrName(byte.arg); - PyObject** p = frame->f_globals().try_get_2(_name); + PyObject** p = frame->f_globals().try_get_2_likely_found(_name); if(p == nullptr) vm->NameError(_name); *p = VAR(CAST(i64, *p) + 1); } DISPATCH(); TARGET(DEC_GLOBAL){ _name = StrName(byte.arg); - PyObject** p = frame->f_globals().try_get_2(_name); + PyObject** p = frame->f_globals().try_get_2_likely_found(_name); if(p == nullptr) vm->NameError(_name); *p = VAR(CAST(i64, *p) - 1); } DISPATCH(); diff --git a/src/pocketpy.cpp b/src/pocketpy.cpp index 76e4b5c4..10ccfa1e 100644 --- a/src/pocketpy.cpp +++ b/src/pocketpy.cpp @@ -123,7 +123,7 @@ void init_builtins(VM* _vm) { }else if(args.size() == 0){ FrameId frame = vm->top_frame(); if(frame->_callable != nullptr){ - class_arg = frame->_callable->attr().try_get(__class__); + class_arg = frame->_callable->attr().try_get_likely_found(__class__); if(frame->_locals.size() > 0) self_arg = frame->_locals[0]; } if(class_arg == nullptr || self_arg == nullptr){ diff --git a/src/vm.cpp b/src/vm.cpp index e54ec1ef..f84c3101 100644 --- a/src/vm.cpp +++ b/src/vm.cpp @@ -150,7 +150,7 @@ namespace pkpy{ } PyObject* VM::_find_type_object(const Str& type){ - PyObject* obj = builtins->attr().try_get(type); + PyObject* obj = builtins->attr().try_get_likely_found(type); if(obj == nullptr){ for(auto& t: _all_types) if(t.name == type) return t.obj; throw std::runtime_error(fmt("type not found: ", type)); @@ -166,7 +166,7 @@ namespace pkpy{ } PyTypeInfo* VM::_type_info(const Str& type){ - PyObject* obj = builtins->attr().try_get(type); + PyObject* obj = builtins->attr().try_get_likely_found(type); if(obj == nullptr){ for(auto& t: _all_types) if(t.name == type) return &t; FATAL_ERROR(); @@ -548,7 +548,7 @@ Str VM::disassemble(CodeObject_ co){ } if(byte.op == OP_GOTO){ // TODO: pre-compute jump targets for OP_GOTO - int* target = co->labels.try_get_2(StrName(byte.arg)); + int* target = co->labels.try_get_2_likely_found(StrName(byte.arg)); if(target != nullptr) jumpTargets.push_back(*target); } } @@ -776,7 +776,7 @@ void VM::_prepare_py_call(PyObject** buffer, ArgsView args, ArgsView kwargs, con for(int j=0; jvarnames_inv.try_get(key); + int index = co->varnames_inv.try_get_likely_found(key); if(index < 0){ if(vkwargs == nullptr){ TypeError(fmt(key.escape(), " is an invalid keyword argument for ", co->name, "()"));