optimize codes

This commit is contained in:
ValKmjolnir 2022-05-22 18:19:13 +08:00
parent 99dca532f6
commit ebfacd9197
7 changed files with 105 additions and 82 deletions

View File

@ -142,7 +142,7 @@ Use these commands to get version of interpreter:
/ \/ / _` / __|/ _` | |
/ /\ / (_| \__ \ (_| | |
\_\ \/ \__,_|___/\__,_|_|
nasal ver : 9.0
nasal ver : 10.0
c++ std : 201103
thanks to : https://github.com/andyross/nasal
code repo : https://github.com/ValKmjolnir/Nasal-Interpreter
@ -156,6 +156,9 @@ Use these commands to get help(see more debug commands in help):
> ./nasal -h | --help
```bash
,--#-,
<3 / \____\ <3
|_|__A_|
nasal <option>
option:
-h, --help | get help.
@ -633,7 +636,7 @@ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
if(hash.type!=vm_hash)
return builtin_err("keys","\"hash\" must be hash");
// push vector into local scope to avoid being sweeped
if(gc.top+1>=gc.stack+nasal_gc::stack_depth-1)
if(gc.top+1>=gc.canary)
return builtin_err("keys","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems;

View File

@ -13,6 +13,9 @@ const uint32_t VM_OPTIMIZE =0x100;
void help()
{
std::cout
<<" ,--#-,\n"
<<"<3 / \\____\\ <3\n"
<<" |_|__A_|\n"
#ifdef _WIN32
<<"use command <chcp 65001> if want to use unicode.\n"
#endif

View File

@ -45,6 +45,8 @@
#define PRTINT64 "%lld"
#endif
const uint32_t STACK_DEPTH=8192;
inline double hex_to_double(const char* str)
{
double ret=0;

View File

@ -306,7 +306,7 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc)
size_t source_len=source.length();
// push it to local scope to avoid being sweeped
if(gc.top+1>=gc.stack+nasal_gc::stack_depth-1)
if(gc.top+1>=gc.canary)
return builtin_err("split","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec);
@ -611,7 +611,7 @@ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc)
if(hash.type!=vm_hash)
return builtin_err("keys","\"hash\" must be hash");
// push vector into local scope to avoid being sweeped
if(gc.top+1>=gc.stack+nasal_gc::stack_depth-1)
if(gc.top+1>=gc.canary)
return builtin_err("keys","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems;
@ -1115,7 +1115,7 @@ nasal_ref builtin_chdir(nasal_ref* local,nasal_gc& gc)
nasal_ref builtin_environ(nasal_ref* local,nasal_gc& gc)
{
char** env=environ;
if(gc.top+1>=gc.stack+nasal_gc::stack_depth-1)
if(gc.top+1>=gc.canary)
return builtin_err("environ","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems;

View File

@ -430,7 +430,7 @@ void nasal_codegen::func_gen(const nasal_ast& ast)
block_gen(block);
in_iterloop.pop();
code[local_label].num=local.back().size();
if(local.back().size()>=nasal_gc::stack_depth)
if(local.back().size()>=STACK_DEPTH)
die("too many local variants: "+std::to_string(local.back().size())+".",block.line());
local.pop_back();
@ -1232,7 +1232,7 @@ void nasal_codegen::compile(const nasal_parse& parse,const nasal_import& import)
gen(op_intg,global.size(),0);
block_gen(parse.ast()); // generate main block
gen(op_exit,0,0);
if(global.size()>=nasal_gc::stack_depth)
if(global.size()>=STACK_DEPTH)
die("too many global variants: "+std::to_string(global.size())+".",0);
nerr.chkerr();
}

View File

@ -175,7 +175,7 @@ struct nasal_obj
enum obj_type
{
null,
file=1,
file,
dir,
dylib,
faddr
@ -209,8 +209,7 @@ struct nasal_co
running,
dead
};
static const uint32_t depth=1024;
nasal_ref stack[depth];
nasal_ref stack[STACK_DEPTH];
uint32_t pc;
nasal_ref* top;
@ -224,19 +223,19 @@ struct nasal_co
nasal_co():
pc(0),
top(stack),
canary(stack+depth-1),
canary(stack+STACK_DEPTH-1),
localr(nullptr),
memr(nullptr),
funcr({vm_nil,(double)0}),
upvalr({vm_nil,(double)0}),
status(nasal_co::suspended)
{
for(uint32_t i=0;i<depth;++i)
for(uint32_t i=0;i<STACK_DEPTH;++i)
stack[i]={vm_nil,(double)0};
}
void clear()
{
for(uint32_t i=0;i<depth;++i)
for(uint32_t i=0;i<STACK_DEPTH;++i)
stack[i]={vm_nil,(double)0};
pc=0;
localr=nullptr;
@ -451,10 +450,8 @@ const nasal_ref nil ={vm_nil,(double)0};
struct nasal_gc
{
static const uint32_t stack_depth=8192; // depth of value stack
struct
{
nasal_ref stack[stack_depth];
uint32_t pc;
nasal_ref* top;
nasal_ref* localr;
@ -462,16 +459,17 @@ struct nasal_gc
nasal_ref funcr;
nasal_ref upvalr;
nasal_ref* canary;
nasal_ref* stack;
} main_ctx;
/* runtime context */
uint32_t pc; // program counter
nasal_ref* top; // stack top
nasal_ref* localr; // local scope register
nasal_ref* memr; // used for mem_call
nasal_ref funcr; // function register
nasal_ref upvalr; // upvalue register
nasal_ref* canary; // avoid stackoverflow
uint32_t& pc; // program counter
nasal_ref*& localr; // local scope register
nasal_ref*& memr; // used for mem_call
nasal_ref& funcr; // function register
nasal_ref& upvalr; // upvalue register
nasal_ref*& canary; // avoid stackoverflow
nasal_ref*& top; // stack top
nasal_ref* stack; // stack pointer
nasal_co* coroutine; // running coroutine
@ -483,6 +481,23 @@ struct nasal_gc
/* values for analysis */
uint64_t size[vm_type_size];
uint64_t count[vm_type_size];
nasal_gc(
uint32_t& _pc,
nasal_ref*& _localr,
nasal_ref*& _memr,
nasal_ref& _funcr,
nasal_ref& _upvalr,
nasal_ref*& _canary,
nasal_ref*& _top,
nasal_ref* _stk):
pc(_pc),
localr(_localr),
memr(_memr),
funcr(_funcr),
upvalr(_upvalr),
canary(_canary),
top(_top),
stack(_stk){}
void mark();
void sweep();
void init(const std::vector<std::string>&);
@ -499,6 +514,7 @@ void nasal_gc::mark()
{
std::queue<nasal_ref> bfs;
// this make sure values on main stack can be scanned
if(!coroutine)
{
for(nasal_ref* i=stack;i<=top;++i)
@ -586,8 +602,6 @@ void nasal_gc::init(const std::vector<std::string>& s)
memory.push_back(tmp);
free_list[i].push(tmp);
}
stack=main_ctx.stack;
top=main_ctx.stack;
coroutine=nullptr;
// init constant strings
strs.resize(s.size());
@ -679,6 +693,7 @@ void nasal_gc::ctxchg(nasal_co& context)
main_ctx.funcr=funcr;
main_ctx.upvalr=upvalr;
main_ctx.canary=canary;
main_ctx.stack=stack;
pc=context.pc;
top=context.top;
@ -694,24 +709,23 @@ void nasal_gc::ctxchg(nasal_co& context)
}
void nasal_gc::ctxreserve()
{
if(coroutine->status!=nasal_co::dead)
coroutine->status=nasal_co::suspended;
// pc=0 means this coroutine is finished, so we use entry to reset it
coroutine->pc=pc==0?coroutine->funcr.func().entry:pc;
coroutine->top=top;
// pc=0 means this coroutine is finished
coroutine->status=pc?nasal_co::suspended:nasal_co::dead;
coroutine->pc=pc;
coroutine->localr=localr;
coroutine->memr=memr;
coroutine->funcr=funcr;
coroutine->upvalr=upvalr;
coroutine->canary=canary;
coroutine->top=top;
pc=main_ctx.pc;
top=main_ctx.top;
localr=main_ctx.localr;
memr=main_ctx.memr;
funcr=main_ctx.funcr;
upvalr=main_ctx.upvalr;
canary=main_ctx.canary;
top=main_ctx.top;
stack=main_ctx.stack;
coroutine=nullptr;
}

View File

@ -5,20 +5,24 @@ class nasal_vm
{
protected:
/* values of nasal_vm */
uint32_t& pc; // program counter
nasal_ref stack[STACK_DEPTH];
uint32_t pc; // program counter
nasal_ref* global; // global scope register
nasal_ref*& localr; // local scope register
nasal_ref*& memr; // used for mem_call
nasal_ref& funcr; // function register
nasal_ref& upvalr; // upvalue register
nasal_ref*& canary; // avoid stackoverflow
nasal_ref*& top; // stack top
nasal_ref* localr; // local scope register
nasal_ref* memr; // used for mem_call
nasal_ref funcr; // function register
nasal_ref upvalr; // upvalue register
nasal_ref* canary; // avoid stackoverflow
nasal_ref* top; // stack top
/* constant */
const double* num_table;// const numbers, ref from nasal_codegen
const std::string* str_table;// const symbols, ref from nasal_codegen
std::vector<uint32_t> imm; // immediate number
/* garbage collector */
nasal_gc gc;
/* values used for debug */
size_t files_size;
const std::string* files; // ref from nasal_import
@ -121,14 +125,8 @@ protected:
void opr_ret();
public:
nasal_vm():
pc(gc.pc),
global(gc.main_ctx.stack),
localr(gc.localr),
memr(gc.memr),
funcr(gc.funcr),
upvalr(gc.upvalr),
canary(gc.canary),
top(gc.top){}
global(stack),
gc(pc,localr,memr,funcr,upvalr,canary,top,stack){}
void run(
const nasal_codegen&,
const nasal_import&,
@ -148,13 +146,16 @@ void nasal_vm::init(
bytecode=code.data();
files=filenames.data();
files_size=filenames.size();
/* set canary and program counter */
canary=gc.stack+nasal_gc::stack_depth-1; // gc.stack[nasal_gc::stack_depth-1]
pc=0;
global=stack;
localr=nullptr;
memr=nullptr;
funcr=nil;
upvalr=nil;
canary=stack+STACK_DEPTH-1; // stack[STACK_DEPTH-1]
top=stack;
}
void nasal_vm::valinfo(nasal_ref& val)
{
@ -239,7 +240,7 @@ void nasal_vm::traceback()
{
uint32_t global_size=bytecode[0].num; // bytecode[0] is op_intg
nasal_ref* t=top;
nasal_ref* bottom=gc.stack+global_size;
nasal_ref* bottom=stack+global_size;
std::stack<uint32_t> ret;
for(nasal_ref* i=bottom;i<=t;++i)
if(i->type==vm_ret)
@ -266,7 +267,7 @@ void nasal_vm::traceback()
void nasal_vm::stackinfo(const uint32_t limit=10)
{
/* bytecode[0] is op_intg, the .num is the global size */
uint32_t gsize=gc.stack==gc.main_ctx.stack?bytecode[0].num:0;
uint32_t gsize=gc.stack==stack?bytecode[0].num:0;
nasal_ref* t=top;
nasal_ref* bottom=gc.stack+gsize;
printf("vm stack(0x" PRTHEX64 "<sp+%u>, limit %u, total ",(uint64_t)bottom,gsize,limit);
@ -285,7 +286,7 @@ void nasal_vm::stackinfo(const uint32_t limit=10)
void nasal_vm::register_info()
{
printf("registers(%s):\n",gc.coroutine?"coroutine":"main");
printf(" [ pc ] | pc | 0x%.x\n",pc);
printf(" [ pc ] | pc | 0x%x\n",pc);
printf(" [ global ] | addr | 0x" PRTHEX64 "\n",(uint64_t)global);
printf(" [ localr ] | addr | 0x" PRTHEX64 "\n",(uint64_t)localr);
printf(" [ memr ] | addr | 0x" PRTHEX64 "\n",(uint64_t)memr);
@ -306,7 +307,7 @@ void nasal_vm::register_info()
}
void nasal_vm::global_state()
{
if(!bytecode[0].num || gc.stack[0].type==vm_none) // bytecode[0].op is op_intg
if(!bytecode[0].num || stack[0].type==vm_none) // bytecode[0].op is op_intg
return;
printf("global(0x" PRTHEX64 "<sp+0>):\n",(uint64_t)global);
for(uint32_t i=0;i<bytecode[0].num;++i)
@ -955,20 +956,21 @@ inline void nasal_vm::opr_mcallh()
}
inline void nasal_vm::opr_ret()
{
// +-----------------+
// | return value | <- top[0]
// +-----------------+
// | old pc | <- top[-1]
// +-----------------+
// | old localr | <- top[-2]
// +-----------------+
// | old upvalr | <- top[-3]
// +-----------------+
// | local scope |
// | ... |
// +-----------------+ <- local pointer stored in localr
// | old funcr | <- old function stored in funcr
// +-----------------+
/* +-----------------+
* | return value | <- top[0]
* +-----------------+
* | old pc | <- top[-1]
* +-----------------+
* | old localr | <- top[-2]
* +-----------------+
* | old upvalr | <- top[-3]
* +-----------------+
* | local scope |
* | ... |
* +-----------------+ <- local pointer stored in localr
* | old funcr | <- old function stored in funcr
* +-----------------+
*/
nasal_ref ret =top[0];
nasal_ref* local=localr;
nasal_ref func =funcr;
@ -992,12 +994,11 @@ inline void nasal_vm::opr_ret()
for(uint32_t i=0;i<size;++i)
upval.elems.push_back(local[i]);
}
if(!pc) // cannot use gc.coroutine to judge, because there maybe another function call inside
{
gc.coroutine->status=nasal_co::dead;
// cannot use gc.coroutine to judge,
// because there maybe another function call inside
if(!pc)
gc.ctxreserve();
}
}
void nasal_vm::run(
const nasal_codegen& gen,
const nasal_import& linker,