lua栈
既然Lua虚拟机模拟的是CPU的运作,那么Lua栈模拟的就是内存的角色.在Lua内部,参数的传递是通过Lua栈,同时Lua与C等外部进行交互的时候也是使用的栈.,先关注的是Lua栈的分配,管理和相关的数据结构.
lua虚拟机在初始化创建lua_State结构体时,会走到stack_init函数中,这个函数主要就是对Lua栈和CallInfo数组的初始化:
static void stack_init (lua_State *L1, lua_State *L) {
/* initialize CallInfo array */
L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo);
L1->ci = L1->base_ci;
L1->size_ci = BASIC_CI_SIZE;
L1->end_ci = L1->base_ci + L1->size_ci - 1;
/* initialize stack array */
L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue);
L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK;
L1->top = L1->stack;
L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1;
/* initialize first ci */
L1->ci->func = L1->top;
setnilvalue(L1->top++); /* `function' entry for this `ci' */
L1->base = L1->ci->base = L1->top;
L1->ci->top = L1->top + LUA_MINSTACK;
}
可以看到的是,初始化了两个数组,分别保存Lua栈和CallInfo结构体数组.
其中,与Lua栈相关的lua_State结构体成员变量有base,stack,top,lastfree,stack保存的是数组的初始位置,base会根据每次函数调用的情况发生变化,top指针指向的是当前第一个可用的栈位置,每次向栈中增加/删减元素都要对应的增减top指针,lastfee指针指向的书Lua栈的最后位置.
CallInfo结构体,是每次有函数调用时都会去初始化的一个结构体,它的成员变量中,也有top,base指针,同样的是指向Lua栈的位置,所不同的是,它关注的仅是函数调用时的相关位置.从代码中可以看出,CallInfo数组是有限制的,换言之,在Lua中的嵌套函数调用层次也是有限制,不能超过一定数量.

首先看f_parser函数:
static void f_parser (lua_State *L, void *ud) {
int i;
Proto *tf;
Closure *cl;
struct SParser *p = cast(struct SParser *, ud);
int c = luaZ_lookahead(p->z);
luaC_checkGC(L);
tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z,
&p->buff, p->name);
cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L)));
cl->l.p = tf;
for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */
cl->l.upvals[i] = luaF_newupval(L);
setclvalue(L, L->top, cl);
incr_top(L);
}
f_parser函数的最后两句,将分析完毕之后的结构Closure指针压入了Lua栈.
再来看luaD_precall函数,这里为将代码放入Lua虚拟机中执行准备了相关数据,我们只截取其中的一部分来看:
int luaD_precall (lua_State *L, StkId func, int nresults) {
….
if (!cl->isC) { /* Lua function? prepare its call */
CallInfo *ci;
StkId st, base;
Proto *p = cl->p;
// 1) 根据函数的参数类型,计算出该CallInfo的base指针位置
if (!p->is_vararg) { /* no varargs? */
base = func + 1;
if (L->top > base + p->numparams)
L->top = base + p->numparams;
}
else { /* vararg function */
int nargs = cast_int(L->top - func) - 1;
base = adjust_varargs(L, p, nargs);
func = restorestack(L, funcr); /* previous call may change the stack */
}
// 2) 分配一个新的CallInfo结构体,用于保存此次函数调用的相关信息:top,base指针,func函数
ci = inc_ci(L); /* now `enter' new function */
ci->func = func;
L->base = ci->base = base;
ci->top = L->base + p->maxstacksize;
lua_assert(ci->top <= L->stack_last);
// 3) LuaState的PC指针指向函数原型的代码数组
L->savedpc = p->code; /* starting point */
// …..
return PCRLUA;
}
到这一步,跟某次具体的Lua代码执行相关的代码(保存在Proto的code数组中)和执行时所需环境(Lua栈),就已经准备完毕了.后面就是进入Lua虚拟机的主循环中解释执行代码了.
lua栈的更多相关文章
- 通过lua栈了解lua与c的交互
lua是如何执行的 其中分析.执行部分都是c语言实现的. lua与c的关系 lua的虚拟机是用c语言实现的,换句话说一段lua指令最终在执行时都是当作c语言来执行的,lua的global表,函数调用栈 ...
- lua和C++交互的lua栈操作——以LuaTinker为例
一. -- C++类注册函数(LuaTinker) 的lua栈操作: -- lua栈内容(执行到pop语句) 栈地址 <--执行语句 space_name[name] = t1 -- (2b8) ...
- Lua 栈的理解
提到C++与lua互调,不可不提栈. 栈是C++和Lua相互通讯的一个地方. 首先这个栈并不是传统意义上的栈(传统的栈需要放同一种数据类型,但在网上的某些资料说,每个栈元素是一个联合体). 栈从上向下 ...
- Lua 栈中元素的位置
Lua与C.C#等的交互是通过栈来实现的,每次插入元素都是放在栈顶(top),至于元素的index,可以使用正数和负数两种方式, 如取栈底开始至第index个元素 -index = gettop - ...
- c调用 lua 栈操作
转自https://www.cnblogs.com/ringofthec/archive/2010/10/22/lua.html 打算记录一些lua_api, 可能会觉得lua文档中已经说的很清楚了, ...
- lua 栈最后调用的函数,用于看调试信息
lua_getinfo int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); 返回一个指定的函数或函数调用的信息. 当用于取 ...
- Lua的栈及基本栈操作
Lua的栈及基本栈操作 https://blog.csdn.net/mydriverc2/article/details/51134737 https://blog.csdn.net/mydriver ...
- lua解释执行脚本流程
#include "lua.hpp" #include <iostream> using namespace std; #pragma comment(lib, &qu ...
- Lua和C++交互详细总结
转自:http://cn.cocos2d-x.org/tutorial/show?id=1474 一.Lua堆栈 要理解Lua和C++交互,首先要理解Lua堆栈. 简单来说,Lua和C/C++语言通信 ...
随机推荐
- 寒假短期学习计划 - C++
寒假短期学习计划 - C++ 一.所选课程 && 相关 0.选以下课的理由: 选课理由0: 只是短期的计划,先选些短视频感受:之后再视情况选其他课: 选课理由1: 难度低,以前自学过一 ...
- Echarts使用小结
还是先来简单的了解一下Echart是什么吧? ECharts,缩写来自Enterprise Charts,商业级数据图表,一个纯Javascript的图表库,可以流畅的运行在PC和移动设备上,兼容当前 ...
- ascii2native 转码 解码
//把十六进制的编码转为原码function asciiHex2native(strAscii) { var output = ""; var posFrom = 0; var p ...
- springmvc细节篇
前面讲了入门篇,现在来了解下springmvc的细节.mvc框架都有请求映射.数据绑定.请求处理.视图解析这几个过程,现在我们来了解springmvc中的这些细节. 1.使用@RequestMappi ...
- mac下用xattr命令来删除文件的扩展属性
mac下发现不能用记事本打开文本文件,ls -la 发现格式后面有个@ wenke-mini:changeServer wenke$ ls -la total 144 drwxr-xr-x 20 w ...
- ucos串口通讯模块设计
在嵌入式应用中,使用RTOS的主要原因是为了提高系统的可靠性,其次是提高开发效率.缩短开发周期.uCOS-II是一个占先式实时多任务内核,使用对象是嵌入式系统,对源代码适当裁减,很容易移植到8~32位 ...
- Mysql 安全登陆工具 mysql_config_editor
mysql_config_editor 帮助信息请查看 man mysql_config_editor 或 mysql_config_editor -? 或 mysql_config_editor s ...
- Linux基础命令之文件和目录操作(二)
. find 用于查找目录下的文件,也可以调用其他命令使用 find [-H] [-L] [-P] [-D debugopts] [-Olevel] [path...] [expression] fi ...
- Mac开发中遇到的一些小问题解析
通过mac开发的过程中,有一些小问题出现,列如下,后续会持续增加: 1. 命令行清空废纸篓(jar包太多,倾倒废纸篓太慢) sudo rm -rfv ~/.Trash /Volumes/*/.Tras ...
- iview的Affix插件遇到滚动时候的bug处理方法
最近有个需求,是用vue做的页面,其中嵌入了一个tinymce编辑器,编辑器设置了自动调整高度,也就是说编辑器中内容越多,高度就会自动撑高 我们需要再页面最下方放一个保存按钮,保存按钮必须固定在屏幕下 ...