Lua一直把虚拟机执行代码的效率作为一个非常重要的设计目标。而采用什么样的指令系统的对于虚拟机的执行效率来说至关重要。

Stack based vs Register based VM

根据指令获取操作数方式的不同,我们可以把虚拟机的实现分为stack based和register based。

Stack based vm

对于大多数的虚拟机,比如JVM,Python,都采用传统的stack based vm。

Stack based vm的指令一般都是在当前stack中获取和保存操作数的。比如一个简单的加法赋值运算:a=b+c,对于stack based vm,一般会被转化成如下的指令:

由于Stack based vm的指令都是基于当前stack来查找操作数的,这就相当于所有操作数的存储位置都是运行期决定的,在编译器的代码生成阶段不需要额外为在哪里存储操作数费心,所以stack based的编译器实现起来相对比较简单直接。也正因为这个原因,每条指令占用的存储空间也比较小。

但是,对于一个简单的运算,stack based vm会使用过多的指令组合来完成,这样就增加了整体指令集合的长度。vm会使用同样多的迭代次数来执行这些指令,这对于效率来说会有很大的影响。并且,由于操作数都要放到stack上面,使得移动这些操作数的内存复制大大增加,这也会影响到效率。

Register based vm

Lua 采用的是register based vm。

Register based vm的指令都是在已经分配好的寄存器中存取操作数。对于上面的运算,register based vm一般会使用如下的指令:

Register based vm的指令可以直接对应标准的3地址指令,用一条指令完成了上面多条指令的计算工作,并且有效地减少了内存复制操作。这样的指令系统对于效率有很大的帮助。

不过,在编译器设计上,就要在代码生成阶段对寄存器进行分配,增加了实现的复杂度。并且每条指令所占用的存储空间也相应的增加了。

Lua虚拟机指令简介

Lua的指令使用一个32bit的unsigned integer表示。所有指令的定义都在lopcodes.h文件中,使用一个enum OpCode代表指令类型。在lua5.2中,总共有40种指令(id从0到39)。根据指令参数的不同,可以将所有指令分为4类:

除了sBx之外,所有的指令参数都是unsigned integer类型。sBx可以表示负数,但表示方法比较特殊。sBx的18bit可表示的最大整数为262143,这个数的一半131071用来表示0,所以-1可以表示为-1+131071,也就是131070,而+1可以表示为+1+131071,也就是131072。

ABC一般用来存放指令操作数据的地址,而地址可以分成3种:

  • 寄存器id
  • 常量表id
  • upvalue id
Lua使用当前函数的stack作为寄存器使用,寄存器id从0开始。当前函数的stack与寄存器数组是相同的概念。stack(n)其实就是register(n)。

每一个函数prototype都有一个属于本函数的常量表,用于存放编译过程中函数所用到的常量。常量表可以存放nil,boolean,number和string类型的数据,id从1开始。

每一个函数prototype中都有一个upvalue描述表,用于存放在编译过程中确定的本函数所使用的upvalue的描述。在运行期,通过OP_CLOSURE指令创建一个closure时,会根据prototype中的描述,为这个closure初始化upvalue表。upvalue本身不需要使用名称,而是通过id进行访问。

A被大多数指令用来指定计算结果的目标寄存器地址。很多指令使用B或C同时存放寄存器地址和常量地址,并通过最左面的一个bit来区分。在指令生成阶段,如果B或C需要引用的常量地址超出了表示范围,则首先会生成指令将常量装载到临时寄存器,然后再将B或C改为使用该寄存器地址。

在lopcodes.h中,对于每个指令,在源码注释中都有简单的操作描述。本文接下来将针对每一个指令做更详细的描述,并给出关于这个指令的示例代码。示例代码可以帮助我们构建出一个指令使用的具体上下文,有助于进一步理解指令的作用。对指令上下文的理解还可以作为进一步研究lua的编译和代码生成系统的基础。

在分析过程中,我们使用luac来显示示例代码所生成的指令。luac的具体使用方式为:

luac -l -l test.lua

  

 

【转】: 探索Lua5.2内部实现:虚拟机指令(1) 概述的更多相关文章

  1. 【转】: 探索Lua5.2内部实现:虚拟机指令(2) MOVE & LOAD

    name args desc OP_MOVE A B R(A) := R(B) OP_MOVE用来将寄存器B中的值拷贝到寄存器A中.由于Lua是register based vm,大部分的指令都是直接 ...

  2. 【转】: 探索Lua5.2内部实现:虚拟机指令(3) Upvalues & Globals

    在编译期,如果要访问变量a时,会依照以下的顺序决定变量a的类型: a是当前函数的local变量 a是外层函数的local变量,那么a是当前函数的upvalue a是全局变量 local变量本身就存在于 ...

  3. JAVA安装过程中出现的“javac不是内部或外部指令”的解决方法

    近来重新安装了JAVA,安装过程中出现问题,网上找到解决办法,汇总发布. 解决流程: 1.确定自己的环境变量设置没问题,没有出现遗漏 : . 等情况 (具体环境变量设置百度) 2.环境变量设置后 ,d ...

  4. Javac不是内部或外部指令

    JDK安装完,命令行窗口中运行Java正常,运行Javac显示不是内部或外部指令 不存在百度上说的没有安装JDK,只安装了JRE 我的电脑是64位Win7操作系统 第一次安装的JDK不是从官网下载的, ...

  5. 从虚拟机指令执行的角度分析JAVA中多态的实现原理

    从虚拟机指令执行的角度分析JAVA中多态的实现原理 前几天突然被一个"家伙"问了几个问题,其中一个是:JAVA中的多态的实现原理是什么? 我一想,这肯定不是从语法的角度来阐释多态吧 ...

  6. Atitit .jvm 虚拟机指令详细解释

    Atitit .jvm 虚拟机指令详细解释 1. 一.未归类系列A1 2. 数据mov系列2 2.1. 二.const系列2 2.2. 三.push系列2 2.3. ldc系列 该系列命令负责把数值常 ...

  7. Java SE7虚拟机指令操作码助记符

    本文转载自Java SE7 虚拟机指令操作码助记符 导语 在Class文件中,Java方法里的方法体,也就是代表着一个Java源码程序中程序的部分存储在方法表集合的Code属性中.存储在Code属性中 ...

  8. JVM 内部原理(一)— 概述

    JVM 内部原理(一)- 概述 介绍 版本:Java SE 7 图中显示组件将会从两个方面分别解释.第一部分涵盖线程独有的组件,第二部分涵盖独立于线程的组件(即线程共享组件). 目录 线程独享(Thr ...

  9. 深入探索.NET框架内部了解CLR如何创建运行时对象

    原文地址:http://msdn.microsoft.com/en-us/magazine/cc163791.aspx 原文发布日期: 9/19/2005 原文已经被 Microsoft 删除了,收集 ...

随机推荐

  1. HIDU 2094

    传送门: http://acm.hdu.edu.cn/showproblem.php?pid=2094 产生冠军 Time Limit: 1000/1000 MS (Java/Others)    M ...

  2. DML-删除

    方式一:使用delete一.删除单表的记录★语法:delete from 表名 [where 筛选条件][limit 条目数]二.级联删除[补充]语法:delete 别名1,别名2 from 表1 别 ...

  3. oracle cascade用法

    原文地址:https://www.cnblogs.com/moyijian/p/9940323.html#4111551 级联删除,比如你删除某个表的时候后面加这个关键字,会在删除这个表的同时删除和该 ...

  4. mongodb3.4.0复制集的搭建

    本次主要介绍一下我们项目中关于mongodb复制集的搭建过程. 部署三台mongodb,分别是在69,70,71上面.71上面是主节点,69和70是从节点.使用mongodb3.4.0版本. 先看一安 ...

  5. 09 OCP知识点讲解 之 LRU链与脏LRU链

    OCP知识点讲解 之 LRU链与脏LRU链 分类: Oracle 2012-06-30 10:49:26   一.LRU链: 任何缓存的大小都是有限制的,并且总不如被缓存的数据多.就像Buffer c ...

  6. 用VMWare搭建服务器集群不能上外网的三种模式下对应解决办法

    前言 决心要花费宝贵时间写下这篇心得,是因为从昨天晚上到今天上午被这个VMWare模拟搭建的服务器集群不能上外网的问题搞得很心烦,最后决定跟它杠上了!上午还通过远程连接得到了“空白”同学的帮助,在此表 ...

  7. angular.js-1初识

    初识AngularJS AngularJS 为了克服HTML在构建页面上的不足,通过新的属性和表达式扩展了 HTML(AngularJS 通过指令扩展了 HTML,且通过表达式绑定数据到 HTML). ...

  8. 关于如何去Apple.cn下载Xcode以及模拟器包

    前言:对于一个懒惰的iOS开发,Xcode的更新我是迟迟没有去下载.有人或许会说:你并不是一个合格的iOS开发者! T3T 我承认自己缺少拓新精神,Apple的尿性是:坑死第一批体验者不偿命~表示本人 ...

  9. restframework中的那些参数你知道吗?

    序列化是很重要的过程, 在构建数据结构的时候, 往往会出现很多意想不到的问题, 有一些参数你要用, 但是没有办法穿过来, 怎么办> 今天这篇博客就是写我之前的一个小项目中用restframewo ...

  10. 【Spark】源码分析之RDD的生成及stage的切分

    一.概述 Spark源码整体的逻辑(spark1.3.1): 从saveAsTextFile()方法入手 -->saveAsTextFile()  --> saveAsHadoopFile ...