lua虚拟机概述
何为虚拟机
用于模拟计算机运行的程序.是个中间层,它处于脚本语言和硬件之间的一个程序.每一门脚本语言都会有自己定义的opcode(”操作码”),可以理解为这门程序自己定义的”汇编语言”.一般的编译型语言,比如C等,经过编译器编译之后生成的都是与当前硬件环境相匹配的汇编代码;而脚本型的语言,经过前端的处理之后,生成的就是opcode,再将该opcode放在这门语言的虚拟机中执行.虚拟机是作为单独的程序独立存在,而Lua由于是一门嵌入式的语言是附着在宿主环境中的.
lua代码到虚拟机执行的流程
在Lua中,Lua代码从词法分析到语法分析再到生成opcode,最后进入虚拟机执行的大体流程是什么样子的呢?
Lua的API中提供了luaL_dofile函数,它实际上是个宏,内部首先调用luaL_loadfile函数,加载Lua代码进行语法,词法分析,生成Lua虚拟机可执行的代码,再调用lua_pcall函数,执行其中的代码:
#define luaL_dofile(L, fn) \
(luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0))
前半部分调用luaL_loadfile函数对Lua代码进行词法和语法分析,后半部分调用lua_pcall将第一步中分析的结果(也就是opcode)到虚拟机中执行.
首先来看luaL_loadfile函数,暂时不深入其中研究它如何分析一个Lua代码文件,先看它最后输出了什么.它最终会调用f_parser函数,这是对一个Lua代码进行分析的入口函数:
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);
}
在完成词法分析之后,返回了Proto类型的指针tf,然后将其绑定在新创建的Closure指针上,初始化UpValue,最后压入Lua栈中.
不难想像,Lua词法分析之后产生的opcode等相关数据都在这个Proto类型的结构体中.
再来看lua_pcall函数是如何将产生的opcode放入虚拟机执行的.
lua_pcall函数中,首先获取需要调用的函数指针:
c.func = L->top - (nargs+1); /* function to be called */
这里的nargs是由函数参数传入的,luaL_dofile中调用lua_pcall时这里传入的参数是0,换句话说,这里得到的函数对象指针就是在f_parser函数中最后放入Lua栈的指针.
继续往下执行,走到luaD_call函数,有这一段代码:
if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */
luaV_execute(L, 1); /* call it */
进入luaV_execute函数,这里是虚拟机执行代码的主函数:
void luaV_execute (lua_State *L, int nexeccalls) {
LClosure *cl;
StkId base;
TValue *k;
const Instruction *pc;
reentry: /* entry point */
lua_assert(isLua(L->ci));
pc = L->savedpc;
cl = &clvalue(L->ci->func)->l;
base = L->base;
k = cl->p->k;
/* main loop of interpreter */
for (;;) {
const Instruction i = *pc++;
StkId ra;
if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) &&
(--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) {
traceexec(L, pc);
if (L->status == LUA_YIELD) { /* did hook yield? */
L->savedpc = pc - 1;
return;
}
base = L->base;
}
/* warning!! several calls may realloc the stack and invalidate `ra' */
ra = RA(i);
// 以下是各种opcode的情况处理
}
可以看到,这里的pc指针里存放的是虚拟机opcode代码,它最开始从L->savepc初始化而来,而L->savepc在luaD_precall中赋值:
L->savedpc = p->code; /* starting point */
这里的p就是第一步f_parser中返回的Proto指针.
回顾一下整个流程:
函数f_parser中,对Lua代码文件的分析返回了Proto指针
函数luaD_precall中,将Lua_state的savepc指针指向1中的Proto结构体的code指针
函数luaV_execute中,pc指针指向2中的savepc指针,紧跟着就是一个大的循环体,依次取出其中的opcode进行执行.
lua虚拟机概述的更多相关文章
- 深入浅出Lua虚拟机
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 作者:郑小辉 | 腾讯 游戏客户端开发高级工程师 写在前面:本文所有的文字都是我手工一个一个敲的,以及本文后面分享的Demo代码都是我一行一 ...
- 大佬带你深入浅出Lua虚拟机
欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由鹅厂优文发表于云+社区专栏 作者:郑小辉 | 腾讯 游戏客户端开发高级工程师 写在前面:本文所有的文字都是我手工一个一个敲的,以及本文 ...
- Lua虚拟机初始化
转自:http://www.cnblogs.com/ringofthec/archive/2010/11/09/lua_State.html 1. 创建lua虚拟机 lua_State *lua_ne ...
- Lua虚拟机中的数据结构与栈
Lua虚拟机中的数据结构与栈 来源 https://blog.csdn.net/zry112233/article/details/80828327 由上一篇文章可知解释器分析Lua文件之后生成Pro ...
- Azure 中的 Windows 虚拟机概述
Azure 虚拟机 (VM) 是 Azure 提供的多种可缩放按需分配计算资源之一. 通常情况下,如果需要以更大的力度(相对于其他控制选项)控制计算环境,则应选择 VM. 本文介绍创建 VM 之前的注 ...
- java虚拟机概述
java 虚拟机是什么? java虚拟机是一个将字节码指令映射为对应物理操作系统指令的程序. java程序的运行需要事先安装 jdk,而在jdk内部的jre中其核心就是 jvm ...
- Java 虚拟机概述
虚拟机是一种抽象化的计算机,通过在实际的计算机上仿真模拟各种计算机功能来实现的.Java虚拟机有自己完善的硬体架构,如处理器.堆栈.寄存器等,还具有相应的指令系统.Java虚拟机屏蔽了与具体操作系统平 ...
- 《Android虚拟机》----虚拟机概述
No1: 虚拟机是指通过软件模拟的具有完整硬件系统功能的.运行在一个完全隔离的环境中的完整计算机系统. No2: Java虚拟机由如下五个部分组成:一组指令集.一组寄存器.一个栈.一个无用单元收集堆. ...
- 【转】: 探索Lua5.2内部实现:虚拟机指令(1) 概述
Lua一直把虚拟机执行代码的效率作为一个非常重要的设计目标.而采用什么样的指令系统的对于虚拟机的执行效率来说至关重要. Stack based vs Register based VM 根据指令获取操 ...
随机推荐
- mysql的日期函数介绍
仅供参考 DAYOFWEEK(date) 返回日期date是星期几(1=星期天,2=星期一,……7=星期六,ODBC标准)mysql> select DAYOFWEEK('1998-02-03 ...
- 用tableView实现的一种加载数据的布局
用tableView实现的一种加载数据的布局 此博文是应朋友之邀解决他的业务逻辑问题 效果: 素材: 源码: ImageCell.h 与 ImageCell.m // // ImageCell.h / ...
- UITableVIew与UICollectionView带动画删除cell时崩溃的处理
UITableVIew与UICollectionView带动画删除cell时崩溃的处理 -会崩溃的原因是因为没有处理好数据源与cell之间的协调关系- 效果: tableView的源码: ModelC ...
- [C++] 用Xcode来写C++程序[3] Constants
用Xcode来写C++程序[3] Constants 以下是一些基本数据的含义: 75 // int 75u // unsigned int 75l // long 75ul // unsigned ...
- Linux ip命令详解
ip命令式用来配置网卡ip信息的命令,且是未来的趋势,重启网卡后IP失效 ip常见命令参数 Usage: ip [ OPTIONS ] OBJECT { COMMAND | help } ip [ - ...
- python常见释疑(有别于报错)(不定时更新)
文:铁乐与猫 01.在cmd运行py脚本后,直接回到了提示符,没有任何输出,看起来像是并没有运行一样. 答:你的感觉很可能是对的,但脚本很可能己经正常运行,只是你的代码里面很可能没有给出print提示 ...
- MongoDB 多实例安装成服务
转发自:https://www.cnblogs.com/GainLoss/p/6906937.html 1.在mongodb的官网上下载安装包 https://www.mongodb.com/down ...
- 021.13 IO流 RandomAccessFile对象
对象和方法:RandomAccessFile:文件操作对象,Java提供getFilePointer:获取文件指针 特点:1.只能操作文件2.既能读,又能写3.里面维护了一个数组,内部定义了字符的读和 ...
- 解密虚拟 DOM——snabbdom 核心源码解读
本文源码地址:https://github.com/zhongdeming428/snabbdom 对很多人而言,虚拟 DOM 都是一个很高大上而且远不可及的专有名词,以前我也这么认为,后来在学习 V ...
- 一个简单的统计问题(解决方案:Trie树)
题目如图 输入几个不重复的单词和几个前缀,分别统计出单词中包含前缀的个数. Trie树 这个题目用到了 Trie 树.它在百度百科中的定义如下:在计算机科学中,Trie,又称字典树.单词查找树 ...