diff --git a/README.md b/README.md index 81dae69..68394db 100644 --- a/README.md +++ b/README.md @@ -678,22 +678,18 @@ If you don't warp built-in function in a normal nasal function, this built-in function may cause a fault when searching arguments, which will cause __segmentation error__. -Use `import("filename.nas")` to get the nasal file including your built-in functions, -then you could use it. +Use `import("filename.nas")` to get the nasal file including your built-in functions, then you could use it. +Also there's another way of importing nasal files, the two way of importing have the same function: -version 6.5 update: +```javascript +import.dirname.dirname.filename; +import("./dirname/dirname/filename.nas"); +``` -Use `gc::builtin_alloc` in builtin function if this function uses alloc more than one time. +When running a builtin function, alloc will run more than one time, this may cause mark-sweep in `gc::alloc`. +The value got before will be collected, but stil in use in this builtin function, this will cause a fatal error. -When running a builtin function,alloc will run more than one time, -this may cause mark-sweep in `gc::alloc`. - -The value got before will be collected,but stil in use in this builtin function, -this is a fatal error. - -So use `gc::builtin_alloc` in builtin functions to allocate a new object. - -Or use `gc::alloc` like this to avoid sweeping objects incorrectly: +So use `gc::temp` in builtin functions to temprorarily store the gc-managed value that you want to return later. Like this: ```C++ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) @@ -701,19 +697,13 @@ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) nasal_ref hash=local[1]; 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.canary) - return builtin_err("keys","expand temporary space error:stackoverflow"); - (++gc.top)[0]=gc.alloc(vm_vec); - auto& vec=gc.top[0].vec().elems; + // avoid being sweeped + nasal_ref res=gc.temp=gc.alloc(vm_vec); + auto& vec=res.vec().elems; for(auto& iter:hash.hash().elems) - { - nasal_ref str=gc.alloc(vm_str); - str.str()=iter.first; - vec.push_back(str); - } - --gc.top; - return gc.top[1]; + vec.push_back(gc.newstr(iter.first)); + gc.temp=nil; + return res; } ``` diff --git a/doc/README_zh.md b/doc/README_zh.md index f79f746..befd863 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -642,18 +642,17 @@ var print=func(elems...){ 一定要注意,如果你不把内置函数包装到一个普通的nasal函数中,那么直接调用这个内置函数会在参数传入阶段出现严重的错误,这个错误会导致 __segmentation error__。也就是大家的老朋友段错误。 在nasal文件中使用`import("文件名.nas")`可以导入该文件中你包装的所有内置函数,接下来你就可以使用他们了。 +当然也有另外一种办法来导入这些nasal文件,下面两种导入方式的效果是一样的: -v6.5 更新: - -在内置函数中使用`gc::builtin_alloc`来避免在内置函数中多次申请需要内存管理的数据类型时可能出现的垃圾收集器的问题。 +```javascript +import.dirname.dirname.filename; +import("./dirname/dirname/filename.nas"); +``` 当运行内置函数的时候,内存分配器如果运行超过一次,那么会有更大可能性多次触发垃圾收集器的mark-sweep。这个操作会在`gc::alloc`中触发。 - 如果先前获取的数值没有被正确存到可以被垃圾收集器索引到的地方,那么它会被错误地回收,这会导致严重的错误。 -所以如果不放心,那就在内置函数中用`gc::builtin_alloc`来申请新的数据。 - -或者你也可以这样使用`gc::alloc`来规避错误的垃圾回收,目前我们大多使用这种方式,因为`gc::builtin_alloc`没那么靠谱: +所以请使用`gc::temp`来暂时存储一个会被返回的需要gc管理的变量,这样可以防止内部所有的申请错误触发垃圾回收。如下所示: ```C++ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) @@ -661,20 +660,13 @@ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) nasal_ref hash=local[1]; if(hash.type!=vm_hash) return builtin_err("keys","\"hash\" must be hash"); - // 把数组提前push到操作数栈上来避免被收集 - // 但是一定要检查会不会栈溢出 - 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; + // 使用gc.temp来存储gc管理的变量,防止错误的回收 + nasal_ref res=gc.temp=gc.alloc(vm_vec); + auto& vec=res.vec().elems; for(auto& iter:hash.hash().elems) - { - nasal_ref str=gc.alloc(vm_str); - str.str()=iter.first; - vec.push_back(str); - } - --gc.top; - return gc.top[1]; + vec.push_back(gc.newstr(iter.first)); + gc.temp=nil; + return res; } ``` diff --git a/main.cpp b/main.cpp index 3da57ea..c2f791f 100644 --- a/main.cpp +++ b/main.cpp @@ -109,11 +109,10 @@ void execute(const std::string& file,const std::vector& argv,const } else if(cmd&VM_EXECTIME) { - timeb begin,end; - ftime(&begin); + auto start=std::chrono::high_resolution_clock::now(); vm.run(gen,linker,argv,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO); - ftime(&end); - std::cout<<"process exited after "<<((end.time-begin.time)*1.0+end.millitm/1000.0-begin.millitm/1000.0)<<"s.\n"; + auto end=std::chrono::high_resolution_clock::now(); + std::cout<<"process exited after "<<(end-start).count()*1.0/std::chrono::high_resolution_clock::duration::period::den<<"s.\n"; } else if(cmd&VM_EXEC) vm.run(gen,linker,argv,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO); diff --git a/module/nasocket.cpp b/module/nasocket.cpp index 070e38a..69fb298 100644 --- a/module/nasocket.cpp +++ b/module/nasocket.cpp @@ -99,15 +99,12 @@ extern "C" nasal_ref nas_accept(std::vector& args,nasal_gc& gc){ #else int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen); #endif - if(gc.top+1>=gc.canary) - return builtin_err("accept","expand temporary space error:stackoverflow"); - (++gc.top)[0]=gc.alloc(vm_hash); - auto& hash=gc.top[0].hash().elems; + nasal_ref res=gc.temp=gc.alloc(vm_hash); + auto& hash=res.hash().elems; hash["sd"]={vm_num,(double)client_sd}; - hash["ip"]=gc.alloc(vm_str); - hash["ip"].str()=inet_ntoa(client.sin_addr); - --gc.top; - return gc.top[1]; + hash["ip"]=gc.newstr(inet_ntoa(client.sin_addr)); + gc.temp=nil; + return res; } extern "C" nasal_ref nas_send(std::vector& args,nasal_gc& gc){ @@ -149,17 +146,14 @@ extern "C" nasal_ref nas_recv(std::vector& args,nasal_gc& gc){ return builtin_err("recv","\"len\" out of range"); if(args[2].type!=vm_num) return builtin_err("recv","\"flags\" muse be a number"); - if(gc.top+1>=gc.canary) - return builtin_err("recv","expand temporary space error:stackoverflow"); - (++gc.top)[0]=gc.alloc(vm_hash); - auto& hash=gc.top[0].hash().elems; - hash["str"]=gc.alloc(vm_str); + nasal_ref res=gc.temp=gc.alloc(vm_hash); + auto& hash=res.hash().elems; char* buf=new char[(int)args[1].num()]; hash["size"]={vm_num,(double)recv(args[0].num(),buf,args[1].num(),args[2].num())}; - hash["str"].str()=buf; + hash["str"]=gc.newstr(buf); delete[] buf; - --gc.top; - return gc.top[1]; + gc.temp=nil; + return res; } extern "C" nasal_ref nas_recvfrom(std::vector& args,nasal_gc& gc){ @@ -171,13 +165,10 @@ extern "C" nasal_ref nas_recvfrom(std::vector& args,nasal_gc& gc){ return builtin_err("recvfrom","\"len\" out of range"); if(args[2].type!=vm_num) return builtin_err("recvfrom","\"flags\" muse be a number"); - if(gc.top+1>=gc.canary) - return builtin_err("recvfrom","expand temporary space error:stackoverflow"); sockaddr_in addr; int socklen=sizeof(sockaddr_in); - (++gc.top)[0]=gc.alloc(vm_hash); - auto& hash=gc.top[0].hash().elems; - hash["str"]=gc.alloc(vm_str); + nasal_ref res=gc.temp=gc.alloc(vm_hash); + auto& hash=res.hash().elems; char* buf=new char[(int)args[1].num()+1]; #ifdef _WIN32 hash["size"]={vm_num,(double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,&socklen)}; @@ -185,16 +176,13 @@ extern "C" nasal_ref nas_recvfrom(std::vector& args,nasal_gc& gc){ hash["size"]={vm_num,(double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,(socklen_t*)&socklen)}; #endif buf[(int)hash["size"].num()]=0; - hash["str"].str()=buf; + hash["str"]=gc.newstr(buf); delete[] buf; - hash["fromip"]=gc.alloc(vm_str); - hash["fromip"].str()=inet_ntoa(addr.sin_addr); - --gc.top; - return gc.top[1]; + hash["fromip"]=gc.newstr(inet_ntoa(addr.sin_addr)); + gc.temp=nil; + return res; } extern "C" nasal_ref nas_errno(std::vector& args,nasal_gc& gc){ - nasal_ref res=gc.alloc(vm_str); - res.str()=strerror(errno); - return res; + return gc.newstr(strerror(errno)); } \ No newline at end of file diff --git a/nasal_builtin.h b/nasal_builtin.h index 604c6b2..480e569 100644 --- a/nasal_builtin.h +++ b/nasal_builtin.h @@ -295,11 +295,9 @@ nasal_ref builtin_fin(nasal_ref* local,nasal_gc& gc) std::ifstream fin(filename); if(!fin.fail()) { - nasal_ref ret=gc.alloc(vm_str); std::stringstream rd; rd<=gc.canary) - return builtin_err("split","expand temporary space error:stackoverflow"); - (++gc.top)[0]=gc.alloc(vm_vec); + // avoid being sweeped + nasal_ref res=gc.temp=gc.alloc(vm_vec); + std::vector& vec=res.vec().elems; - std::vector& vec=gc.top[0].vec().elems; if(!delimeter_len) { for(size_t i=0;ivm_num) sprintf(buf,"%p",val.value.gcobj); else sprintf(buf,"0"); - ret.str()=buf; - return ret; + return gc.newstr(buf); } nasal_ref builtin_int(nasal_ref* local,nasal_gc& gc) { @@ -455,9 +444,7 @@ nasal_ref builtin_str(nasal_ref* local,nasal_gc& gc) std::string tmp=std::to_string(val.num()); tmp.erase(tmp.find_last_not_of('0')+1,std::string::npos); tmp.erase(tmp.find_last_not_of('.')+1,std::string::npos); - nasal_ref ret=gc.alloc(vm_str); - ret.str()=tmp; - return ret; + return gc.newstr(tmp); } nasal_ref builtin_size(nasal_ref* local,nasal_gc& gc) { @@ -637,19 +624,13 @@ nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) nasal_ref hash=local[1]; 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.canary) - return builtin_err("keys","expand temporary space error:stackoverflow"); - (++gc.top)[0]=gc.alloc(vm_vec); - auto& vec=gc.top[0].vec().elems; + // avoid being sweeped + nasal_ref res=gc.temp=gc.alloc(vm_vec); + auto& vec=res.vec().elems; for(auto& iter:hash.hash().elems) - { - nasal_ref str=gc.alloc(vm_str); - str.str()=iter.first; - vec.push_back(str); - } - --gc.top; - return gc.top[1]; + vec.push_back(gc.newstr(iter.first)); + gc.temp=nil; + return res; } nasal_ref builtin_die(nasal_ref* local,nasal_gc& gc) { @@ -674,21 +655,19 @@ nasal_ref builtin_find(nasal_ref* local,nasal_gc& gc) } nasal_ref builtin_type(nasal_ref* local,nasal_gc& gc) { - nasal_ref val=local[1]; - nasal_ref ret=gc.alloc(vm_str); - switch(val.type) + switch(local[1].type) { - case vm_none: ret.str()="undefined";break; - case vm_nil: ret.str()="nil"; break; - case vm_num: ret.str()="num"; break; - case vm_str: ret.str()="str"; break; - case vm_vec: ret.str()="vec"; break; - case vm_hash: ret.str()="hash"; break; - case vm_func: ret.str()="func"; break; - case vm_obj: ret.str()="obj"; break; - case vm_co: ret.str()="coroutine";break; + case vm_none: return gc.newstr("undefined");break; + case vm_nil: return gc.newstr("nil"); break; + case vm_num: return gc.newstr("num"); break; + case vm_str: return gc.newstr("str"); break; + case vm_vec: return gc.newstr("vec"); break; + case vm_hash: return gc.newstr("hash"); break; + case vm_func: return gc.newstr("func"); break; + case vm_obj: return gc.newstr("obj"); break; + case vm_co: return gc.newstr("coroutine");break; } - return ret; + return nil; } nasal_ref builtin_substr(nasal_ref* local,nasal_gc& gc) { @@ -709,9 +688,7 @@ nasal_ref builtin_substr(nasal_ref* local,nasal_gc& gc) size_t length=(size_t)len.num(); if(begin>=str.str().length() || begin+length>str.str().length()) return builtin_err("susbtr","index out of range"); - nasal_ref ret=gc.alloc(vm_str); - ret.str()=str.str().substr(begin,length); - return ret; + return gc.newstr(str.str().substr(begin,length)); } nasal_ref builtin_streq(nasal_ref* local,nasal_gc& gc) { @@ -730,9 +707,7 @@ nasal_ref builtin_left(nasal_ref* local,nasal_gc& gc) int length=(int)len.num(); if(length<0) length=0; - nasal_ref ret=gc.alloc(vm_str); - ret.str()=str.str().substr(0,length); - return ret; + return gc.newstr(str.str().substr(0,length)); } nasal_ref builtin_right(nasal_ref* local,nasal_gc& gc) { @@ -748,9 +723,7 @@ nasal_ref builtin_right(nasal_ref* local,nasal_gc& gc) length=srclen; if(length<0) length=0; - nasal_ref ret=gc.alloc(vm_str); - ret.str()=str.str().substr(srclen-length, srclen); - return ret; + return gc.newstr(str.str().substr(srclen-length, srclen)); } nasal_ref builtin_cmp(nasal_ref* local,nasal_gc& gc) { @@ -785,15 +758,12 @@ nasal_ref builtin_chr(nasal_ref* local,nasal_gc& gc) nasal_ref code=local[1]; if(code.type!=vm_num) return builtin_err("chr","\"code\" must be number"); - nasal_ref ret=gc.alloc(vm_str); int num=code.num(); if(0<=num && num<128) - ret.str()=(char)num; + return gc.newstr((char)num); else if(128<=num && num<256) - ret.str()=extend[num-128]; - else - ret.str()=" "; - return ret; + return gc.newstr(extend[num-128]); + return gc.newstr(" "); } nasal_ref builtin_values(nasal_ref* local,nasal_gc& gc) { @@ -1106,9 +1076,7 @@ nasal_ref builtin_readdir(nasal_ref* local,nasal_gc& gc) dirent* p=readdir((DIR*)handle.obj().ptr); if(!p) return nil; - nasal_ref ret=gc.alloc(vm_str); - ret.str()=p->d_name; - return ret; + return gc.newstr(p->d_name); } nasal_ref builtin_closedir(nasal_ref* local,nasal_gc& gc) { @@ -1131,28 +1099,22 @@ 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.canary) - return builtin_err("environ","expand temporary space error:stackoverflow"); - (++gc.top)[0]=gc.alloc(vm_vec); - auto& vec=gc.top[0].vec().elems; + nasal_ref res=gc.temp=gc.alloc(vm_vec); + auto& vec=res.vec().elems; while(*env) { - auto s=gc.alloc(vm_str); - s.str()=*env; - vec.push_back(s); + vec.push_back(gc.newstr(*env)); ++env; } - --gc.top; - return gc.top[1]; + gc.temp=nil; + return res; } nasal_ref builtin_getcwd(nasal_ref* local,nasal_gc& gc) { char buf[1024]; if(!getcwd(buf,sizeof(buf))) return builtin_err("getcwd","failed to call getcwd"); - nasal_ref str=gc.alloc(vm_str); - str.str()=buf; - return str; + return gc.newstr(buf); } nasal_ref builtin_getenv(nasal_ref* local,nasal_gc& gc) { @@ -1162,9 +1124,7 @@ nasal_ref builtin_getenv(nasal_ref* local,nasal_gc& gc) char* res=getenv(envvar.str().c_str()); if(!res) return nil; - nasal_ref str=gc.alloc(vm_str); - str.str()=res; - return str; + return gc.newstr(res); } void obj_dylib_destructor(void* ptr) { @@ -1241,15 +1201,14 @@ nasal_ref builtin_dlcall(nasal_ref* local,nasal_gc& gc) } nasal_ref builtin_platform(nasal_ref* local,nasal_gc& gc) { - nasal_ref ret=gc.alloc(vm_str); #if defined _WIN32 || defined _WIN64 - ret.str()="windows"; + return gc.newstr("windows"); #elif defined __linux__ - ret.str()="linux"; + return gc.newstr("linux"); #elif defined __APPLE__ - ret.str()="macOS"; + return gc.newstr("macOS"); #endif - return ret; + return gc.newstr("unknown"); } nasal_ref builtin_gc(nasal_ref* local,nasal_gc& gc) { @@ -1347,9 +1306,7 @@ nasal_ref builtin_md5(nasal_ref* local,nasal_gc& gc) nasal_ref str=local[1]; if(str.type!=vm_str) return builtin_err("md5","\"str\" must be a string"); - nasal_ref res=gc.alloc(vm_str); - res.str()=md5(str.str()); - return res; + return gc.newstr(md5(str.str())); } nasal_ref builtin_cocreate(nasal_ref* local,nasal_gc& gc) @@ -1416,14 +1373,13 @@ nasal_ref builtin_costatus(nasal_ref* local,nasal_gc& gc) nasal_ref co=local[1]; if(co.type!=vm_co) return builtin_err("coroutine::status","must use a coroutine object"); - nasal_ref res=gc.alloc(vm_str); switch(co.co().status) { - case nasal_co::suspended: res.str()="suspended";break; - case nasal_co::running: res.str()="running"; break; - case nasal_co::dead: res.str()="dead"; break; + case nasal_co::suspended: return gc.newstr("suspended");break; + case nasal_co::running: return gc.newstr("running"); break; + case nasal_co::dead: return gc.newstr("dead"); break; } - return res; + return nil; } nasal_ref builtin_corun(nasal_ref* local,nasal_gc& gc) { @@ -1449,8 +1405,6 @@ nasal_ref builtin_logtime(nasal_ref* local,nasal_gc& gc) tm* tm_t=localtime(&t); char s[128]; sprintf(s,"%d-%.2d-%.2d %.2d:%.2d:%.2d",tm_t->tm_year+1900,tm_t->tm_mon+1,tm_t->tm_mday,tm_t->tm_hour,tm_t->tm_min,tm_t->tm_sec); - nasal_ref res=gc.alloc(vm_str); - res.str()=s; - return res; + return gc.newstr(s); } #endif \ No newline at end of file diff --git a/nasal_gc.h b/nasal_gc.h index 63a8025..df308d0 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -456,6 +456,7 @@ struct nasal_gc nasal_ref*& top; // stack top nasal_ref* stack; // stack pointer nasal_co* coroutine; // running coroutine + nasal_ref temp; // temporary place used in builtin/module functions /* constants and memory pool */ std::vector strs; // reserved address for const vm_str @@ -483,14 +484,17 @@ struct nasal_gc upvalr(_upvalr), canary(_canary), top(_top), - stack(_stk){} + stack(_stk), + temp(nil){} void mark(); void sweep(); void init(const std::vector&,const std::vector&); void clear(); void info(); nasal_ref alloc(const uint8_t); - nasal_ref builtin_alloc(const uint8_t); + nasal_ref newstr(char); + nasal_ref newstr(const char*); + nasal_ref newstr(const std::string&); void ctxchg(nasal_co&); void ctxreserve(); }; @@ -507,6 +511,7 @@ void nasal_gc::mark() bfs.push(*i); bfs.push(funcr); bfs.push(upvalr); + bfs.push(temp); if(coroutine) // scan main process stack { for(nasal_ref* i=main_ctx.stack;i<=main_ctx.top;++i) @@ -654,28 +659,23 @@ nasal_ref nasal_gc::alloc(uint8_t type) unused[index].pop(); return ret; } -nasal_ref nasal_gc::builtin_alloc(uint8_t type) +nasal_ref nasal_gc::newstr(char c) { - // when running a builtin function,alloc will run more than one time - // this may cause mark-sweep in gc::alloc - // and the value got before will be collected,this is a fatal error - // so use builtin_alloc in builtin functions if this function uses alloc more then one time - const uint8_t index=type-vm_str; - ++allocc[index]; - if(unused[index].empty()) - { - ++size[index]; - for(uint32_t i=0;imark=GC_UNCOLLECTED; - unused[index].pop(); - return ret; + nasal_ref s=alloc(vm_str); + s.str()=c; + return s; +} +nasal_ref nasal_gc::newstr(const char* buff) +{ + nasal_ref s=alloc(vm_str); + s.str()=buff; + return s; +} +nasal_ref nasal_gc::newstr(const std::string& buff) +{ + nasal_ref s=alloc(vm_str); + s.str()=buff; + return s; } void nasal_gc::ctxchg(nasal_co& context) { diff --git a/nasal_vm.h b/nasal_vm.h index 9d3f8fd..0427a33 100644 --- a/nasal_vm.h +++ b/nasal_vm.h @@ -526,8 +526,7 @@ inline void nasal_vm::opr_mul(){op_calc(*);} inline void nasal_vm::opr_div(){op_calc(/);} inline void nasal_vm::opr_lnk() { - nasal_ref val=gc.alloc(vm_str); - val.str()=top[-1].tostr()+top[0].tostr(); + nasal_ref val=gc.newstr(top[-1].tostr()+top[0].tostr()); (--top)[0]=val; } @@ -541,8 +540,7 @@ inline void nasal_vm::opr_mulc(){op_calc_const(*);} inline void nasal_vm::opr_divc(){op_calc_const(/);} inline void nasal_vm::opr_lnkc() { - nasal_ref val=gc.alloc(vm_str); - val.str()=top[0].tostr()+str_table[imm[pc]]; + nasal_ref val=gc.newstr(top[0].tostr()+str_table[imm[pc]]); top[0]=val; } @@ -558,8 +556,7 @@ inline void nasal_vm::opr_muleq(){op_calc_eq(*);} inline void nasal_vm::opr_diveq(){op_calc_eq(/);} inline void nasal_vm::opr_lnkeq() { - nasal_ref val=gc.alloc(vm_str); - val.str()=memr[0].tostr()+top[-1].tostr(); + nasal_ref val=gc.newstr(memr[0].tostr()+top[-1].tostr()); (--top)[0]=memr[0]=val; memr=nullptr; top-=imm[pc]; @@ -577,8 +574,7 @@ inline void nasal_vm::opr_muleqc(){op_calc_eq_const(*);} inline void nasal_vm::opr_diveqc(){op_calc_eq_const(/);} inline void nasal_vm::opr_lnkeqc() { - nasal_ref val=gc.alloc(vm_str); - val.str()=memr[0].tostr()+str_table[imm[pc]&0x7fffffff]; + nasal_ref val=gc.newstr(memr[0].tostr()+str_table[imm[pc]&0x7fffffff]); top[0]=memr[0]=val; memr=nullptr; top-=(imm[pc]>>31);