Lua 4.0 学习 (八) for语句和新的指令格式
Lua 4.0 学习 (八) for语句和新的指令格式
刘军兴 发表于4年前
Lua 4.0 学习 (八) for语句和新的指令格式
  • 发表于 4年前
  • 阅读 117
  • 收藏 2
  • 点赞 0
  • 评论 0

Lua 4.0 比起 3.2, 3.1 有了一些改进, 见 HISTORY 文件. 下面对几个关心的摘要:

1. 新的 break 和 for 语句.
语法参考: http://wenku.baidu.com/view/159bc8aad1f34693daef3e70.html
for i = 1, 10, 2 do
  print ('i is: ' .. i)
  if i >= 7 then break end
end

for 语句的产生式简单易懂, 两种形式如下(为容易理解略有改动):
  for语句 -> fornum | forlist
  fornum -> FOR var1 = exp1, exp2[,exp3] DO block END
  forlist -> FOR var1,var2 IN exp1 DO block END

为支持 for 的数字形式的实现, 引入了两种新的指令: OP_FORPREP, OP_FORLOOP.
一般的编译结果为(伪代码形式):

  PUSH var1; PUSH $limit; PUSH $step  -- 局部循环变量值入栈
  OP_FORPREP end_label
begin_label:
  block -- for 内部的代码块
  OP_FORLOOP begin_label
end_label:
  后续代码块.

指令 OP_FORPREP end_label:
  从栈中得到循环变量 var1, $limit, $step
  比较: 如果 var1 > $limit 则 (注1)
    从栈中移除 var1, $limit, $step 循环控制变量 (top -= 3)
 跳转到 end_label
  否则执行下一个指令, 也即循环体.
(注1: 如果 $step 为负数, 则比较 var1 < $limit. 不影响我们语义理解的略去.)
 
指令 OP_FORLOOP begin_label:
  从栈中得到循环变量 var1, $limit, $step (并简单验证)
  var1 += $step 增加循环变量值
  如果 var1 > $limit 则
    从栈中移除 var1, $limit, $step 循环控制变量
 执行下一个代码, 即出了循环体.
  否则
    跳转到 begin_label 处执行, 即执行循环体.

根据上述描述, Lua 虚拟机使用了相比硬件指令而言, 更高级的虚拟指令
来支持实现 for 语句.

对 forlist 形式的支持有相似性, 也是使用了两种新的指令帮助实现,
OP_LFORPREP 和 OP_LFORLOOP, 因其实现原理的相似性, 即略去不详述了.


2. uniform treatment of globals: globals are now stored in a Lua table.
  全局变量放到 lua table 中访问了.

早期的版本, 访问全局变量的指令如 PUSH/GETGLOBAL i, 其指令数 i 指的是该全局
变量在表格 global_vars[] 中的索引(表格名字可能有变化, 示意用); 再后的版本
可能有所调整, 未曾细研究; 则在新的 4.0 版本中, i 首先索引到当前函数字符串
常量表 kstr[] 得到一个字符串, 该字符串为全局变量的名字. 然后通过该名字在
当前 lua 线程(lua_State) 的全局变量表 gt 中查找, 这个表实现为一个 hash 表.

使用整数索引 i 直接访问全局变量表, 肯定比字符串 s 访问 hash 表快多了. 使用
字符串名字 s 引用全局变量, 有更好的灵活性, 或 uniform 就是优点. 考虑到现在
CPU 如此之快, 内存如此之多, 就是多用了一点对于脚本语言来说, 应不是什么问题.
我想这样可以自己说服自己, 以不至于纠结在对性能的不必要的完美追求上了.

3. cleaner virtual machine -- at least 20% faster.

Lua 4.0 的虚拟机指令格式有了大的变化. 原 3.1 及以下版本使用字节码, 每个
指令一个字节, 有的指令带一个字节或两个字节的操作数. 新 4.0 版本使用 ulong
做指令单位 (Instruction), 每个指令(至少) 32 比特. 操作码 OP 使用 6 个 bits
(即最多 64 种指令), 剩余 26 bits 按照指令, 可被当做一个 26 bits 的操作数,
或当做两个分别是 9 bits, 17 bits 的操作数.

这种形式的指令有点像 RISC 体系的 CPU 所使用的指令. 而原字节码就是像 Intel
体系的 CPU 使用的. 按 lua 所称速度提升了 20%, 没有对自己程序在实际的机器
环境上实测, 则实在不能凭空想说哪种更好.


4. non-recursive garbage-collector algorithm.
  非递归的垃圾收集算法. (以后有时间专门研究垃圾回收再看)

 

 

 

共有 人打赏支持
粉丝 55
博文 141
码字总数 220645
×
刘军兴
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: