BLUELOVETH 2 years ago
parent
commit
e03ce955fc
7 changed files with 38 additions and 33 deletions
  1. 17 9
      src/ceval.h
  2. 1 1
      src/common.h
  3. 2 2
      src/compiler.h
  4. 6 11
      src/frame.h
  5. 1 0
      src/opcodes.h
  6. 7 7
      src/pocketpy.h
  7. 4 3
      src/vm.h

+ 17 - 9
src/ceval.h

@@ -53,14 +53,22 @@ __NEXT_STEP:;
     case OP_LOAD_NAME: {
         StrName name = frame->co->names[byte.arg];
         PyObject* val;
-        int i = 0;  // names[0] is ensured to be non-null
-        do{
-            val = frame->names[i++]->try_get(name);
-            if(val != nullptr){
-                frame->push(val);
-                DISPATCH();
-            }
-        }while(frame->names[i] != nullptr);
+        val = frame->f_locals().try_get(name);
+        if(val != nullptr) { frame->push(val); DISPATCH(); }
+        val = frame->f_closure_try_get(name);
+        if(val != nullptr) { frame->push(val); DISPATCH(); }
+        val = frame->f_globals().try_get(name);
+        if(val != nullptr) { frame->push(val); DISPATCH(); }
+        val = vm->builtins->attr().try_get(name);
+        if(val != nullptr) { frame->push(val); DISPATCH(); }
+        vm->NameError(name);
+    } DISPATCH();
+    case OP_LOAD_GLOBAL: {
+        StrName name = frame->co->names[byte.arg];
+        PyObject* val = frame->f_globals().try_get(name);
+        if(val != nullptr) { frame->push(val); DISPATCH(); }
+        val = vm->builtins->attr().try_get(name);
+        if(val != nullptr) { frame->push(val); DISPATCH(); }
         vm->NameError(name);
     } DISPATCH();
     case OP_LOAD_ATTR: {
@@ -319,7 +327,7 @@ __NEXT_STEP:;
             }
             CodeObject_ code = compile(source, name.str(), EXEC_MODE);
             PyObject* new_mod = new_module(name);
-            _exec(code, new_mod, builtins);
+            _exec(code, new_mod);
             new_mod->attr()._try_perfect_rehash();
             frame->push(new_mod);
         }else{

+ 1 - 1
src/common.h

@@ -41,7 +41,7 @@
 #define DEBUG_NO_AUTO_GC			0
 #define DEBUG_GC_STATS				0
 
-#define DEBUG_FRAME_USE_POOL		1
+#define DEBUG_FRAME_USE_POOL		0
 
 #if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__)
 #define PK_ENABLE_FILEIO 		0

+ 2 - 2
src/compiler.h

@@ -812,7 +812,7 @@ __SUBSCR_END:
             consume(TK(")"));
         }
         if(super_namei == -1) ctx()->emit(OP_LOAD_NONE, BC_NOARG, prev().line);
-        else ctx()->emit(OP_LOAD_NAME, super_namei, prev().line);
+        else ctx()->emit(OP_LOAD_GLOBAL, super_namei, prev().line);
         ctx()->emit(OP_BEGIN_CLASS, namei, BC_KEEPLINE);
         ctx()->is_compiling_class = true;
         compile_block_body();
@@ -894,7 +894,7 @@ __SUBSCR_END:
                 auto e = make_expr<NameExpr>(decl->name, name_scope());
                 e->emit_store(ctx());
             } else {
-                ctx()->emit(OP_LOAD_NAME, ctx()->add_name(obj_name), prev().line);
+                ctx()->emit(OP_LOAD_GLOBAL, ctx()->add_name(obj_name), prev().line);
                 int index = ctx()->add_name(decl->name);
                 ctx()->emit(OP_STORE_ATTR, index, prev().line);
             }

+ 6 - 11
src/frame.h

@@ -21,21 +21,16 @@ struct Frame {
     NameDict_ _closure;
     const uint64_t id;
     std::vector<std::pair<int, ValueStack>> s_try_block;
-    const NameDict* names[5];     // name resolution array, zero terminated
 
-    NameDict& f_locals() noexcept { return *_locals; }
+    NameDict& f_locals() noexcept { return _locals!=nullptr ? *_locals : _module->attr(); }
     NameDict& f_globals() noexcept { return _module->attr(); }
+    PyObject* f_closure_try_get(StrName name){
+        if(_closure == nullptr) return nullptr;
+        return _closure->try_get(name);
+    }
 
-    Frame(const CodeObject_& co, PyObject* _module, PyObject* builtins, NameDict_ _locals=nullptr, NameDict_ _closure=nullptr)
+    Frame(const CodeObject_& co, PyObject* _module, NameDict_ _locals=nullptr, NameDict_ _closure=nullptr)
             : co(co.get()), _module(_module), _locals(_locals), _closure(_closure), id(kFrameGlobalId++) {
-        memset(names, 0, sizeof(names));
-        int i = 0;
-        if(_locals != nullptr) names[i++] = _locals.get();
-        if(_closure != nullptr) names[i++] = _closure.get();
-        names[i++] = &_module->attr();  // borrowed reference
-        if(builtins != nullptr){
-            names[i++] = &builtins->attr(); // borrowed reference
-        }
     }
 
     const Bytecode& next_bytecode() {

+ 1 - 0
src/opcodes.h

@@ -18,6 +18,7 @@ OPCODE(LOAD_FUNCTION)
 OPCODE(LOAD_NULL)
 /**************************/
 OPCODE(LOAD_NAME)
+OPCODE(LOAD_GLOBAL)
 OPCODE(LOAD_ATTR)
 OPCODE(LOAD_METHOD)
 OPCODE(LOAD_SUBSCR)

+ 7 - 7
src/pocketpy.h

@@ -98,12 +98,12 @@ inline void init_builtins(VM* _vm) {
 
     _vm->bind_builtin_func<1>("eval", [](VM* vm, Args& args) {
         CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<eval>", EVAL_MODE);
-        return vm->_exec(code, vm->top_frame()->_module, vm->builtins, vm->top_frame()->_locals);
+        return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals);
     });
 
     _vm->bind_builtin_func<1>("exec", [](VM* vm, Args& args) {
         CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<exec>", EXEC_MODE);
-        vm->_exec(code, vm->top_frame()->_module, vm->builtins, vm->top_frame()->_locals);
+        vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals);
         return vm->None;
     });
 
@@ -601,7 +601,7 @@ inline void add_module_json(VM* vm){
     vm->bind_func<1>(mod, "loads", [](VM* vm, Args& args) {
         const Str& expr = CAST(Str&, args[0]);
         CodeObject_ code = vm->compile(expr, "<json>", JSON_MODE);
-        return vm->_exec(code, vm->top_frame()->_module, vm->builtins, vm->top_frame()->_locals);
+        return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals);
     });
 
     vm->bind_func<1>(mod, "dumps", CPP_LAMBDA(vm->fast_call(__json__, Args{args[0]})));
@@ -754,7 +754,7 @@ inline void add_module_random(VM* vm){
     PyObject* mod = vm->new_module("random");
     Random::register_class(vm, mod);
     CodeObject_ code = vm->compile(kPythonLibs["random"], "random.py", EXEC_MODE);
-    vm->_exec(code, mod, vm->builtins);
+    vm->_exec(code, mod);
 }
 
 inline void add_module_gc(VM* vm){
@@ -782,11 +782,11 @@ inline void VM::post_init(){
     }
 
     CodeObject_ code = compile(kPythonLibs["builtins"], "<builtins>", EXEC_MODE);
-    this->_exec(code, this->builtins, nullptr);
+    this->_exec(code, this->builtins);
     code = compile(kPythonLibs["_dict"], "<builtins>", EXEC_MODE);
-    this->_exec(code, this->builtins, nullptr);
+    this->_exec(code, this->builtins);
     code = compile(kPythonLibs["_set"], "<builtins>", EXEC_MODE);
-    this->_exec(code, this->builtins, nullptr);
+    this->_exec(code, this->builtins);
 
     // property is defined in builtins.py so we need to add it after builtins is loaded
     _t(tp_object)->attr().set(__class__, property(CPP_LAMBDA(vm->_t(args[0]))));

+ 4 - 3
src/vm.h

@@ -169,7 +169,7 @@ public:
 #if DEBUG_DIS_EXEC
             if(_module == _main) std::cout << disassemble(code) << '\n';
 #endif
-            return _exec(code, _module, builtins);
+            return _exec(code, _module);
         }catch (const Exception& e){
             *_stderr << e.summary() << '\n';
 
@@ -600,7 +600,8 @@ inline Str VM::disassemble(CodeObject_ co){
             case OP_LOAD_CONST:
                 argStr += " (" + CAST(Str, asRepr(co->consts[byte.arg])) + ")";
                 break;
-            case OP_LOAD_NAME: case OP_STORE_LOCAL: case OP_STORE_GLOBAL:
+            case OP_LOAD_NAME: case OP_LOAD_GLOBAL:
+            case OP_STORE_LOCAL: case OP_STORE_GLOBAL:
             case OP_LOAD_ATTR: case OP_LOAD_METHOD: case OP_STORE_ATTR: case OP_DELETE_ATTR:
             case OP_IMPORT_NAME: case OP_BEGIN_CLASS:
             case OP_DELETE_LOCAL: case OP_DELETE_GLOBAL:
@@ -764,7 +765,7 @@ inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, boo
             locals->set(key, kwargs[i+1]);
         }
         PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
-        auto _frame = _new_frame(fn.decl->code, _module, builtins, locals, fn._closure);
+        auto _frame = _new_frame(fn.decl->code, _module, locals, fn._closure);
         if(fn.decl->code->is_generator) return PyIter(Generator(this, std::move(_frame)));
         callstack.push(std::move(_frame));
         if(opCall) return _py_op_call;