mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-23 04:50:17 +00:00
cache nlocals
This commit is contained in:
parent
1132a6ecff
commit
52d7133e1b
@ -76,6 +76,7 @@ struct CodeObject {
|
|||||||
|
|
||||||
small_vector_2<PyVar, 8> consts; // constants
|
small_vector_2<PyVar, 8> consts; // constants
|
||||||
small_vector_2<StrName, 8> varnames; // local variables
|
small_vector_2<StrName, 8> varnames; // local variables
|
||||||
|
int nlocals; // varnames.size()
|
||||||
|
|
||||||
NameDictInt varnames_inv;
|
NameDictInt varnames_inv;
|
||||||
std::vector<CodeBlock> blocks;
|
std::vector<CodeBlock> blocks;
|
||||||
|
@ -14,7 +14,7 @@ struct FastLocals{
|
|||||||
const CodeObject* co;
|
const CodeObject* co;
|
||||||
PyVar* a;
|
PyVar* a;
|
||||||
|
|
||||||
int size() const{ return co->varnames.size();}
|
int size() const{ return co->nlocals;}
|
||||||
|
|
||||||
PyVar& operator[](int i){ return a[i]; }
|
PyVar& operator[](int i){ return a[i]; }
|
||||||
PyVar operator[](int i) const { return a[i]; }
|
PyVar operator[](int i) const { return a[i]; }
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
|
||||||
CodeObject::CodeObject(std::shared_ptr<SourceData> src, const Str& name):
|
CodeObject::CodeObject(std::shared_ptr<SourceData> src, const Str& name):
|
||||||
src(src), name(name), start_line(-1), end_line(-1) {
|
src(src), name(name), nlocals(0), start_line(-1), end_line(-1) {
|
||||||
blocks.push_back(CodeBlock(CodeBlockType::NO_BLOCK, -1, 0, 0));
|
blocks.push_back(CodeBlock(CodeBlockType::NO_BLOCK, -1, 0, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ namespace pkpy{
|
|||||||
|
|
||||||
// some check here
|
// some check here
|
||||||
auto& codes = ctx()->co->codes;
|
auto& codes = ctx()->co->codes;
|
||||||
if(ctx()->co->varnames.size() > PK_MAX_CO_VARNAMES){
|
if(ctx()->co->nlocals > PK_MAX_CO_VARNAMES){
|
||||||
SyntaxError("maximum number of local variables exceeded");
|
SyntaxError("maximum number of local variables exceeded");
|
||||||
}
|
}
|
||||||
if(ctx()->co->consts.size() > 65530){
|
if(ctx()->co->consts.size() > 65530){
|
||||||
|
@ -111,6 +111,7 @@ namespace pkpy{
|
|||||||
int index = co->varnames_inv.try_get(name);
|
int index = co->varnames_inv.try_get(name);
|
||||||
if(index >= 0) return index;
|
if(index >= 0) return index;
|
||||||
co->varnames.push_back(name);
|
co->varnames.push_back(name);
|
||||||
|
co->nlocals++;
|
||||||
index = co->varnames.size() - 1;
|
index = co->varnames.size() - 1;
|
||||||
co->varnames_inv.set(name, index);
|
co->varnames_inv.set(name, index);
|
||||||
return index;
|
return index;
|
||||||
|
20
src/vm.cpp
20
src/vm.cpp
@ -949,7 +949,6 @@ void VM::__unpack_as_dict(ArgsView args, Dict& dict){
|
|||||||
|
|
||||||
void VM::__prepare_py_call(PyVar* buffer, ArgsView args, ArgsView kwargs, const FuncDecl_& decl){
|
void VM::__prepare_py_call(PyVar* buffer, ArgsView args, ArgsView kwargs, const FuncDecl_& decl){
|
||||||
const CodeObject* co = decl->code.get();
|
const CodeObject* co = decl->code.get();
|
||||||
int co_nlocals = co->varnames.size();
|
|
||||||
int decl_argc = decl->args.size();
|
int decl_argc = decl->args.size();
|
||||||
|
|
||||||
if(args.size() < decl_argc){
|
if(args.size() < decl_argc){
|
||||||
@ -960,7 +959,7 @@ void VM::__prepare_py_call(PyVar* buffer, ArgsView args, ArgsView kwargs, const
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
// prepare args
|
// prepare args
|
||||||
memset(buffer, 0, co_nlocals * sizeof(PyVar));
|
memset(buffer, 0, co->nlocals * sizeof(PyVar));
|
||||||
for(int index: decl->args) buffer[index] = args[i++];
|
for(int index: decl->args) buffer[index] = args[i++];
|
||||||
// prepare kwdefaults
|
// prepare kwdefaults
|
||||||
for(auto& kv: decl->kwargs) buffer[kv.index] = kv.value;
|
for(auto& kv: decl->kwargs) buffer[kv.index] = kv.value;
|
||||||
@ -1036,22 +1035,20 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
|
|
||||||
const Function& fn = PK_OBJ_GET(Function, callable);
|
const Function& fn = PK_OBJ_GET(Function, callable);
|
||||||
const CodeObject* co = fn.decl->code.get();
|
const CodeObject* co = fn.decl->code.get();
|
||||||
int co_nlocals = co->varnames.size();
|
|
||||||
|
|
||||||
switch(fn.decl->type){
|
switch(fn.decl->type){
|
||||||
case FuncType::UNSET: PK_FATAL_ERROR(); break;
|
|
||||||
case FuncType::NORMAL:
|
case FuncType::NORMAL:
|
||||||
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
__prepare_py_call(__vectorcall_buffer, args, kwargs, fn.decl);
|
||||||
// copy buffer back to stack
|
// copy buffer back to stack
|
||||||
s_data.reset(_base + co_nlocals);
|
s_data.reset(_base + co->nlocals);
|
||||||
for(int j=0; j<co_nlocals; j++) _base[j] = __vectorcall_buffer[j];
|
for(int j=0; j<co->nlocals; j++) _base[j] = __vectorcall_buffer[j];
|
||||||
break;
|
break;
|
||||||
case FuncType::SIMPLE:
|
case FuncType::SIMPLE:
|
||||||
if(args.size() != fn.decl->args.size()) TypeError(_S(co->name, "() takes ", fn.decl->args.size(), " positional arguments but ", args.size(), " were given"));
|
if(args.size() != fn.decl->args.size()) TypeError(_S(co->name, "() takes ", fn.decl->args.size(), " positional arguments but ", args.size(), " were given"));
|
||||||
if(!kwargs.empty()) TypeError(_S(co->name, "() takes no keyword arguments"));
|
if(!kwargs.empty()) TypeError(_S(co->name, "() takes no keyword arguments"));
|
||||||
// [callable, <self>, args..., local_vars...]
|
// [callable, <self>, args..., local_vars...]
|
||||||
// ^p0 ^p1 ^_sp
|
// ^p0 ^p1 ^_sp
|
||||||
s_data.reset(_base + co_nlocals);
|
s_data.reset(_base + co->nlocals);
|
||||||
// initialize local variables to PY_NULL
|
// initialize local variables to PY_NULL
|
||||||
memset(p1, 0, (char*)s_data._sp - (char*)p1);
|
memset(p1, 0, (char*)s_data._sp - (char*)p1);
|
||||||
break;
|
break;
|
||||||
@ -1065,8 +1062,13 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
s_data.reset(p0);
|
s_data.reset(p0);
|
||||||
return __py_generator(
|
return __py_generator(
|
||||||
Frame(nullptr, co, fn._module, callable, nullptr),
|
Frame(nullptr, co, fn._module, callable, nullptr),
|
||||||
ArgsView(__vectorcall_buffer, __vectorcall_buffer + co_nlocals)
|
ArgsView(__vectorcall_buffer, __vectorcall_buffer + co->nlocals)
|
||||||
);
|
);
|
||||||
|
#if PK_DEBUG_EXTRA_CHECK
|
||||||
|
default: PK_FATAL_ERROR(); break;
|
||||||
|
#else
|
||||||
|
default: PK_UNREACHABLE()
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
// simple or normal
|
// simple or normal
|
||||||
@ -1080,7 +1082,7 @@ PyVar VM::vectorcall(int ARGC, int KWARGC, bool op_call){
|
|||||||
const auto& f = PK_OBJ_GET(NativeFunc, callable);
|
const auto& f = PK_OBJ_GET(NativeFunc, callable);
|
||||||
PyVar ret;
|
PyVar ret;
|
||||||
if(f.decl != nullptr){
|
if(f.decl != nullptr){
|
||||||
int co_nlocals = f.decl->code->varnames.size();
|
int co_nlocals = f.decl->code->nlocals;
|
||||||
__prepare_py_call(__vectorcall_buffer, args, kwargs, f.decl);
|
__prepare_py_call(__vectorcall_buffer, args, kwargs, f.decl);
|
||||||
// copy buffer back to stack
|
// copy buffer back to stack
|
||||||
s_data.reset(_base + co_nlocals);
|
s_data.reset(_base + co_nlocals);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user