mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
reduce bytecode size
This commit is contained in:
parent
ffde186dfa
commit
1afef9dcb9
@ -21,8 +21,7 @@ inline const char* OP_NAMES[] = {
|
|||||||
|
|
||||||
struct Bytecode{
|
struct Bytecode{
|
||||||
uint8_t op;
|
uint8_t op;
|
||||||
uint16_t block;
|
uint16_t arg;
|
||||||
int arg;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CodeBlockType {
|
enum CodeBlockType {
|
||||||
@ -33,7 +32,7 @@ enum CodeBlockType {
|
|||||||
TRY_EXCEPT,
|
TRY_EXCEPT,
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const int BC_NOARG = -1;
|
inline const uint8_t BC_NOARG = 0;
|
||||||
inline const int BC_KEEPLINE = -1;
|
inline const int BC_KEEPLINE = -1;
|
||||||
|
|
||||||
struct CodeBlock {
|
struct CodeBlock {
|
||||||
@ -103,7 +102,8 @@ struct CodeObject {
|
|||||||
bool is_generator = false;
|
bool is_generator = false;
|
||||||
|
|
||||||
std::vector<Bytecode> codes;
|
std::vector<Bytecode> codes;
|
||||||
std::vector<int> lines; // line number for each bytecode
|
std::vector<int> iblocks; // block index for each bytecode
|
||||||
|
std::vector<int> lines; // line number for each bytecode
|
||||||
List consts;
|
List consts;
|
||||||
std::vector<StrName> varnames; // local variables
|
std::vector<StrName> varnames; // local variables
|
||||||
NameDictInt varnames_inv;
|
NameDictInt varnames_inv;
|
||||||
@ -111,6 +111,10 @@ struct CodeObject {
|
|||||||
NameDictInt labels;
|
NameDictInt labels;
|
||||||
std::vector<FuncDecl_> func_decls;
|
std::vector<FuncDecl_> func_decls;
|
||||||
|
|
||||||
|
const CodeBlock& _get_block_codei(int codei) const{
|
||||||
|
return blocks[iblocks[codei]];
|
||||||
|
}
|
||||||
|
|
||||||
CodeObject(std::shared_ptr<SourceData> src, const Str& name);
|
CodeObject(std::shared_ptr<SourceData> src, const Str& name);
|
||||||
void _gc_mark() const;
|
void _gc_mark() const;
|
||||||
void write(VM* vm, CodeObjectSerializer& ss) const;
|
void write(VM* vm, CodeObjectSerializer& ss) const;
|
||||||
|
@ -52,7 +52,7 @@
|
|||||||
|
|
||||||
// This is the maximum number of arguments in a function declaration
|
// This is the maximum number of arguments in a function declaration
|
||||||
// including positional arguments, keyword-only arguments, and varargs
|
// including positional arguments, keyword-only arguments, and varargs
|
||||||
// (not recommended to change this)
|
// (not recommended to change this / it should be less than 200)
|
||||||
#define PK_MAX_CO_VARNAMES 32
|
#define PK_MAX_CO_VARNAMES 32
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
|
@ -60,7 +60,7 @@ struct CodeEmitContext{
|
|||||||
void exit_block();
|
void exit_block();
|
||||||
void emit_expr(); // clear the expression stack and generate bytecode
|
void emit_expr(); // clear the expression stack and generate bytecode
|
||||||
std::string _log_s_expr();
|
std::string _log_s_expr();
|
||||||
int emit(Opcode opcode, int arg, int line);
|
int emit(Opcode opcode, uint16_t arg, int line);
|
||||||
void patch_jump(int index);
|
void patch_jump(int index);
|
||||||
bool add_label(StrName name);
|
bool add_label(StrName name);
|
||||||
int add_varname(StrName name);
|
int add_varname(StrName name);
|
||||||
|
@ -88,7 +88,7 @@ __NEXT_STEP:;
|
|||||||
TARGET(LOAD_NONE) PUSH(None); DISPATCH();
|
TARGET(LOAD_NONE) PUSH(None); DISPATCH();
|
||||||
TARGET(LOAD_TRUE) PUSH(True); DISPATCH();
|
TARGET(LOAD_TRUE) PUSH(True); DISPATCH();
|
||||||
TARGET(LOAD_FALSE) PUSH(False); DISPATCH();
|
TARGET(LOAD_FALSE) PUSH(False); DISPATCH();
|
||||||
TARGET(LOAD_INTEGER) PUSH(VAR(byte.arg)); DISPATCH();
|
TARGET(LOAD_INTEGER) PUSH(VAR((int16_t)byte.arg)); DISPATCH();
|
||||||
TARGET(LOAD_ELLIPSIS) PUSH(Ellipsis); DISPATCH();
|
TARGET(LOAD_ELLIPSIS) PUSH(Ellipsis); DISPATCH();
|
||||||
TARGET(LOAD_FUNCTION) {
|
TARGET(LOAD_FUNCTION) {
|
||||||
FuncDecl_ decl = co->func_decls[byte.arg];
|
FuncDecl_ decl = co->func_decls[byte.arg];
|
||||||
@ -511,8 +511,8 @@ __NEXT_STEP:;
|
|||||||
DISPATCH();
|
DISPATCH();
|
||||||
TARGET(CALL)
|
TARGET(CALL)
|
||||||
_0 = vectorcall(
|
_0 = vectorcall(
|
||||||
byte.arg & 0xFFFF, // ARGC
|
byte.arg & 0xFF, // ARGC
|
||||||
(byte.arg>>16) & 0xFFFF, // KWARGC
|
(byte.arg>>8) & 0xFF, // KWARGC
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
if(_0 == PY_OP_CALL) DISPATCH_OP_CALL();
|
if(_0 == PY_OP_CALL) DISPATCH_OP_CALL();
|
||||||
@ -600,7 +600,8 @@ __NEXT_STEP:;
|
|||||||
if(_0 != StopIteration){
|
if(_0 != StopIteration){
|
||||||
PUSH(_0);
|
PUSH(_0);
|
||||||
}else{
|
}else{
|
||||||
frame->jump_abs_break(co_blocks[byte.block].end);
|
// TODO: optimize this
|
||||||
|
frame->jump_abs_break(co->_get_block_codei(frame->_ip).end);
|
||||||
}
|
}
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
|
25
src/expr.cpp
25
src/expr.cpp
@ -50,10 +50,9 @@ namespace pkpy{
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
int CodeEmitContext::emit(Opcode opcode, int arg, int line) {
|
int CodeEmitContext::emit(Opcode opcode, uint16_t arg, int line) {
|
||||||
co->codes.push_back(
|
co->codes.push_back(Bytecode{(uint8_t)opcode, arg});
|
||||||
Bytecode{(uint8_t)opcode, (uint16_t)curr_block_i, arg}
|
co->iblocks.push_back(curr_block_i);
|
||||||
);
|
|
||||||
co->lines.push_back(line);
|
co->lines.push_back(line);
|
||||||
int i = co->codes.size() - 1;
|
int i = co->codes.size() - 1;
|
||||||
if(line==BC_KEEPLINE){
|
if(line==BC_KEEPLINE){
|
||||||
@ -75,6 +74,7 @@ namespace pkpy{
|
|||||||
}
|
}
|
||||||
|
|
||||||
int CodeEmitContext::add_varname(StrName name){
|
int CodeEmitContext::add_varname(StrName name){
|
||||||
|
// PK_MAX_CO_VARNAMES will be checked when pop_context(), not here
|
||||||
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);
|
||||||
@ -143,8 +143,7 @@ namespace pkpy{
|
|||||||
|
|
||||||
bool NameExpr::emit_store(CodeEmitContext* ctx) {
|
bool NameExpr::emit_store(CodeEmitContext* ctx) {
|
||||||
if(ctx->is_compiling_class){
|
if(ctx->is_compiling_class){
|
||||||
int index = name.index;
|
ctx->emit(OP_STORE_CLASS_ATTR, name.index, line);
|
||||||
ctx->emit(OP_STORE_CLASS_ATTR, index, line);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
ctx->emit_store_name(scope, name, line);
|
ctx->emit_store_name(scope, name, line);
|
||||||
@ -214,7 +213,7 @@ namespace pkpy{
|
|||||||
if(std::holds_alternative<i64>(value)){
|
if(std::holds_alternative<i64>(value)){
|
||||||
i64 _val = std::get<i64>(value);
|
i64 _val = std::get<i64>(value);
|
||||||
if(_val >= INT16_MIN && _val <= INT16_MAX){
|
if(_val >= INT16_MIN && _val <= INT16_MAX){
|
||||||
ctx->emit(OP_LOAD_INTEGER, (int)_val, line);
|
ctx->emit(OP_LOAD_INTEGER, (uint16_t)_val, line);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
obj = VAR(_val);
|
obj = VAR(_val);
|
||||||
@ -237,7 +236,7 @@ namespace pkpy{
|
|||||||
if(std::holds_alternative<i64>(lit->value)){
|
if(std::holds_alternative<i64>(lit->value)){
|
||||||
i64 _val = -std::get<i64>(lit->value);
|
i64 _val = -std::get<i64>(lit->value);
|
||||||
if(_val >= INT16_MIN && _val <= INT16_MAX){
|
if(_val >= INT16_MIN && _val <= INT16_MAX){
|
||||||
ctx->emit(OP_LOAD_INTEGER, (int)_val, line);
|
ctx->emit(OP_LOAD_INTEGER, (uint16_t)_val, line);
|
||||||
}else{
|
}else{
|
||||||
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
|
ctx->emit(OP_LOAD_CONST, ctx->add_const(VAR(_val)), line);
|
||||||
}
|
}
|
||||||
@ -484,7 +483,7 @@ namespace pkpy{
|
|||||||
|
|
||||||
if(vargs || vkwargs){
|
if(vargs || vkwargs){
|
||||||
for(auto& item: args) item->emit(ctx);
|
for(auto& item: args) item->emit(ctx);
|
||||||
ctx->emit(OP_BUILD_TUPLE_UNPACK, (int)args.size(), line);
|
ctx->emit(OP_BUILD_TUPLE_UNPACK, (uint16_t)args.size(), line);
|
||||||
|
|
||||||
if(!kwargs.empty()){
|
if(!kwargs.empty()){
|
||||||
for(auto& item: kwargs){
|
for(auto& item: kwargs){
|
||||||
@ -508,13 +507,13 @@ namespace pkpy{
|
|||||||
// vectorcall protocal
|
// vectorcall protocal
|
||||||
for(auto& item: args) item->emit(ctx);
|
for(auto& item: args) item->emit(ctx);
|
||||||
for(auto& item: kwargs){
|
for(auto& item: kwargs){
|
||||||
int index = StrName(item.first.sv()).index;
|
uint16_t index = StrName(item.first.sv()).index;
|
||||||
ctx->emit(OP_LOAD_INTEGER, index, line);
|
ctx->emit(OP_LOAD_INTEGER, index, line);
|
||||||
item.second->emit(ctx);
|
item.second->emit(ctx);
|
||||||
}
|
}
|
||||||
int KWARGC = (int)kwargs.size();
|
int KWARGC = kwargs.size();
|
||||||
int ARGC = (int)args.size();
|
int ARGC = args.size();
|
||||||
ctx->emit(OP_CALL, (KWARGC<<16)|ARGC, line);
|
ctx->emit(OP_CALL, (KWARGC<<8)|ARGC, line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ namespace pkpy{
|
|||||||
|
|
||||||
bool Frame::jump_to_exception_handler(){
|
bool Frame::jump_to_exception_handler(){
|
||||||
// try to find a parent try block
|
// try to find a parent try block
|
||||||
int block = co->codes[_ip].block;
|
int block = co->iblocks[_ip];
|
||||||
while(block >= 0){
|
while(block >= 0){
|
||||||
if(co->blocks[block].type == TRY_EXCEPT) break;
|
if(co->blocks[block].type == TRY_EXCEPT) break;
|
||||||
block = co->blocks[block].parent;
|
block = co->blocks[block].parent;
|
||||||
@ -47,8 +47,7 @@ namespace pkpy{
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Frame::jump_abs_break(int target){
|
void Frame::jump_abs_break(int target){
|
||||||
const Bytecode& prev = co->codes[_ip];
|
int i = co->iblocks[_ip];
|
||||||
int i = prev.block;
|
|
||||||
_next_ip = target;
|
_next_ip = target;
|
||||||
if(_next_ip >= co->codes.size()){
|
if(_next_ip >= co->codes.size()){
|
||||||
while(i>=0) i = _exit_block(i);
|
while(i>=0) i = _exit_block(i);
|
||||||
@ -58,9 +57,9 @@ namespace pkpy{
|
|||||||
// _ = 0
|
// _ = 0
|
||||||
// # if there is no op here, the block check will fail
|
// # if there is no op here, the block check will fail
|
||||||
// while i: --i
|
// while i: --i
|
||||||
const Bytecode& next = co->codes[target];
|
int next_block = co->iblocks[target];
|
||||||
while(i>=0 && i!=next.block) i = _exit_block(i);
|
while(i>=0 && i!=next_block) i = _exit_block(i);
|
||||||
if(i!=next.block) throw std::runtime_error("invalid jump");
|
if(i!=next_block) throw std::runtime_error("invalid jump");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +513,7 @@ PyObject* VM::new_module(Str name, Str package) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
|
static std::string _opcode_argstr(VM* vm, Bytecode byte, const CodeObject* co){
|
||||||
std::string argStr = byte.arg == -1 ? "" : std::to_string(byte.arg);
|
std::string argStr = byte.arg == BC_NOARG ? "" : std::to_string(byte.arg);
|
||||||
switch(byte.op){
|
switch(byte.op){
|
||||||
case OP_LOAD_CONST: case OP_FORMAT_STRING: case OP_IMPORT_PATH:
|
case OP_LOAD_CONST: case OP_FORMAT_STRING: case OP_IMPORT_PATH:
|
||||||
if(vm != nullptr){
|
if(vm != nullptr){
|
||||||
|
Loading…
x
Reference in New Issue
Block a user