Lua5.3 VM 分析(二)表处理
来源:互联网 发布:网络春晚2016完整版 编辑:程序博客网 时间:2024/05/29 09:08
Lua5.3 VM 分析(二)表处理
luaV_gettable
luaV_gettable 函数实现了Table类型的读操作,可能触发元方法。
/* ** Main function for table access (invoking metamethods if needed). ** Compute 'val = t[key]' */voidluaV_gettable(lua_State *L, const TValue *t, TValue *key, StkId val){ int loop; /* counter to avoid infinite loops */ for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; if (ttistable(t)) { /* 't' is a table? */ Table *h = hvalue(t); const TValue *res = luaH_get(h, key); /* do a primitive get */ if (!ttisnil(res) || /* result is not nil? */ (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ setobj2s(L, val, res); /* result is the raw get */ return; } /* else will try metamethod */ } else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) luaG_typeerror(L, t, "index"); /* no metamethod */ if (ttisfunction(tm)) { /* metamethod is a function */ luaT_callTM(L, tm, t, key, val, 1); return; } t = tm; /* else repeat access over 'tm' */ } luaG_runerror(L, "gettable chain too long; possible loop");}
OP_GETTABUP、OP_GETTABLE、OP_SELF 这三种指令会调用 luaV_gettable 函数对表做读操作。
处理元表的深度最大为 MAXTAGLOOP (2000)层。越深的嵌套性能越低下。
当操作对象不可以按照 表的模式去索引时,利用luaG_typeerror 抛出异常,中断死循环执行。
如果元表中的index 并不对应一张表,而是一个 函数的时候,就会引发一次元方法调用。它由luaT_callTM 函数实现。
voidluaT_callTM(lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, TValue *p3, int hasres){ ptrdiff_t result = savestack(L, p3); setobj2s(L, L->top++, f); /* push function (assume EXTRA_STACK) */ setobj2s(L, L->top++, p1); /* 1st argument */ setobj2s(L, L->top++, p2); /* 2nd argument */ if (!hasres) /* no result? 'p3' is third argument */ setobj2s(L, L->top++, p3); /* 3rd argument */ /* metamethod may yield only when called from Lua code */ luaD_call(L, L->top - (4 - hasres), hasres, isLua(L->ci)); if (hasres) { /* if has result, move it to its place */ p3 = restorestack(L, result); setobjs2s(L, p3, --L->top); }}
callTM 的hasres 参数表示是否需要输出。有输出时,元方法只有两个输入参数(参数一 p1 和 参数二 p2),第三个参数 p3 作为输出。
所有的元方法都有三个参数:
1. 参数一一定是对象本身。 是输入值,只读。
2. 参数二则根据元方法的不同而不同。对于表操作,参数二为Key 值;而对于二元运算操作则是第二个参数的数值。是输入值,只读。
3. 参数三则可以是输入也可以是输出使用。
luaV_settable
luaV_settable 函数实现了Table 类型的写操作,可能触发元方法。
/* ** Main function for table assignment (invoking metamethods if needed). ** Compute 't[key] = val' */voidluaV_settable(lua_State *L, const TValue *t, TValue *key, StkId val){ int loop; /* counter to avoid infinite loops */ for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; if (ttistable(t)) { /* 't' is a table? */ Table *h = hvalue(t); TValue *oldval = cast(TValue *, luaH_get(h, key)); /* if previous value is not nil, there must be a previous entry in the table; a metamethod has no relevance */ if (!ttisnil(oldval) || /* previous value is nil; must check the metamethod */ ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL && /* no metamethod; is there a previous entry in the table? */ (oldval != luaO_nilobject || /* no previous entry; must create one. (The next test is always true; we only need the assignment.) */ (oldval = luaH_newkey(L, h, key), 1)))) { /* no metamethod and (now) there is an entry with given key */ setobj2t(L, oldval, val); /* assign new value to that entry */ invalidateTMcache(h); luaC_barrierback(L, h, val); return; } /* else will try the metamethod */ } else /* not a table; check metamethod */ if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) luaG_typeerror(L, t, "index"); /* try the metamethod */ if (ttisfunction(tm)) { luaT_callTM(L, tm, t, key, val, 0); return; } t = tm; /* else repeat assignment over 'tm' */ } luaG_runerror(L, "settable chain too long; possible loop");}
OP_SETTABUP、OP_SETTABLE 这两种指令会调用luaV_settable 函数对表做写操作。
由于Lua 表的删除操作使用 对应 键值设置为nil来实现,所以这里有可能会导致Lua 内其它对象的生命期变化,这涉及到了 GC 的工作。
invalidateTMcache(h);
luaC_barrierback(L, h, val);
阅读全文
0 0
- Lua5.3 VM 分析(二)表处理
- Lua5.3 VM 分析(一)字节码运行
- Lua5.3 VM 分析(三)表达式运算
- Lua5.3 VM 分析(四)分支和跳转
- Lua5.3 VM 分析(七)生成闭包
- Lua5.3 VM 分析(八)For 循环
- Lua5.3 虚拟机指令分析(二)赋值指令
- Lua5.3 虚拟机指令分析(十)表相关指令
- Lua基础语法学习(二)+Lua5.3参考手册
- Lua5.3 虚拟机指令分析(一)概述
- Lua5.3 虚拟机指令分析(三)表达式运算
- Lua5.3 虚拟机指令分析(四)分支与跳转
- Lua5.3 虚拟机指令分析(五)函数调用
- Lua5.3 虚拟机指令分析(六)不定参数
- Lua5.3 虚拟机指令分析(八)循环
- lua5.3与C++交互学习(二)
- lua5.1学习笔记(二)
- Lua5.1代码阅读(二):llex.h/llex.c
- Could not create the view: An unexpected exception was thrown.
- CSS样式的基础知识
- yii2项目实战-了解一下基于角色的访问控制
- Lua5.3 VM 分析(一)字节码运行
- JVM内存分配以及存储总结
- Lua5.3 VM 分析(二)表处理
- RCNN, Fast-RCNN, Faster-RCNN
- 《算法导论》第五章-第4节_练习(参考答案)
- 打扫房间的各种方法 —— Java虚拟机的垃圾收集算法清单
- 1037. 在霍格沃茨找零钱(20)
- 如何更好的做计划-SMART原则
- Lua5.3 VM 分析(三)表达式运算
- 【数学基础】【欧拉函数解析模板】【欧拉筛法实现求1~n】【求单个n】
- Lua5.3 VM 分析(四)分支和跳转