没想到Lua的作者理论水平这么高,这篇文章读的我顿生高屋建瓴之感。云风分享了一篇中译:http://www.codingnow.com/2000/download/The%20Implementation%20of%20Lua5.0.pdf

全篇的主题有4个:1.基于寄存器的虚拟机;2.用于将table作为数组使用的新算法;3.闭包的实现;4.以及协程。第二点我关注不多,会写的比较简略。

1 简介

简介主要就是说,我们搞Lua嘛,就是一个实验室出来的产品,没想到今天在工业界特别是游戏界红得发紫,这主要是得益于Lua轻灵小巧,注重可移植性。除了上面提到的4点,这篇文章还有一些铺垫的章节,帮助你们理解我们这个牛逼哄哄的东西。(这些铺垫的东东也很牛逼,建议参考中译)

2 Lua的设计和实现

我们写的Lua简洁,高效,可移植,非常容易嵌入。

3 Lua的类型系统

这段看代码比较简洁:

typedef struct {
int t;
Value v;
} TObject; typedef union {
GCObject *gc;
void *p;
lua_Number n;
int b;
} Value;

作者顺便扯了一下对象的装箱拆箱,嘲笑python的实现比Lua要慢。

4 Lua的Table

牛逼的地方在于,如果table是当array用,数字的key比较紧凑,我们就会拿一个真实的数组去储存它,即省空间又快速,如果是当成单纯的关联组来用,那么数组部分则不会分配,避免浪费

5 函数和闭包的实现

闭包在lua里应用得非常广泛。每一个函数都会被编译成一个prototype作为原型。实际执行的时候,则会为其生成一个闭包,包含了对函数原型的引用,对全局变量的引用表,以及对upvalue的引用(用来访问外部的局部变量)。

以函数为第一类对象,以及带词法作用域的语言,大多会遇到外部局部变量访问的问题。考虑下面的例子:

function add(x)
return function(y)
return x + y
end
end add2 = add()
print(add2())

当调用add2的时候,add函数已经返回,那么add2函数体内的x会不会随着add函数的退栈而被销毁呢?如果不被销毁,又应该如何保存这个变量呢?

Lua巧妙的使用了upvalue解决这一问题,参考下图:

每当创建一个新闭包,Lua就会检查外部定义的局部变量是否有加入upvalue链表,如果没有就创建一个upvalue加入双向链表里。所有对外部定义的局部变量访问,都是通过upvalue的指针进行间接访问的。当外部函数退出时,因为函数退栈,局部变量被清理,这时候局部变量就会被转存在upvalue的值域里,然后把upvalue的指针指向自身的值域。对于定义局部变量的函数,这些局部变量还是栈上的元素,不许通过upvalue访问。

对于多层函数嵌套的情况,当一个函数需要访问的变量不在上一层函数的局部变量,就访问上一层函数的闭包。闭包具有传递性,会由外部函数传递到内部。

下篇:The implementation of Lua 5.0 阅读笔记(二)

The Implementation of Lua 5.0 阅读笔记(一)的更多相关文章

  1. The implementation of Lua 5.0 阅读笔记(二)

    6 线程和协程 读完这篇文章我才意识到python的协程到底缺了什么,这个就是coroutine和semi-coroutine的区别了.区别就是,semi-coroutine只能返回(yield)到调 ...

  2. skynet1.0阅读笔记2_skynet的消息投递skynet.call

    为了了解 skynet.call 的调用过程,需要先看看 skynet的队列是如何把包分到不同工作线程的.看下图 查看 global_queue 的skynet_globalmq_push和skyne ...

  3. skynet1.0阅读笔记_skynet的启动

    首先看skynet的启动,函数入口在 skynet_main.c 的main(),其中最重要的是: skynet_start(&config); 在skynet_start中做了两个启动: / ...

  4. Effective objective-c 2.0阅读笔记

    这本书非常的好,看完后,感触挺深,总结纪录一下,针对ios开发的备忘: 注:分类和原著有些不同,自己总结学习用的,仅供参考.   系统篇: 了解oc起源:继承c,由Smalltalk演化而来.动态语言 ...

  5. 《C# 6.0 本质论》 阅读笔记

    <C# 6.0 本质论> 阅读笔记   阅读笔记不是讲述这本书的内容,只是提取了其中一部分我认为比较重要或者还没有掌握的知识,所以如果有错误或者模糊之处,请指正,谢谢! 对于C# 6.0才 ...

  6. Linux 0.11源码阅读笔记-文件管理

    Linux 0.11源码阅读笔记-文件管理 文件系统 生磁盘 未安装文件系统的磁盘称之为生磁盘,生磁盘也可以作为文件读写,linux中一切皆文件. 磁盘分区 生磁盘可以被分区,分区中可以安装文件系统, ...

  7. Linux 0.11源码阅读笔记-中断过程

    Linux 0.11源码阅读笔记-中断过程 是什么中断 中断发生时,计算机会停止当前运行的程序,转而执行中断处理程序,然后再返回原被中断的程序继续运行.中断包括硬件中断和软件中断,硬中断是由外设自动产 ...

  8. Linux 0.11源码阅读笔记-总览

    Linux 0.11源码阅读笔记-总览 阅读源码的目的 加深对Linux操作系统的了解,了解Linux操作系统基本架构,熟悉进程管理.内存管理等主要模块知识. 通过阅读教复杂的代码,锻炼自己复杂项目代 ...

  9. Mybatis3.3——源码阅读笔记

    目录 Mybatis--Source阅读笔记 兵马未动,日志先行 异常 缓存 回收机制适配器 回收机制优化缓存 事务缓存 调试型缓存--日志缓存 解析 类型处理器 IO VFS Resource Re ...

随机推荐

  1. ajax简单封装

    var xmlhttp = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); ...

  2. BZOJ3933 [CQOI2015]多项式

    $\sum_{k = 0} ^ {n} a_kx^k = \sum_{k = 0} ^ {n} b_k(x - t)^k \Leftrightarrow \sum_{k = 0} ^ {n} a_k( ...

  3. oracle查锁表SQL

    SELECT l.session_id sid, s.serial#, l.locked_mode, l.oracle_username, s.user#, l.os_user_name,s.mach ...

  4. centos 卸载软件·

    centos下完全卸载php 1显示相关软件的列表 rpm -qa  | grep i(可以不加) php 2 卸载即可 rpm -e 软件名 --nodeps centos下完全卸载mysql 1显 ...

  5. jq 判断输入数字

    jq 判断输入数字 <input   id="N_source" name="N_source"   type="text" valu ...

  6. 哈希(Hask)

     编辑 Hash,一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种转换是一种压缩映射 ...

  7. bzoj 2286: [Sdoi2011消耗战

    #include<cstdio> #include<iostream> #define M 1000009 #define N 250009 #define ll long l ...

  8. 让webapi只接受ajax请求

    为了测试先做一个简单的webapi,直接用新建项目时默认的就可以了.   在浏览器中测试request get,得到结果   然后再项目中新建一个AjaxOnly的类   AjaxOnly继承Acti ...

  9. windows下svn自动更新

    配置hooks下post-commit.bat文件,文件内容如下 @echo offSET REPOS=%1SET REV=%2SET DIR=%REPOS%/hooksSET PATH=%PATH% ...

  10. Oracle性能调优

    这部分目前主要是从网上搜集来的,后续要在实践中慢慢体会. v$sqltext: 存储的是被分割的sql v$sqlarea: 存储的是完整的sql和一些统计信息,比如累计的执行次数.逻辑读.物理读等( ...