optimize codes. details:

1. delete gc::builtin_alloc
2. add convenient way of getting new string object: gc::newstr, and shrink the size of codes
3. update doc
4. add gc::temp to be used in native/module functions to avoid being recognized as garbage incorrectly when triggered mark-sweep
This commit is contained in:
ValKmjolnir 2022-07-07 17:51:30 +08:00
parent 75c46fa727
commit fb25a4973c
7 changed files with 128 additions and 209 deletions

View File

@ -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, this built-in function may cause a fault when searching arguments,
which will cause __segmentation error__. which will cause __segmentation error__.
Use `import("filename.nas")` to get the nasal file including your built-in functions, Use `import("filename.nas")` to get the nasal file including your built-in functions, then you could use it.
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, So use `gc::temp` in builtin functions to temprorarily store the gc-managed value that you want to return later. Like this:
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:
```C++ ```C++
nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) 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]; nasal_ref hash=local[1];
if(hash.type!=vm_hash) if(hash.type!=vm_hash)
return builtin_err("keys","\"hash\" must be hash"); return builtin_err("keys","\"hash\" must be hash");
// push vector into local scope to avoid being sweeped // avoid being sweeped
if(gc.top+1>=gc.canary) nasal_ref res=gc.temp=gc.alloc(vm_vec);
return builtin_err("keys","expand temporary space error:stackoverflow"); auto& vec=res.vec().elems;
(++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems;
for(auto& iter:hash.hash().elems) for(auto& iter:hash.hash().elems)
{ vec.push_back(gc.newstr(iter.first));
nasal_ref str=gc.alloc(vm_str); gc.temp=nil;
str.str()=iter.first; return res;
vec.push_back(str);
}
--gc.top;
return gc.top[1];
} }
``` ```

View File

@ -642,18 +642,17 @@ var print=func(elems...){
一定要注意如果你不把内置函数包装到一个普通的nasal函数中那么直接调用这个内置函数会在参数传入阶段出现严重的错误这个错误会导致 __segmentation error__。也就是大家的老朋友段错误。 一定要注意如果你不把内置函数包装到一个普通的nasal函数中那么直接调用这个内置函数会在参数传入阶段出现严重的错误这个错误会导致 __segmentation error__。也就是大家的老朋友段错误。
在nasal文件中使用`import("文件名.nas")`可以导入该文件中你包装的所有内置函数,接下来你就可以使用他们了。 在nasal文件中使用`import("文件名.nas")`可以导入该文件中你包装的所有内置函数,接下来你就可以使用他们了。
当然也有另外一种办法来导入这些nasal文件下面两种导入方式的效果是一样的
v6.5 更新: ```javascript
import.dirname.dirname.filename;
在内置函数中使用`gc::builtin_alloc`来避免在内置函数中多次申请需要内存管理的数据类型时可能出现的垃圾收集器的问题。 import("./dirname/dirname/filename.nas");
```
当运行内置函数的时候内存分配器如果运行超过一次那么会有更大可能性多次触发垃圾收集器的mark-sweep。这个操作会在`gc::alloc`中触发。 当运行内置函数的时候内存分配器如果运行超过一次那么会有更大可能性多次触发垃圾收集器的mark-sweep。这个操作会在`gc::alloc`中触发。
如果先前获取的数值没有被正确存到可以被垃圾收集器索引到的地方,那么它会被错误地回收,这会导致严重的错误。 如果先前获取的数值没有被正确存到可以被垃圾收集器索引到的地方,那么它会被错误地回收,这会导致严重的错误。
所以如果不放心,那就在内置函数中用`gc::builtin_alloc`来申请新的数据。 所以请使用`gc::temp`来暂时存储一个会被返回的需要gc管理的变量这样可以防止内部所有的申请错误触发垃圾回收。如下所示
或者你也可以这样使用`gc::alloc`来规避错误的垃圾回收,目前我们大多使用这种方式,因为`gc::builtin_alloc`没那么靠谱:
```C++ ```C++
nasal_ref builtin_keys(nasal_ref* local,nasal_gc& gc) 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]; nasal_ref hash=local[1];
if(hash.type!=vm_hash) if(hash.type!=vm_hash)
return builtin_err("keys","\"hash\" must be hash"); return builtin_err("keys","\"hash\" must be hash");
// 把数组提前push到操作数栈上来避免被收集 // 使用gc.temp来存储gc管理的变量防止错误的回收
// 但是一定要检查会不会栈溢出 nasal_ref res=gc.temp=gc.alloc(vm_vec);
if(gc.top+1>=gc.canary) auto& vec=res.vec().elems;
return builtin_err("keys","expand temporary space error:stackoverflow");
(++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems;
for(auto& iter:hash.hash().elems) for(auto& iter:hash.hash().elems)
{ vec.push_back(gc.newstr(iter.first));
nasal_ref str=gc.alloc(vm_str); gc.temp=nil;
str.str()=iter.first; return res;
vec.push_back(str);
}
--gc.top;
return gc.top[1];
} }
``` ```

View File

@ -109,11 +109,10 @@ void execute(const std::string& file,const std::vector<std::string>& argv,const
} }
else if(cmd&VM_EXECTIME) else if(cmd&VM_EXECTIME)
{ {
timeb begin,end; auto start=std::chrono::high_resolution_clock::now();
ftime(&begin);
vm.run(gen,linker,argv,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO); vm.run(gen,linker,argv,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO);
ftime(&end); auto end=std::chrono::high_resolution_clock::now();
std::cout<<"process exited after "<<((end.time-begin.time)*1.0+end.millitm/1000.0-begin.millitm/1000.0)<<"s.\n"; 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) else if(cmd&VM_EXEC)
vm.run(gen,linker,argv,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO); vm.run(gen,linker,argv,cmd&VM_OPCALLNUM,cmd&VM_DBGINFO);

View File

@ -99,15 +99,12 @@ extern "C" nasal_ref nas_accept(std::vector<nasal_ref>& args,nasal_gc& gc){
#else #else
int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen); int client_sd=accept(args[0].num(),(sockaddr*)&client,(socklen_t*)&socklen);
#endif #endif
if(gc.top+1>=gc.canary) nasal_ref res=gc.temp=gc.alloc(vm_hash);
return builtin_err("accept","expand temporary space error:stackoverflow"); auto& hash=res.hash().elems;
(++gc.top)[0]=gc.alloc(vm_hash);
auto& hash=gc.top[0].hash().elems;
hash["sd"]={vm_num,(double)client_sd}; hash["sd"]={vm_num,(double)client_sd};
hash["ip"]=gc.alloc(vm_str); hash["ip"]=gc.newstr(inet_ntoa(client.sin_addr));
hash["ip"].str()=inet_ntoa(client.sin_addr); gc.temp=nil;
--gc.top; return res;
return gc.top[1];
} }
extern "C" nasal_ref nas_send(std::vector<nasal_ref>& args,nasal_gc& gc){ extern "C" nasal_ref nas_send(std::vector<nasal_ref>& args,nasal_gc& gc){
@ -149,17 +146,14 @@ extern "C" nasal_ref nas_recv(std::vector<nasal_ref>& args,nasal_gc& gc){
return builtin_err("recv","\"len\" out of range"); return builtin_err("recv","\"len\" out of range");
if(args[2].type!=vm_num) if(args[2].type!=vm_num)
return builtin_err("recv","\"flags\" muse be a number"); return builtin_err("recv","\"flags\" muse be a number");
if(gc.top+1>=gc.canary) nasal_ref res=gc.temp=gc.alloc(vm_hash);
return builtin_err("recv","expand temporary space error:stackoverflow"); auto& hash=res.hash().elems;
(++gc.top)[0]=gc.alloc(vm_hash);
auto& hash=gc.top[0].hash().elems;
hash["str"]=gc.alloc(vm_str);
char* buf=new char[(int)args[1].num()]; 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["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; delete[] buf;
--gc.top; gc.temp=nil;
return gc.top[1]; return res;
} }
extern "C" nasal_ref nas_recvfrom(std::vector<nasal_ref>& args,nasal_gc& gc){ extern "C" nasal_ref nas_recvfrom(std::vector<nasal_ref>& args,nasal_gc& gc){
@ -171,13 +165,10 @@ extern "C" nasal_ref nas_recvfrom(std::vector<nasal_ref>& args,nasal_gc& gc){
return builtin_err("recvfrom","\"len\" out of range"); return builtin_err("recvfrom","\"len\" out of range");
if(args[2].type!=vm_num) if(args[2].type!=vm_num)
return builtin_err("recvfrom","\"flags\" muse be a number"); 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; sockaddr_in addr;
int socklen=sizeof(sockaddr_in); int socklen=sizeof(sockaddr_in);
(++gc.top)[0]=gc.alloc(vm_hash); nasal_ref res=gc.temp=gc.alloc(vm_hash);
auto& hash=gc.top[0].hash().elems; auto& hash=res.hash().elems;
hash["str"]=gc.alloc(vm_str);
char* buf=new char[(int)args[1].num()+1]; char* buf=new char[(int)args[1].num()+1];
#ifdef _WIN32 #ifdef _WIN32
hash["size"]={vm_num,(double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,&socklen)}; 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<nasal_ref>& 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)}; hash["size"]={vm_num,(double)recvfrom(args[0].num(),buf,args[1].num(),args[2].num(),(sockaddr*)&addr,(socklen_t*)&socklen)};
#endif #endif
buf[(int)hash["size"].num()]=0; buf[(int)hash["size"].num()]=0;
hash["str"].str()=buf; hash["str"]=gc.newstr(buf);
delete[] buf; delete[] buf;
hash["fromip"]=gc.alloc(vm_str); hash["fromip"]=gc.newstr(inet_ntoa(addr.sin_addr));
hash["fromip"].str()=inet_ntoa(addr.sin_addr); gc.temp=nil;
--gc.top; return res;
return gc.top[1];
} }
extern "C" nasal_ref nas_errno(std::vector<nasal_ref>& args,nasal_gc& gc){ extern "C" nasal_ref nas_errno(std::vector<nasal_ref>& args,nasal_gc& gc){
nasal_ref res=gc.alloc(vm_str); return gc.newstr(strerror(errno));
res.str()=strerror(errno);
return res;
} }

View File

@ -295,11 +295,9 @@ nasal_ref builtin_fin(nasal_ref* local,nasal_gc& gc)
std::ifstream fin(filename); std::ifstream fin(filename);
if(!fin.fail()) if(!fin.fail())
{ {
nasal_ref ret=gc.alloc(vm_str);
std::stringstream rd; std::stringstream rd;
rd<<fin.rdbuf(); rd<<fin.rdbuf();
ret.str()=rd.str(); return gc.newstr(rd.str());
return ret;
} }
return builtin_err("io.fin","cannot open \""+filename+"\""); return builtin_err("io.fin","cannot open \""+filename+"\"");
} }
@ -330,21 +328,16 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc)
size_t delimeter_len=delimeter.length(); size_t delimeter_len=delimeter.length();
size_t source_len=source.length(); size_t source_len=source.length();
// push it to local scope to avoid being sweeped // avoid being sweeped
if(gc.top+1>=gc.canary) nasal_ref res=gc.temp=gc.alloc(vm_vec);
return builtin_err("split","expand temporary space error:stackoverflow"); std::vector<nasal_ref>& vec=res.vec().elems;
(++gc.top)[0]=gc.alloc(vm_vec);
std::vector<nasal_ref>& vec=gc.top[0].vec().elems;
if(!delimeter_len) if(!delimeter_len)
{ {
for(size_t i=0;i<source_len;++i) for(size_t i=0;i<source_len;++i)
{ vec.push_back(gc.newstr(source[i]));
vec.push_back(gc.alloc(vm_str)); gc.temp=nil;
vec.back().str()=source[i]; return res;
}
--gc.top;
return gc.top[1];
} }
std::string tmp=""; std::string tmp="";
@ -363,8 +356,7 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc)
{ {
if(tmp.length()) if(tmp.length())
{ {
vec.push_back(gc.alloc(vm_str)); vec.push_back(gc.newstr(tmp));
vec.back().str()=tmp;
tmp=""; tmp="";
} }
i+=delimeter_len-1; i+=delimeter_len-1;
@ -374,12 +366,11 @@ nasal_ref builtin_split(nasal_ref* local,nasal_gc& gc)
} }
if(tmp.length()) if(tmp.length())
{ {
vec.push_back(gc.alloc(vm_str)); vec.push_back(gc.newstr(tmp));
vec.back().str()=tmp;
tmp=""; tmp="";
} }
--gc.top; gc.temp=nil;
return gc.top[1]; return res;
} }
nasal_ref builtin_rand(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_rand(nasal_ref* local,nasal_gc& gc)
{ {
@ -399,14 +390,12 @@ nasal_ref builtin_rand(nasal_ref* local,nasal_gc& gc)
nasal_ref builtin_id(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_id(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref val=local[1]; nasal_ref val=local[1];
nasal_ref ret=gc.alloc(vm_str);
char buf[32]; char buf[32];
if(val.type>vm_num) if(val.type>vm_num)
sprintf(buf,"%p",val.value.gcobj); sprintf(buf,"%p",val.value.gcobj);
else else
sprintf(buf,"0"); sprintf(buf,"0");
ret.str()=buf; return gc.newstr(buf);
return ret;
} }
nasal_ref builtin_int(nasal_ref* local,nasal_gc& gc) 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()); 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('0')+1,std::string::npos);
tmp.erase(tmp.find_last_not_of('.')+1,std::string::npos); tmp.erase(tmp.find_last_not_of('.')+1,std::string::npos);
nasal_ref ret=gc.alloc(vm_str); return gc.newstr(tmp);
ret.str()=tmp;
return ret;
} }
nasal_ref builtin_size(nasal_ref* local,nasal_gc& gc) 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]; nasal_ref hash=local[1];
if(hash.type!=vm_hash) if(hash.type!=vm_hash)
return builtin_err("keys","\"hash\" must be hash"); return builtin_err("keys","\"hash\" must be hash");
// push vector into local scope to avoid being sweeped // avoid being sweeped
if(gc.top+1>=gc.canary) nasal_ref res=gc.temp=gc.alloc(vm_vec);
return builtin_err("keys","expand temporary space error:stackoverflow"); auto& vec=res.vec().elems;
(++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems;
for(auto& iter:hash.hash().elems) for(auto& iter:hash.hash().elems)
{ vec.push_back(gc.newstr(iter.first));
nasal_ref str=gc.alloc(vm_str); gc.temp=nil;
str.str()=iter.first; return res;
vec.push_back(str);
}
--gc.top;
return gc.top[1];
} }
nasal_ref builtin_die(nasal_ref* local,nasal_gc& gc) 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 builtin_type(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref val=local[1]; switch(local[1].type)
nasal_ref ret=gc.alloc(vm_str);
switch(val.type)
{ {
case vm_none: ret.str()="undefined";break; case vm_none: return gc.newstr("undefined");break;
case vm_nil: ret.str()="nil"; break; case vm_nil: return gc.newstr("nil"); break;
case vm_num: ret.str()="num"; break; case vm_num: return gc.newstr("num"); break;
case vm_str: ret.str()="str"; break; case vm_str: return gc.newstr("str"); break;
case vm_vec: ret.str()="vec"; break; case vm_vec: return gc.newstr("vec"); break;
case vm_hash: ret.str()="hash"; break; case vm_hash: return gc.newstr("hash"); break;
case vm_func: ret.str()="func"; break; case vm_func: return gc.newstr("func"); break;
case vm_obj: ret.str()="obj"; break; case vm_obj: return gc.newstr("obj"); break;
case vm_co: ret.str()="coroutine";break; case vm_co: return gc.newstr("coroutine");break;
} }
return ret; return nil;
} }
nasal_ref builtin_substr(nasal_ref* local,nasal_gc& gc) 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(); size_t length=(size_t)len.num();
if(begin>=str.str().length() || begin+length>str.str().length()) if(begin>=str.str().length() || begin+length>str.str().length())
return builtin_err("susbtr","index out of range"); return builtin_err("susbtr","index out of range");
nasal_ref ret=gc.alloc(vm_str); return gc.newstr(str.str().substr(begin,length));
ret.str()=str.str().substr(begin,length);
return ret;
} }
nasal_ref builtin_streq(nasal_ref* local,nasal_gc& gc) 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(); int length=(int)len.num();
if(length<0) if(length<0)
length=0; length=0;
nasal_ref ret=gc.alloc(vm_str); return gc.newstr(str.str().substr(0,length));
ret.str()=str.str().substr(0,length);
return ret;
} }
nasal_ref builtin_right(nasal_ref* local,nasal_gc& gc) 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; length=srclen;
if(length<0) if(length<0)
length=0; length=0;
nasal_ref ret=gc.alloc(vm_str); return gc.newstr(str.str().substr(srclen-length, srclen));
ret.str()=str.str().substr(srclen-length, srclen);
return ret;
} }
nasal_ref builtin_cmp(nasal_ref* local,nasal_gc& gc) 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]; nasal_ref code=local[1];
if(code.type!=vm_num) if(code.type!=vm_num)
return builtin_err("chr","\"code\" must be number"); return builtin_err("chr","\"code\" must be number");
nasal_ref ret=gc.alloc(vm_str);
int num=code.num(); int num=code.num();
if(0<=num && num<128) if(0<=num && num<128)
ret.str()=(char)num; return gc.newstr((char)num);
else if(128<=num && num<256) else if(128<=num && num<256)
ret.str()=extend[num-128]; return gc.newstr(extend[num-128]);
else return gc.newstr(" ");
ret.str()=" ";
return ret;
} }
nasal_ref builtin_values(nasal_ref* local,nasal_gc& gc) 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); dirent* p=readdir((DIR*)handle.obj().ptr);
if(!p) if(!p)
return nil; return nil;
nasal_ref ret=gc.alloc(vm_str); return gc.newstr(p->d_name);
ret.str()=p->d_name;
return ret;
} }
nasal_ref builtin_closedir(nasal_ref* local,nasal_gc& gc) 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) nasal_ref builtin_environ(nasal_ref* local,nasal_gc& gc)
{ {
char** env=environ; char** env=environ;
if(gc.top+1>=gc.canary) nasal_ref res=gc.temp=gc.alloc(vm_vec);
return builtin_err("environ","expand temporary space error:stackoverflow"); auto& vec=res.vec().elems;
(++gc.top)[0]=gc.alloc(vm_vec);
auto& vec=gc.top[0].vec().elems;
while(*env) while(*env)
{ {
auto s=gc.alloc(vm_str); vec.push_back(gc.newstr(*env));
s.str()=*env;
vec.push_back(s);
++env; ++env;
} }
--gc.top; gc.temp=nil;
return gc.top[1]; return res;
} }
nasal_ref builtin_getcwd(nasal_ref* local,nasal_gc& gc) nasal_ref builtin_getcwd(nasal_ref* local,nasal_gc& gc)
{ {
char buf[1024]; char buf[1024];
if(!getcwd(buf,sizeof(buf))) if(!getcwd(buf,sizeof(buf)))
return builtin_err("getcwd","failed to call getcwd"); return builtin_err("getcwd","failed to call getcwd");
nasal_ref str=gc.alloc(vm_str); return gc.newstr(buf);
str.str()=buf;
return str;
} }
nasal_ref builtin_getenv(nasal_ref* local,nasal_gc& gc) 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()); char* res=getenv(envvar.str().c_str());
if(!res) if(!res)
return nil; return nil;
nasal_ref str=gc.alloc(vm_str); return gc.newstr(res);
str.str()=res;
return str;
} }
void obj_dylib_destructor(void* ptr) 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 builtin_platform(nasal_ref* local,nasal_gc& gc)
{ {
nasal_ref ret=gc.alloc(vm_str);
#if defined _WIN32 || defined _WIN64 #if defined _WIN32 || defined _WIN64
ret.str()="windows"; return gc.newstr("windows");
#elif defined __linux__ #elif defined __linux__
ret.str()="linux"; return gc.newstr("linux");
#elif defined __APPLE__ #elif defined __APPLE__
ret.str()="macOS"; return gc.newstr("macOS");
#endif #endif
return ret; return gc.newstr("unknown");
} }
nasal_ref builtin_gc(nasal_ref* local,nasal_gc& gc) 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]; nasal_ref str=local[1];
if(str.type!=vm_str) if(str.type!=vm_str)
return builtin_err("md5","\"str\" must be a string"); return builtin_err("md5","\"str\" must be a string");
nasal_ref res=gc.alloc(vm_str); return gc.newstr(md5(str.str()));
res.str()=md5(str.str());
return res;
} }
nasal_ref builtin_cocreate(nasal_ref* local,nasal_gc& gc) 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]; nasal_ref co=local[1];
if(co.type!=vm_co) if(co.type!=vm_co)
return builtin_err("coroutine::status","must use a coroutine object"); return builtin_err("coroutine::status","must use a coroutine object");
nasal_ref res=gc.alloc(vm_str);
switch(co.co().status) switch(co.co().status)
{ {
case nasal_co::suspended: res.str()="suspended";break; case nasal_co::suspended: return gc.newstr("suspended");break;
case nasal_co::running: res.str()="running"; break; case nasal_co::running: return gc.newstr("running"); break;
case nasal_co::dead: res.str()="dead"; break; case nasal_co::dead: return gc.newstr("dead"); break;
} }
return res; return nil;
} }
nasal_ref builtin_corun(nasal_ref* local,nasal_gc& gc) 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); tm* tm_t=localtime(&t);
char s[128]; 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); 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); return gc.newstr(s);
res.str()=s;
return res;
} }
#endif #endif

View File

@ -456,6 +456,7 @@ struct nasal_gc
nasal_ref*& top; // stack top nasal_ref*& top; // stack top
nasal_ref* stack; // stack pointer nasal_ref* stack; // stack pointer
nasal_co* coroutine; // running coroutine nasal_co* coroutine; // running coroutine
nasal_ref temp; // temporary place used in builtin/module functions
/* 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
@ -483,14 +484,17 @@ struct nasal_gc
upvalr(_upvalr), upvalr(_upvalr),
canary(_canary), canary(_canary),
top(_top), top(_top),
stack(_stk){} stack(_stk),
temp(nil){}
void mark(); void mark();
void sweep(); void sweep();
void init(const std::vector<std::string>&,const std::vector<std::string>&); void init(const std::vector<std::string>&,const std::vector<std::string>&);
void clear(); void clear();
void info(); void info();
nasal_ref alloc(const uint8_t); 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 ctxchg(nasal_co&);
void ctxreserve(); void ctxreserve();
}; };
@ -507,6 +511,7 @@ void nasal_gc::mark()
bfs.push(*i); bfs.push(*i);
bfs.push(funcr); bfs.push(funcr);
bfs.push(upvalr); bfs.push(upvalr);
bfs.push(temp);
if(coroutine) // scan main process stack if(coroutine) // scan main process stack
{ {
for(nasal_ref* i=main_ctx.stack;i<=main_ctx.top;++i) 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(); unused[index].pop();
return ret; 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 nasal_ref s=alloc(vm_str);
// this may cause mark-sweep in gc::alloc s.str()=c;
// and the value got before will be collected,this is a fatal error return s;
// so use builtin_alloc in builtin functions if this function uses alloc more then one time }
const uint8_t index=type-vm_str; nasal_ref nasal_gc::newstr(const char* buff)
++allocc[index]; {
if(unused[index].empty()) nasal_ref s=alloc(vm_str);
{ s.str()=buff;
++size[index]; return s;
for(uint32_t i=0;i<incr[index];++i) }
{ nasal_ref nasal_gc::newstr(const std::string& buff)
nasal_val* tmp=new nasal_val(type); {
memory.push_back(tmp); nasal_ref s=alloc(vm_str);
unused[index].push(tmp); s.str()=buff;
} return s;
}
nasal_ref ret={type,unused[index].front()};
ret.value.gcobj->mark=GC_UNCOLLECTED;
unused[index].pop();
return ret;
} }
void nasal_gc::ctxchg(nasal_co& context) void nasal_gc::ctxchg(nasal_co& context)
{ {

View File

@ -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_div(){op_calc(/);}
inline void nasal_vm::opr_lnk() inline void nasal_vm::opr_lnk()
{ {
nasal_ref val=gc.alloc(vm_str); nasal_ref val=gc.newstr(top[-1].tostr()+top[0].tostr());
val.str()=top[-1].tostr()+top[0].tostr();
(--top)[0]=val; (--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_divc(){op_calc_const(/);}
inline void nasal_vm::opr_lnkc() inline void nasal_vm::opr_lnkc()
{ {
nasal_ref val=gc.alloc(vm_str); nasal_ref val=gc.newstr(top[0].tostr()+str_table[imm[pc]]);
val.str()=top[0].tostr()+str_table[imm[pc]];
top[0]=val; 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_diveq(){op_calc_eq(/);}
inline void nasal_vm::opr_lnkeq() inline void nasal_vm::opr_lnkeq()
{ {
nasal_ref val=gc.alloc(vm_str); nasal_ref val=gc.newstr(memr[0].tostr()+top[-1].tostr());
val.str()=memr[0].tostr()+top[-1].tostr();
(--top)[0]=memr[0]=val; (--top)[0]=memr[0]=val;
memr=nullptr; memr=nullptr;
top-=imm[pc]; 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_diveqc(){op_calc_eq_const(/);}
inline void nasal_vm::opr_lnkeqc() inline void nasal_vm::opr_lnkeqc()
{ {
nasal_ref val=gc.alloc(vm_str); nasal_ref val=gc.newstr(memr[0].tostr()+str_table[imm[pc]&0x7fffffff]);
val.str()=memr[0].tostr()+str_table[imm[pc]&0x7fffffff];
top[0]=memr[0]=val; top[0]=memr[0]=val;
memr=nullptr; memr=nullptr;
top-=(imm[pc]>>31); top-=(imm[pc]>>31);