⚡ optimize codes: store upvalue on stack & debugger now can output information of registers
This commit is contained in:
parent
120ceb429a
commit
07eeaadf96
|
@ -1386,6 +1386,8 @@ When `op_callb` is called, the stack frame is like this:
|
||||||
+----------------------------+
|
+----------------------------+
|
||||||
| old localr(vm_addr) | <- top[-1]
|
| old localr(vm_addr) | <- top[-1]
|
||||||
+----------------------------+
|
+----------------------------+
|
||||||
|
| old upvalr(vm_upval) | <- top[-2]
|
||||||
|
+----------------------------+
|
||||||
| local scope(nasal_ref) |
|
| local scope(nasal_ref) |
|
||||||
| ... |
|
| ... |
|
||||||
+----------------------------+ <- local pointer stored in localr
|
+----------------------------+ <- local pointer stored in localr
|
||||||
|
@ -1403,6 +1405,8 @@ In `op_callb`'s progress, next step the stack frame is:
|
||||||
+----------------------------+
|
+----------------------------+
|
||||||
| old localr(vm_addr) |
|
| old localr(vm_addr) |
|
||||||
+----------------------------+
|
+----------------------------+
|
||||||
|
| old upvalr(vm_upval) |
|
||||||
|
+----------------------------+
|
||||||
| local scope(nasal_ref) |
|
| local scope(nasal_ref) |
|
||||||
| ... |
|
| ... |
|
||||||
+----------------------------+ <- local pointer stored in localr
|
+----------------------------+ <- local pointer stored in localr
|
||||||
|
@ -1435,6 +1439,8 @@ but where is the returned `local[1]` sent?
|
||||||
+----------------------------+
|
+----------------------------+
|
||||||
| old localr(vm_addr) |
|
| old localr(vm_addr) |
|
||||||
+----------------------------+
|
+----------------------------+
|
||||||
|
| old upvalr(vm_upval) |
|
||||||
|
+----------------------------+
|
||||||
| local scope(nasal_ref) |
|
| local scope(nasal_ref) |
|
||||||
| ... |
|
| ... |
|
||||||
+----------------------------+ <- local pointer stored in localr
|
+----------------------------+ <- local pointer stored in localr
|
||||||
|
@ -1453,6 +1459,8 @@ and the returned `local[1]` in fact is set to the top of the main stack by `op_c
|
||||||
+----------------------------+
|
+----------------------------+
|
||||||
| old localr(vm_addr) |
|
| old localr(vm_addr) |
|
||||||
+----------------------------+
|
+----------------------------+
|
||||||
|
| old upvalr(vm_upval) |
|
||||||
|
+----------------------------+
|
||||||
| local scope(nasal_ref) |
|
| local scope(nasal_ref) |
|
||||||
| ... |
|
| ... |
|
||||||
+----------------------------+ <- local pointer stored in localr
|
+----------------------------+ <- local pointer stored in localr
|
||||||
|
|
1
makefile
1
makefile
|
@ -16,6 +16,7 @@ test:nasal
|
||||||
@ ./nasal -op -e -d test/calc.nas
|
@ ./nasal -op -e -d test/calc.nas
|
||||||
@ ./nasal -op -e test/choice.nas
|
@ ./nasal -op -e test/choice.nas
|
||||||
@ ./nasal -op -e test/class.nas
|
@ ./nasal -op -e test/class.nas
|
||||||
|
@ ./nasal -op -d -o test/coroutine.nas
|
||||||
@ ./nasal -op -e test/diff.nas
|
@ ./nasal -op -e test/diff.nas
|
||||||
-@ ./nasal -op -d test/exception.nas
|
-@ ./nasal -op -d test/exception.nas
|
||||||
@ ./nasal -op -t -d test/fib.nas
|
@ ./nasal -op -t -d test/fib.nas
|
||||||
|
|
|
@ -1343,6 +1343,8 @@ nasal_ref builtin_cocreate(nasal_ref* local,nasal_gc& gc)
|
||||||
// +-----------------+
|
// +-----------------+
|
||||||
// | old localr | <- top[-1]
|
// | old localr | <- top[-1]
|
||||||
// +-----------------+
|
// +-----------------+
|
||||||
|
// | old upvalr | <- top[-2]
|
||||||
|
// +-----------------+
|
||||||
// | local scope |
|
// | local scope |
|
||||||
// | ... |
|
// | ... |
|
||||||
// +-----------------+ <- local pointer stored in localr
|
// +-----------------+ <- local pointer stored in localr
|
||||||
|
@ -1361,11 +1363,13 @@ nasal_ref builtin_cocreate(nasal_ref* local,nasal_gc& gc)
|
||||||
coroutine.localr=coroutine.top+1;
|
coroutine.localr=coroutine.top+1;
|
||||||
coroutine.top=coroutine.localr+func.func().lsize;
|
coroutine.top=coroutine.localr+func.func().lsize;
|
||||||
coroutine.localr[0]=func.func().local[0];
|
coroutine.localr[0]=func.func().local[0];
|
||||||
coroutine.top[0]={vm_addr,(nasal_ref*)nullptr};
|
coroutine.top[0]=nil; // old upvalr
|
||||||
coroutine.top++;
|
coroutine.top++;
|
||||||
coroutine.top[0]={vm_ret,(uint32_t)0};
|
coroutine.top[0]={vm_addr,(nasal_ref*)nullptr}; // old localr
|
||||||
|
coroutine.top++;
|
||||||
|
coroutine.top[0]={vm_ret,(uint32_t)0}; // old pc, set to zero to make op_ret recognizing this as coroutine function
|
||||||
|
|
||||||
coroutine.funcr=func;
|
coroutine.funcr=func; // make sure the coroutine function can use correct upvalues
|
||||||
coroutine.status=nasal_co::suspended;
|
coroutine.status=nasal_co::suspended;
|
||||||
|
|
||||||
return co;
|
return co;
|
||||||
|
|
31
nasal_gc.h
31
nasal_gc.h
|
@ -218,6 +218,7 @@ struct nasal_co
|
||||||
nasal_ref* localr;
|
nasal_ref* localr;
|
||||||
nasal_ref* memr;
|
nasal_ref* memr;
|
||||||
nasal_ref funcr;
|
nasal_ref funcr;
|
||||||
|
nasal_ref upvalr;
|
||||||
|
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
nasal_co():
|
nasal_co():
|
||||||
|
@ -227,6 +228,7 @@ struct nasal_co
|
||||||
localr(nullptr),
|
localr(nullptr),
|
||||||
memr(nullptr),
|
memr(nullptr),
|
||||||
funcr({vm_nil,(double)0}),
|
funcr({vm_nil,(double)0}),
|
||||||
|
upvalr({vm_nil,(double)0}),
|
||||||
status(nasal_co::suspended)
|
status(nasal_co::suspended)
|
||||||
{
|
{
|
||||||
for(uint32_t i=0;i<depth;++i)
|
for(uint32_t i=0;i<depth;++i)
|
||||||
|
@ -454,13 +456,13 @@ struct nasal_gc
|
||||||
{
|
{
|
||||||
nasal_ref stack[stack_depth];
|
nasal_ref stack[stack_depth];
|
||||||
uint32_t pc;
|
uint32_t pc;
|
||||||
|
nasal_ref* top;
|
||||||
nasal_ref* localr;
|
nasal_ref* localr;
|
||||||
nasal_ref* memr;
|
nasal_ref* memr;
|
||||||
nasal_ref* canary;
|
|
||||||
nasal_ref funcr;
|
nasal_ref funcr;
|
||||||
nasal_ref* top;
|
nasal_ref upvalr;
|
||||||
|
nasal_ref* canary;
|
||||||
} main_ctx;
|
} main_ctx;
|
||||||
nasal_ref* global; // global values pointer(this should not be changed)
|
|
||||||
|
|
||||||
/* runtime context */
|
/* runtime context */
|
||||||
uint32_t pc; // program counter
|
uint32_t pc; // program counter
|
||||||
|
@ -468,20 +470,15 @@ struct nasal_gc
|
||||||
nasal_ref* localr; // local scope register
|
nasal_ref* localr; // local scope register
|
||||||
nasal_ref* memr; // used for mem_call
|
nasal_ref* memr; // used for mem_call
|
||||||
nasal_ref funcr; // function register
|
nasal_ref funcr; // function register
|
||||||
|
nasal_ref upvalr; // upvalue register
|
||||||
nasal_ref* canary; // avoid stackoverflow
|
nasal_ref* canary; // avoid stackoverflow
|
||||||
nasal_ref* stack; // stack pointer
|
nasal_ref* stack; // stack pointer
|
||||||
nasal_co* coroutine; // running coroutin
|
nasal_co* coroutine; // running coroutine
|
||||||
|
|
||||||
/* constants and memory pool */
|
/* constants and memory pool */
|
||||||
std::vector<nasal_ref> strs; // reserved address for const vm_str
|
std::vector<nasal_ref> strs; // reserved address for const vm_str
|
||||||
std::vector<nasal_val*> memory; // gc memory
|
std::vector<nasal_val*> memory; // gc memory
|
||||||
std::queue<nasal_val*> free_list[vm_type_size]; // gc free list
|
std::queue<nasal_val*> free_list[vm_type_size]; // gc free list
|
||||||
/* upvalue is a temporary space to store upvalues */
|
|
||||||
/* if no new functions generated in local scope */
|
|
||||||
/* upvalue will pushback(nil) */
|
|
||||||
/* if new functions generated in local scope */
|
|
||||||
/* they will share the same upvalue stored here */
|
|
||||||
std::vector<nasal_ref> upvalue;
|
|
||||||
|
|
||||||
/* values for analysis */
|
/* values for analysis */
|
||||||
uint64_t size[vm_type_size];
|
uint64_t size[vm_type_size];
|
||||||
|
@ -502,19 +499,19 @@ void nasal_gc::mark()
|
||||||
{
|
{
|
||||||
std::queue<nasal_ref> bfs;
|
std::queue<nasal_ref> bfs;
|
||||||
|
|
||||||
for(auto& i:upvalue)
|
|
||||||
bfs.push(i);
|
|
||||||
if(!coroutine)
|
if(!coroutine)
|
||||||
{
|
{
|
||||||
for(nasal_ref* i=stack;i<=top;++i)
|
for(nasal_ref* i=stack;i<=top;++i)
|
||||||
bfs.push(*i);
|
bfs.push(*i);
|
||||||
bfs.push(funcr);
|
bfs.push(funcr);
|
||||||
|
bfs.push(upvalr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for(nasal_ref* i=main_ctx.stack;i<=main_ctx.top;++i)
|
for(nasal_ref* i=main_ctx.stack;i<=main_ctx.top;++i)
|
||||||
bfs.push(*i);
|
bfs.push(*i);
|
||||||
bfs.push(main_ctx.funcr);
|
bfs.push(main_ctx.funcr);
|
||||||
|
bfs.push(main_ctx.upvalr);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!bfs.empty())
|
while(!bfs.empty())
|
||||||
|
@ -545,6 +542,7 @@ void nasal_gc::mark()
|
||||||
break;
|
break;
|
||||||
case vm_co:
|
case vm_co:
|
||||||
bfs.push(tmp.co().funcr);
|
bfs.push(tmp.co().funcr);
|
||||||
|
bfs.push(tmp.co().upvalr);
|
||||||
for(nasal_ref* i=tmp.co().stack;i<=tmp.co().top;++i)
|
for(nasal_ref* i=tmp.co().stack;i<=tmp.co().top;++i)
|
||||||
bfs.push(*i);
|
bfs.push(*i);
|
||||||
break;
|
break;
|
||||||
|
@ -588,7 +586,6 @@ void nasal_gc::init(const std::vector<std::string>& s)
|
||||||
memory.push_back(tmp);
|
memory.push_back(tmp);
|
||||||
free_list[i].push(tmp);
|
free_list[i].push(tmp);
|
||||||
}
|
}
|
||||||
global=main_ctx.stack;
|
|
||||||
stack=main_ctx.stack;
|
stack=main_ctx.stack;
|
||||||
top=main_ctx.stack;
|
top=main_ctx.stack;
|
||||||
coroutine=nullptr;
|
coroutine=nullptr;
|
||||||
|
@ -606,7 +603,6 @@ void nasal_gc::clear()
|
||||||
for(auto i:memory)
|
for(auto i:memory)
|
||||||
delete i;
|
delete i;
|
||||||
memory.clear();
|
memory.clear();
|
||||||
upvalue.clear();
|
|
||||||
for(uint8_t i=0;i<vm_type_size;++i)
|
for(uint8_t i=0;i<vm_type_size;++i)
|
||||||
while(!free_list[i].empty())
|
while(!free_list[i].empty())
|
||||||
free_list[i].pop();
|
free_list[i].pop();
|
||||||
|
@ -681,6 +677,7 @@ void nasal_gc::ctxchg(nasal_co& context)
|
||||||
main_ctx.localr=localr;
|
main_ctx.localr=localr;
|
||||||
main_ctx.memr=memr;
|
main_ctx.memr=memr;
|
||||||
main_ctx.funcr=funcr;
|
main_ctx.funcr=funcr;
|
||||||
|
main_ctx.upvalr=upvalr;
|
||||||
main_ctx.canary=canary;
|
main_ctx.canary=canary;
|
||||||
|
|
||||||
pc=context.pc;
|
pc=context.pc;
|
||||||
|
@ -688,11 +685,11 @@ void nasal_gc::ctxchg(nasal_co& context)
|
||||||
localr=context.localr;
|
localr=context.localr;
|
||||||
memr=context.memr;
|
memr=context.memr;
|
||||||
funcr=context.funcr;
|
funcr=context.funcr;
|
||||||
|
upvalr=context.upvalr;
|
||||||
canary=context.canary;
|
canary=context.canary;
|
||||||
stack=context.stack;
|
stack=context.stack;
|
||||||
coroutine=&context;
|
coroutine=&context;
|
||||||
|
|
||||||
upvalue.push_back(nil);
|
|
||||||
coroutine->status=nasal_co::running;
|
coroutine->status=nasal_co::running;
|
||||||
}
|
}
|
||||||
void nasal_gc::ctxreserve()
|
void nasal_gc::ctxreserve()
|
||||||
|
@ -705,6 +702,7 @@ void nasal_gc::ctxreserve()
|
||||||
coroutine->localr=localr;
|
coroutine->localr=localr;
|
||||||
coroutine->memr=memr;
|
coroutine->memr=memr;
|
||||||
coroutine->funcr=funcr;
|
coroutine->funcr=funcr;
|
||||||
|
coroutine->upvalr=upvalr;
|
||||||
coroutine->canary=canary;
|
coroutine->canary=canary;
|
||||||
|
|
||||||
pc=main_ctx.pc;
|
pc=main_ctx.pc;
|
||||||
|
@ -712,10 +710,9 @@ void nasal_gc::ctxreserve()
|
||||||
localr=main_ctx.localr;
|
localr=main_ctx.localr;
|
||||||
memr=main_ctx.memr;
|
memr=main_ctx.memr;
|
||||||
funcr=main_ctx.funcr;
|
funcr=main_ctx.funcr;
|
||||||
|
upvalr=main_ctx.upvalr;
|
||||||
canary=main_ctx.canary;
|
canary=main_ctx.canary;
|
||||||
stack=main_ctx.stack;
|
stack=main_ctx.stack;
|
||||||
coroutine=nullptr;
|
coroutine=nullptr;
|
||||||
|
|
||||||
upvalue.pop_back();
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
66
nasal_vm.h
66
nasal_vm.h
|
@ -6,10 +6,11 @@ class nasal_vm
|
||||||
protected:
|
protected:
|
||||||
/* values of nasal_vm */
|
/* values of nasal_vm */
|
||||||
uint32_t& pc; // program counter
|
uint32_t& pc; // program counter
|
||||||
nasal_ref*& global; // global scope register
|
nasal_ref* global; // global scope register
|
||||||
nasal_ref*& localr; // local scope register
|
nasal_ref*& localr; // local scope register
|
||||||
nasal_ref*& memr; // used for mem_call
|
nasal_ref*& memr; // used for mem_call
|
||||||
nasal_ref& funcr; // function register
|
nasal_ref& funcr; // function register
|
||||||
|
nasal_ref& upvalr; // upvalue register
|
||||||
nasal_ref*& canary; // avoid stackoverflow
|
nasal_ref*& canary; // avoid stackoverflow
|
||||||
nasal_ref*& top; // stack top
|
nasal_ref*& top; // stack top
|
||||||
/* constant */
|
/* constant */
|
||||||
|
@ -120,10 +121,11 @@ protected:
|
||||||
public:
|
public:
|
||||||
nasal_vm():
|
nasal_vm():
|
||||||
pc(gc.pc),
|
pc(gc.pc),
|
||||||
global(gc.global),
|
global(gc.main_ctx.stack),
|
||||||
localr(gc.localr),
|
localr(gc.localr),
|
||||||
memr(gc.memr),
|
memr(gc.memr),
|
||||||
funcr(gc.funcr),
|
funcr(gc.funcr),
|
||||||
|
upvalr(gc.upvalr),
|
||||||
canary(gc.canary),
|
canary(gc.canary),
|
||||||
top(gc.top){}
|
top(gc.top){}
|
||||||
void run(
|
void run(
|
||||||
|
@ -147,9 +149,11 @@ void nasal_vm::init(
|
||||||
files_size=filenames.size();
|
files_size=filenames.size();
|
||||||
/* set canary and program counter */
|
/* set canary and program counter */
|
||||||
canary=gc.stack+nasal_gc::stack_depth-1; // gc.stack[nasal_gc::stack_depth-1]
|
canary=gc.stack+nasal_gc::stack_depth-1; // gc.stack[nasal_gc::stack_depth-1]
|
||||||
memr=nullptr;
|
|
||||||
localr=nullptr;
|
|
||||||
pc=0;
|
pc=0;
|
||||||
|
localr=nullptr;
|
||||||
|
memr=nullptr;
|
||||||
|
funcr=nil;
|
||||||
|
upvalr=nil;
|
||||||
}
|
}
|
||||||
void nasal_vm::valinfo(nasal_ref& val)
|
void nasal_vm::valinfo(nasal_ref& val)
|
||||||
{
|
{
|
||||||
|
@ -169,6 +173,7 @@ void nasal_vm::valinfo(nasal_ref& val)
|
||||||
printf("| str | <0x" PRTHEX64 "> %.16s%s\n",(uint64_t)p,tmp.c_str(),tmp.length()>16?"...":"");
|
printf("| str | <0x" PRTHEX64 "> %.16s%s\n",(uint64_t)p,tmp.c_str(),tmp.length()>16?"...":"");
|
||||||
}break;
|
}break;
|
||||||
case vm_func: printf("| func | <0x" PRTHEX64 "> entry:0x%x\n",(uint64_t)p,val.func().entry);break;
|
case vm_func: printf("| func | <0x" PRTHEX64 "> entry:0x%x\n",(uint64_t)p,val.func().entry);break;
|
||||||
|
case vm_upval:printf("| upval| <0x" PRTHEX64 "> [%u val]\n",(uint64_t)p,val.upval().size);break;
|
||||||
case vm_vec: printf("| vec | <0x" PRTHEX64 "> [%zu val]\n",(uint64_t)p,val.vec().size());break;
|
case vm_vec: printf("| vec | <0x" PRTHEX64 "> [%zu val]\n",(uint64_t)p,val.vec().size());break;
|
||||||
case vm_hash: printf("| hash | <0x" PRTHEX64 "> {%zu val}\n",(uint64_t)p,val.hash().size());break;
|
case vm_hash: printf("| hash | <0x" PRTHEX64 "> {%zu val}\n",(uint64_t)p,val.hash().size());break;
|
||||||
case vm_obj: printf("| obj | <0x" PRTHEX64 "> obj:0x" PRTHEX64 "\n",(uint64_t)p,(uint64_t)val.obj().ptr);break;
|
case vm_obj: printf("| obj | <0x" PRTHEX64 "> obj:0x" PRTHEX64 "\n",(uint64_t)p,(uint64_t)val.obj().ptr);break;
|
||||||
|
@ -216,7 +221,7 @@ void nasal_vm::bytecodeinfo(const char* header,const uint32_t p)
|
||||||
case op_callb:
|
case op_callb:
|
||||||
printf("0x%x <%s@0x" PRTHEX64 ">",c.num,builtin[c.num].name,(uint64_t)builtin[c.num].func);break;
|
printf("0x%x <%s@0x" PRTHEX64 ">",c.num,builtin[c.num].name,(uint64_t)builtin[c.num].func);break;
|
||||||
case op_upval: case op_mupval: case op_loadu:
|
case op_upval: case op_mupval: case op_loadu:
|
||||||
printf(" (0x%x[0x%x])",(c.num>>16)&0xffff,c.num&0xffff);break;
|
printf("0x%x[0x%x]",(c.num>>16)&0xffff,c.num&0xffff);break;
|
||||||
case op_happ: case op_pstr:
|
case op_happ: case op_pstr:
|
||||||
case op_lnkc:
|
case op_lnkc:
|
||||||
case op_callh: case op_mcallh:
|
case op_callh: case op_mcallh:
|
||||||
|
@ -318,14 +323,25 @@ void nasal_vm::upval_state()
|
||||||
}
|
}
|
||||||
void nasal_vm::detail()
|
void nasal_vm::detail()
|
||||||
{
|
{
|
||||||
printf("maddr:\n (0x" PRTHEX64 ")\n",(uint64_t)memr);
|
printf("registers(%s):\n",gc.coroutine?"coroutine":"main");
|
||||||
printf("localr:\n (0x" PRTHEX64 ")\n",(uint64_t)localr);
|
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);
|
||||||
if(funcr.type==vm_nil)
|
if(funcr.type==vm_nil)
|
||||||
printf("funcr:\n (nil)\n");
|
printf(" [ funcr ] | nil |\n");
|
||||||
else
|
else
|
||||||
printf("funcr:\n (<0x" PRTHEX64 "> entry:0x%x)\n",
|
printf(" [ funcr ] | func | <0x" PRTHEX64 "> entry:0x%x\n",
|
||||||
(uint64_t)funcr.value.gcobj,
|
(uint64_t)funcr.value.gcobj,
|
||||||
funcr.func().entry);
|
funcr.func().entry);
|
||||||
|
if(upvalr.type==vm_nil)
|
||||||
|
printf(" [ upvalr ] | nil |\n");
|
||||||
|
else
|
||||||
|
printf(" [ upvalr ] | upval| <0x" PRTHEX64 "> [%u val]\n",
|
||||||
|
(uint64_t)upvalr.value.gcobj,
|
||||||
|
upvalr.upval().size);
|
||||||
|
printf(" [ canary ] | addr | 0x" PRTHEX64 "\n",(uint64_t)canary);
|
||||||
|
printf(" [ top ] | addr | 0x" PRTHEX64 "\n",(uint64_t)top);
|
||||||
global_state();
|
global_state();
|
||||||
local_state();
|
local_state();
|
||||||
upval_state();
|
upval_state();
|
||||||
|
@ -436,11 +452,11 @@ inline void nasal_vm::opr_newf()
|
||||||
if(localr)
|
if(localr)
|
||||||
{
|
{
|
||||||
func.upvalue=funcr.func().upvalue;
|
func.upvalue=funcr.func().upvalue;
|
||||||
nasal_ref upval=(gc.upvalue.back().type==vm_nil)?gc.alloc(vm_upval):gc.upvalue.back();
|
nasal_ref upval=(upvalr.type==vm_nil)?gc.alloc(vm_upval):upvalr;
|
||||||
upval.upval().size=funcr.func().lsize;
|
upval.upval().size=funcr.func().lsize;
|
||||||
upval.upval().stk=localr;
|
upval.upval().stk=localr;
|
||||||
func.upvalue.push_back(upval);
|
func.upvalue.push_back(upval);
|
||||||
gc.upvalue.back()=upval;
|
upvalr=upval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_happ()
|
inline void nasal_vm::opr_happ()
|
||||||
|
@ -739,7 +755,7 @@ inline void nasal_vm::opr_callfv()
|
||||||
nasal_ref tmp=local[-1];
|
nasal_ref tmp=local[-1];
|
||||||
local[-1]=funcr;
|
local[-1]=funcr;
|
||||||
funcr=tmp;
|
funcr=tmp;
|
||||||
if(top-argc+func.lsize+2>=canary) // top-argc+lsize(local) +1(old pc) +1(old localr)
|
if(top-argc+func.lsize+3>=canary) // top-argc+lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
||||||
die("stack overflow");
|
die("stack overflow");
|
||||||
|
|
||||||
uint32_t psize=func.psize-1; // parameter size is func->psize-1, 1 is reserved for "me"
|
uint32_t psize=func.psize-1; // parameter size is func->psize-1, 1 is reserved for "me"
|
||||||
|
@ -763,11 +779,12 @@ inline void nasal_vm::opr_callfv()
|
||||||
if(func.dynpara>=0)
|
if(func.dynpara>=0)
|
||||||
local[psize+1]=dynamic;
|
local[psize+1]=dynamic;
|
||||||
|
|
||||||
top[0]={vm_addr,localr};
|
top[0]=upvalr;
|
||||||
|
(++top)[0]={vm_addr,localr};
|
||||||
(++top)[0]={vm_ret,pc};
|
(++top)[0]={vm_ret,pc};
|
||||||
pc=func.entry-1;
|
pc=func.entry-1;
|
||||||
localr=local;
|
localr=local;
|
||||||
gc.upvalue.push_back(nil);
|
upvalr=nil;
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_callfh()
|
inline void nasal_vm::opr_callfh()
|
||||||
{
|
{
|
||||||
|
@ -779,7 +796,7 @@ inline void nasal_vm::opr_callfh()
|
||||||
nasal_ref tmp=top[-1];
|
nasal_ref tmp=top[-1];
|
||||||
top[-1]=funcr;
|
top[-1]=funcr;
|
||||||
funcr=tmp;
|
funcr=tmp;
|
||||||
if(top+func.lsize+1>=canary) // top -1(hash) +lsize(local) +1(old pc) +1(old localr)
|
if(top+func.lsize+2>=canary) // top -1(hash) +lsize(local) +1(old pc) +1(old localr) +1(old upvalr)
|
||||||
die("stack overflow");
|
die("stack overflow");
|
||||||
if(func.dynpara>=0)
|
if(func.dynpara>=0)
|
||||||
die("callfh: special call cannot use dynamic argument");
|
die("callfh: special call cannot use dynamic argument");
|
||||||
|
@ -797,11 +814,12 @@ inline void nasal_vm::opr_callfh()
|
||||||
die("callfh: lack argument(s): \""+i.first+"\"");
|
die("callfh: lack argument(s): \""+i.first+"\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
top[0]={vm_addr,localr};
|
top[0]=upvalr;
|
||||||
|
(++top)[0]={vm_addr,localr};
|
||||||
(++top)[0]={vm_ret,pc}; // rewrite top with vm_ret
|
(++top)[0]={vm_ret,pc}; // rewrite top with vm_ret
|
||||||
pc=func.entry-1;
|
pc=func.entry-1;
|
||||||
localr=local;
|
localr=local;
|
||||||
gc.upvalue.push_back(nil);
|
upvalr=nil;
|
||||||
}
|
}
|
||||||
inline void nasal_vm::opr_callb()
|
inline void nasal_vm::opr_callb()
|
||||||
{
|
{
|
||||||
|
@ -939,6 +957,8 @@ inline void nasal_vm::opr_ret()
|
||||||
// +-----------------+
|
// +-----------------+
|
||||||
// | old localr | <- top[-2]
|
// | old localr | <- top[-2]
|
||||||
// +-----------------+
|
// +-----------------+
|
||||||
|
// | old upvalr | <- top[-3]
|
||||||
|
// +-----------------+
|
||||||
// | local scope |
|
// | local scope |
|
||||||
// | ... |
|
// | ... |
|
||||||
// +-----------------+ <- local pointer stored in localr
|
// +-----------------+ <- local pointer stored in localr
|
||||||
|
@ -947,9 +967,11 @@ inline void nasal_vm::opr_ret()
|
||||||
nasal_ref ret=top[0];
|
nasal_ref ret=top[0];
|
||||||
nasal_ref* local=localr;
|
nasal_ref* local=localr;
|
||||||
nasal_ref func=funcr;
|
nasal_ref func=funcr;
|
||||||
|
nasal_ref up=upvalr;
|
||||||
|
|
||||||
pc=top[-1].ret();
|
pc=top[-1].ret();
|
||||||
localr=top[-2].addr();
|
localr=top[-2].addr();
|
||||||
|
upvalr=top[-3];
|
||||||
|
|
||||||
top=local-1;
|
top=local-1;
|
||||||
func.func().local[0]=nil;// get func and set 'me' to nil
|
func.func().local[0]=nil;// get func and set 'me' to nil
|
||||||
|
@ -957,21 +979,19 @@ inline void nasal_vm::opr_ret()
|
||||||
|
|
||||||
top[0]=ret; // rewrite func with returned value
|
top[0]=ret; // rewrite func with returned value
|
||||||
|
|
||||||
if(gc.upvalue.back().type==vm_upval) // synchronize upvalue
|
if(up.type==vm_upval) // synchronize upvalue
|
||||||
{
|
{
|
||||||
auto& upval=gc.upvalue.back().upval();
|
auto& upval=up.upval();
|
||||||
auto size=func.func().lsize;
|
auto size=func.func().lsize;
|
||||||
upval.onstk=false;
|
upval.onstk=false;
|
||||||
for(uint32_t i=0;i<size;++i)
|
for(uint32_t i=0;i<size;++i)
|
||||||
upval.elems.push_back(local[i]);
|
upval.elems.push_back(local[i]);
|
||||||
}
|
}
|
||||||
if(!pc)
|
if(!pc) // cannot use gc.coroutine to judge, because there maybe another function call inside
|
||||||
{
|
{
|
||||||
gc.coroutine->status=nasal_co::dead;
|
gc.coroutine->status=nasal_co::dead;
|
||||||
gc.ctxreserve();
|
gc.ctxreserve();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
gc.upvalue.pop_back();
|
|
||||||
}
|
}
|
||||||
void nasal_vm::run(
|
void nasal_vm::run(
|
||||||
const nasal_codegen& gen,
|
const nasal_codegen& gen,
|
||||||
|
@ -1101,6 +1121,6 @@ mcalll: exec_operand(opr_mcalll ,op_mcalll ); // +1
|
||||||
mupval: exec_operand(opr_mupval ,op_mupval ); // +1
|
mupval: exec_operand(opr_mupval ,op_mupval ); // +1
|
||||||
mcallv: exec_opnodie(opr_mcallv ,op_mcallv ); // -0
|
mcallv: exec_opnodie(opr_mcallv ,op_mcallv ); // -0
|
||||||
mcallh: exec_opnodie(opr_mcallh ,op_mcallh ); // -0
|
mcallh: exec_opnodie(opr_mcallh ,op_mcallh ); // -0
|
||||||
ret: exec_opnodie(opr_ret ,op_ret ); // -1
|
ret: exec_opnodie(opr_ret ,op_ret ); // -2
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
|
@ -2,16 +2,11 @@
|
||||||
# 2022/5/19
|
# 2022/5/19
|
||||||
var fib=func(){
|
var fib=func(){
|
||||||
var (a,b)=(1,1);
|
var (a,b)=(1,1);
|
||||||
if(coroutine.running()){
|
|
||||||
coroutine.yield(a);
|
coroutine.yield(a);
|
||||||
coroutine.yield(b);
|
coroutine.yield(b);
|
||||||
}
|
|
||||||
while(1){
|
while(1){
|
||||||
(a,b)=(b,a+b);
|
(a,b)=(b,a+b);
|
||||||
if(coroutine.running())
|
|
||||||
coroutine.yield(b);
|
coroutine.yield(b);
|
||||||
else
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -22,4 +17,34 @@ for(var i=0;i<45;i+=1){
|
||||||
println('coroutine[0]:',res[0]==nil?nil:res[0][0],'\ncoroutine[1]:',res[1]==nil?nil:res[1][0]);
|
println('coroutine[0]:',res[0]==nil?nil:res[0][0],'\ncoroutine[1]:',res[1]==nil?nil:res[1][0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fib();
|
var productor=func(){
|
||||||
|
for(var i=0;;i+=1)
|
||||||
|
coroutine.yield(i);
|
||||||
|
}
|
||||||
|
var counter=0;
|
||||||
|
var consumer=func(){
|
||||||
|
counter+=1;
|
||||||
|
print('[',counter,']: ');
|
||||||
|
for(var i=0;i<5;i+=1){
|
||||||
|
print('[',i,']',coroutine.resume(co)[0],' ');
|
||||||
|
}
|
||||||
|
print('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
var co=coroutine.create(productor);
|
||||||
|
var tm=maketimestamp();
|
||||||
|
tm.stamp();
|
||||||
|
while(tm.elapsedMSec()<1000)
|
||||||
|
consumer();
|
||||||
|
|
||||||
|
func(){
|
||||||
|
var x=1;
|
||||||
|
var co=coroutine.create(func(){
|
||||||
|
for(var j=0;j<1024;j+=1){
|
||||||
|
coroutine.yield(x,i,j);
|
||||||
|
x+=1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for(var i=0;i<256;i+=1)
|
||||||
|
println(coroutine.resume(co));
|
||||||
|
}();
|
Loading…
Reference in New Issue