diff --git a/README.md b/README.md index 8c5d5a6..9ca6eda 100644 --- a/README.md +++ b/README.md @@ -551,31 +551,48 @@ And `get` has the same process. And we must remind you that if you do this: ```javascript -var b=a.get; -println(b()); -println(b()); +var trait={ + get:func{return me.val;}, + set:func(x){me.val=x;} +}; + +var class={ + new:func(){ + return { + val:nil, + parents:[trait] + }; + } +}; +var a=class.new(); +var b=class.new(); +a.set(114); +b.set(514); +println(a.get()); +println(b.get()); + +var c=a.get; +var d=b.get; + +println(c()); +println(c()); +println(d()); +println(d()); ``` -You will find the vm crashes: +You will get this result now: ```bash -114514 -114514 -[vm] callh: must call a hash -trace back: - 0x0000050f: 3d 00 00 00 08 callh 0x8 ("val") (a.nas:2) - 0x00000544: 3e 00 00 00 00 callfv 0x0 (a.nas:19) -vm stack(0x7fffd1b38250, limit 10, total 7): - 0x00000059 | nil | - 0x00000058 | pc | 0x544 - 0x00000057 | addr | 0x0 - 0x00000056 | nil | - 0x00000055 | nil | - 0x00000054 | nil | - 0x00000053 | func | <0x1a3b250> entry:0x125 +114 +514 +514 +514 +514 +514 ``` -Because `a.get` will set `me=a` in the `trait.get`. First time we running it, it works. But when the function returns, `me` is set to `nil`, so the second time, we failed to call the function. +Because `a.get` will set `me=a` in the `trait.get`. Then `b.get` do the `me=b`. So in fact c is `b.get` too after running `var d=b.get`. +If you want to use this trick to make the program running more efficiently, you must know this special mechanism. ### __native functions__ diff --git a/doc/README_zh.md b/doc/README_zh.md index 946a1f4..593ae81 100644 --- a/doc/README_zh.md +++ b/doc/README_zh.md @@ -518,31 +518,48 @@ println(a.get()); 不过我们必须提醒你一点,如果你在这个地方使用该优化来减少hash的搜索开销: ```javascript -var b=a.get; -println(b()); -println(b()); +var trait={ + get:func{return me.val;}, + set:func(x){me.val=x;} +}; + +var class={ + new:func(){ + return { + val:nil, + parents:[trait] + }; + } +}; +var a=class.new(); +var b=class.new(); +a.set(114); +b.set(514); +println(a.get()); +println(b.get()); + +var c=a.get; +var d=b.get; + +println(c()); +println(c()); +println(d()); +println(d()); ``` -那么你会发现虚拟机崩溃了: +那么你会发现现在虚拟机会输出这个结果: ```bash -114514 -114514 -[vm] callh: must call a hash -trace back: - 0x0000050f: 3d 00 00 00 08 callh 0x8 ("val") (a.nas:2) - 0x00000544: 3e 00 00 00 00 callfv 0x0 (a.nas:19) -vm stack(0x7fffd1b38250, limit 10, total 7): - 0x00000059 | nil | - 0x00000058 | pc | 0x544 - 0x00000057 | addr | 0x0 - 0x00000056 | nil | - 0x00000055 | nil | - 0x00000054 | nil | - 0x00000053 | func | <0x1a3b250> entry:0x125 +114 +514 +514 +514 +514 +514 ``` -因为执行`a.get`时在`trait.get`函数的属性中进行了`me=a`的操作。所以接下来第一次运行的时候它确实成功运行了。但是当函数返回时,`me`会被自动设置为`nil`以保证安全,所以第二次调用的时候,`me`不再是个hash类型,故虚拟机抛出了错误。这不意味着这种优化方法是不可行的,只要你理解了它的运行机制,这种优化方式仍然可以使用。 +因为执行`a.get`时在`trait.get`函数的属性中进行了`me=a`的操作。而`b.get`则执行了`me=b`的操作。所以在运行`var d=b.get`后实际上c也变成`b.get`了。 +如果你想要用这种小技巧来让程序运行更高效的话,最好是要知道这里存在这样一个机制。 ### __内置函数__ diff --git a/nasal.h b/nasal.h index 30f77de..9cfd83a 100644 --- a/nasal.h +++ b/nasal.h @@ -43,7 +43,7 @@ #define PRTINT64 "%lld" #endif -const uint32_t STACK_DEPTH=8192; +const uint32_t STACK_DEPTH=4096; inline double hex_to_double(const char* str) { diff --git a/nasal_dbg.h b/nasal_dbg.h index ca7e571..daa2b29 100644 --- a/nasal_dbg.h +++ b/nasal_dbg.h @@ -182,7 +182,7 @@ void nasal_dbg::run( { detail_info=true; init(gen.get_strs(),gen.get_nums(),gen.get_code(),linker.get_file(),argv); - const void* opr_table[]= + const void* oprs[]= { &&vmexit, &&intg, &&intl, &&loadg, &&loadl, &&loadu, &&pnum, &&pnil, @@ -207,7 +207,7 @@ void nasal_dbg::run( std::vector code; for(auto& i:gen.get_code()) { - code.push_back(opr_table[i.op]); + code.push_back(oprs[i.op]); imm.push_back(i.num); } // goto the first operand diff --git a/nasal_gc.h b/nasal_gc.h index 0607c6a..a76d21c 100644 --- a/nasal_gc.h +++ b/nasal_gc.h @@ -624,8 +624,8 @@ void nasal_gc::info() const char* name[]={"str ","func ","vec ","hash ","upval","obj ","co "}; std::cout<<"\ngarbage collector info\n"; for(uint8_t i=0;i imm; // immediate number - + /* main stack */ + nasal_ref stack[STACK_DEPTH]; /* garbage collector */ nasal_gc gc; @@ -125,9 +122,7 @@ protected: void opr_mcallh(); void opr_ret(); public: - nasal_vm(): - global(stack), - gc(pc,localr,memr,funcr,upvalr,canary,top,stack){} + nasal_vm():gc(pc,localr,memr,funcr,upvalr,canary,top,stack){} void run( const nasal_codegen&, const nasal_import&, @@ -152,7 +147,6 @@ void nasal_vm::init( /* set canary and program counter */ pc=0; - global=stack; localr=nullptr; memr=nullptr; funcr=nil; @@ -290,7 +284,7 @@ void nasal_vm::register_info() { printf("registers(%s):\n",gc.coroutine?"coroutine":"main"); printf(" [ pc ] | pc | 0x%x\n",pc); - printf(" [ global ] | addr | 0x" PRTHEX64 "\n",(uint64_t)global); + printf(" [ global ] | addr | 0x" PRTHEX64 "\n",(uint64_t)stack); printf(" [ localr ] | addr | 0x" PRTHEX64 "\n",(uint64_t)localr); printf(" [ memr ] | addr | 0x" PRTHEX64 "\n",(uint64_t)memr); if(funcr.type==vm_nil) @@ -312,11 +306,11 @@ void nasal_vm::global_state() { if(!bytecode[0].num || stack[0].type==vm_none) // bytecode[0].op is op_intg return; - printf("global(0x" PRTHEX64 "):\n",(uint64_t)global); + printf("global(0x" PRTHEX64 "):\n",(uint64_t)stack); for(uint32_t i=0;i code; for(auto& i:gen.get_code()) { - code.push_back(opr_table[i.op]); + code.push_back(oprs[i.op]); imm.push_back(i.num); } // goto the first operand @@ -1048,7 +1041,7 @@ vmexit: die("stack overflow"); if(opcnt) opcallsort(count); - if(detail_info) + if(detail) gc.info(); gc.clear(); imm.clear();