From 429f572c53612bdbc0fdc2701ae8141a956a3677 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 22 May 2023 13:11:28 +0800 Subject: [PATCH] ... --- docs/features/goto.md | 2 - run_profile.sh | 4 +- src/vm.h | 154 ++++++++++++++++++++---------------------- 3 files changed, 75 insertions(+), 85 deletions(-) diff --git a/docs/features/goto.md b/docs/features/goto.md index 1bbc8f3d..5bd346c7 100644 --- a/docs/features/goto.md +++ b/docs/features/goto.md @@ -7,8 +7,6 @@ pkpy supports `goto` and `label` just like C. You are allowed to change the cont ## Syntax -Labels are named a dot `.` and an identifier. - ``` $goto $label diff --git a/run_profile.sh b/run_profile.sh index c868aabc..8ea891ff 100644 --- a/run_profile.sh +++ b/run_profile.sh @@ -1,5 +1,5 @@ -clang++ -pg -O2 -std=c++17 -fno-rtti -stdlib=libc++ -Wall -o pocketpy src/main.cpp -time ./pocketpy benchmarks/primes.py +clang++ -pg -O1 -std=c++17 -fno-rtti -stdlib=libc++ -Wall -o pocketpy src/main.cpp +time ./pocketpy benchmarks/fib.py mv benchmarks/gmon.out . gprof pocketpy gmon.out > gprof.txt rm gmon.out diff --git a/src/vm.h b/src/vm.h index c3f23a91..07cc3310 100644 --- a/src/vm.h +++ b/src/vm.h @@ -568,7 +568,6 @@ public: PyObject* new_module(StrName name); Str disassemble(CodeObject_ co); void init_builtin_types(); - PyObject* _py_call(PyObject** sp_base, PyObject* callable, ArgsView args, ArgsView kwargs); PyObject* getattr(PyObject* obj, StrName name, bool throw_err=true); PyObject* get_unbound_method(PyObject* obj, StrName name, PyObject** self, bool throw_err=true, bool fallback=false); void parse_int_slice(const Slice& s, int length, int& start, int& stop, int& step); @@ -1110,12 +1109,81 @@ inline PyObject* VM::vectorcall(int ARGC, int KWARGC, bool op_call){ ArgsView kwargs(p1, s_data._sp); if(is_non_tagged_type(callable, tp_function)){ - // ret is nullptr or a generator - PyObject* ret = _py_call(p0, callable, args, kwargs); - // stack resetting is handled by _py_call - if(ret != nullptr) return ret; + /*****************_py_call*****************/ + // callable must be a `function` object + if(s_data.is_overflow()) StackOverflowError(); + + const Function& fn = CAST(Function&, callable); + const CodeObject* co = fn.decl->code.get(); + int co_nlocals = co->varnames.size(); + + if(args.size() < fn.argc){ + vm->TypeError(fmt( + "expected ", + fn.argc, + " positional arguments, but got ", + args.size(), + " (", fn.decl->code->name, ')' + )); + } + + // if this function is simple, a.k.a, no kwargs and no *args and not a generator + // we can use a fast path to avoid using buffer copy + if(fn.is_simple){ + if(args.size() > fn.argc) TypeError("too many positional arguments"); + int spaces = co_nlocals - fn.argc; + for(int j=0; jargs) buffer[index] = args[i++]; + // set extra varnames to nullptr + for(int j=i; jkwargs) buffer[kv.key] = kv.value; + + // handle *args + if(fn.decl->starred_arg != -1){ + ArgsView vargs(args.begin() + i, args.end()); + buffer[fn.decl->starred_arg] = VAR(vargs.to_tuple()); + i += vargs.size(); + }else{ + // kwdefaults override + for(auto& kv: fn.decl->kwargs){ + if(i >= args.size()) break; + buffer[kv.key] = args[i++]; + } + if(i < args.size()) TypeError(fmt("too many arguments", " (", fn.decl->code->name, ')')); + } + + for(int i=0; ivarnames_inv.try_get(key); + if(index<0) TypeError(fmt(key.escape(), " is an invalid keyword argument for ", co->name, "()")); + buffer[index] = kwargs[i+1]; + } + + if(co->is_generator){ + s_data.reset(p0); + return _py_generator( + Frame(&s_data, nullptr, co, fn._module, callable), + ArgsView(buffer, buffer + co_nlocals) + ); + } + + // copy buffer back to stack + s_data.reset(args.begin()); + for(int i=0; icode.get(); - int co_nlocals = co->varnames.size(); - - if(args.size() < fn.argc){ - vm->TypeError(fmt( - "expected ", - fn.argc, - " positional arguments, but got ", - args.size(), - " (", fn.decl->code->name, ')' - )); - } - - // if this function is simple, a.k.a, no kwargs and no *args and not a generator - // we can use a fast path to avoid using buffer copy - if(fn.is_simple){ - if(args.size() > fn.argc) TypeError("too many positional arguments"); - int spaces = co_nlocals - fn.argc; - for(int j=0; jargs) buffer[index] = args[i++]; - // set extra varnames to nullptr - for(int j=i; jkwargs) buffer[kv.key] = kv.value; - - // handle *args - if(fn.decl->starred_arg != -1){ - ArgsView vargs(args.begin() + i, args.end()); - buffer[fn.decl->starred_arg] = VAR(vargs.to_tuple()); - i += vargs.size(); - }else{ - // kwdefaults override - for(auto& kv: fn.decl->kwargs){ - if(i >= args.size()) break; - buffer[kv.key] = args[i++]; - } - if(i < args.size()) TypeError(fmt("too many arguments", " (", fn.decl->code->name, ')')); - } - - for(int i=0; ivarnames_inv.try_get(key); - if(index<0) TypeError(fmt(key.escape(), " is an invalid keyword argument for ", co->name, "()")); - buffer[index] = kwargs[i+1]; - } - - - if(co->is_generator){ - s_data.reset(p0); - return _py_generator( - Frame(&s_data, nullptr, co, fn._module, callable), - ArgsView(buffer, buffer + co_nlocals) - ); - } - - // copy buffer back to stack - s_data.reset(args.begin()); - for(int i=0; i