转自:http://www.cppblog.com/pwq1989/archive/2013/11/28/204487.html

大家可以从官网下载到源码(http://luajit.org/),也可以从Github(https://github.com/LuaDist/luajit)down下来,顺便还可以看下commit记录。

大家对着luajit的wiki结合源码看的话会更好些,因为。。文档太特么少了!!

目录结构:
-- src
    -- host
    -- jit
    *.c
    *.h
    *.dasc
等等,别的不是很重要

最开始我是从main函数开始看的,然后。。碰了一鼻子灰,后来研究下他的makefile,发现他是这样子的编译的,贴一下关键的msvcbuild.bat的代码(这个更容易看懂)

:X64
minilua %DASM% -LN %DASMFLAGS% -o host\buildvm_arch.h vm_x86.dasc
@if errorlevel goto :BAD %LJCOMPILE% /I "." /I %DASMDIR% host\buildvm*.c
@if errorlevel goto :BAD
%LJLINK% /out:buildvm.exe buildvm*.obj
@if errorlevel goto :BAD
if exist buildvm.exe.manifest^
%LJMT% -manifest buildvm.exe.manifest -outputresource:buildvm.exe buildvm -m peobj -o lj_vm.obj
@if errorlevel goto :BAD
buildvm -m bcdef -o lj_bcdef.h %ALL_LIB%
@if errorlevel goto :BAD
buildvm -m ffdef -o lj_ffdef.h %ALL_LIB%
@if errorlevel goto :BAD
buildvm -m libdef -o lj_libdef.h %ALL_LIB%
@if errorlevel goto :BAD
buildvm -m recdef -o lj_recdef.h %ALL_LIB%
@if errorlevel goto :BAD
buildvm -m vmdef -o jit\vmdef.lua %ALL_LIB%
@if errorlevel goto :BAD
buildvm -m folddef -o lj_folddef.h lj_opt_fold.c
@if errorlevel goto :BAD

先创建了一个buildvm.exe的中间工具,来自动生成代码,分别生成了lj_vm.obj,lj_bcdef.h,lj_ffdef.h ,lj_recdef.h ,jit\vmdef.lua,lj_folddef.h, lj_libdef.h

其中lv_vm.obj是依赖于host\buildvm_arch.h的,这个是用DynASM预处理vm_x86.dasc生成的,这个工具的具体分析会在下一篇博客提及。

先来看下上面自动生成的代码:
lj_bcdef.h:

LJ_DATADEF const uint16_t lj_bc_ofs[] = {
,
,
,
,
, }; LJ_DATADEF const uint16_t lj_bc_mode[] = {
BCDEF(BCMODE)
BCMODE_FF,
BCMODE_FF,
BCMODE_FF,
BCMODE_FF,
BCMODE_FF, };

lj_bc_ofs[]可能是bc在vm代码段中的偏移量(这个我还没深入进去调试一下),vm的一部分是用DynASM直接撸汇编撸出来的,wiki中也有提到下一步jit化的opcode等等。

lj_bc_mode[]的用来根据压缩后的bytecode构造,分离出操作数,第一行的两个宏的定义是

#define BCMODE(name, ma, mb, mc, mm) \
(BCM##ma|(BCM##mb<<)|(BCM##mc<<)|(MM_##mm<<)),
#define BCMODE_FF 0 #define BCDEF(_) \
/* Comparison ops. ORDER OPR. */ \
_(ISLT, var, ___, var, lt) \
_(ISGE, var, ___, var, lt) \
_(ISLE, var, ___, var, le) \
_(ISGT, var, ___, var, le) \
...
总之就是充斥着各种拼接起来的宏

lj_ffdef.h:

FFDEF(assert)
FFDEF(type)
FFDEF(next)
FFDEF(pairs)
FFDEF(ipairs_aux)
...

FFDEF的定义是在

/* Fast function ID. */
typedef enum {
FF_LUA_ = FF_LUA, /* Lua function (must be ). */
FF_C_ = FF_C, /* Regular C function (must be ). */
#define FFDEF(name) FF_##name,
#include "lj_ffdef.h"
FF__MAX
} FastFunc;

差不多就是用FF_##name把上面的名字拼接起来,然后生成在enum里面,这样就能当成是数字,在数组中迅速找到入口了

vmdef.lua:
这个里面内容就不贴了,包括bcname,irname,irfpm,irfield,ircall 的定义,在jit文件夹下面,用于调试等,比如在dump.lua中就有用到

local jit = require("jit")
assert(jit.version_num == , "LuaJIT core/library version mismatch")
local jutil = require("jit.util")
local vmdef = require("jit.vmdef") // ← ← ← ←

当你用luajit -jdump的时候,就是调用的lua的jit库里面的lua函数

lj_recdef.h:

static const uint16_t recff_idmap[] = {
,
0x0100,
0x0200,
0x0300,
,
,
0x0400, }; static const RecordFunc recff_func[] = {
recff_nyi,
recff_c,
recff_assert,
recff_type,
recff_ipairs_aux, };

其中recff_func[]是被注册的被traced jit 跟踪的函数,具体可是在lj_ffrecord.c里面看到
recff_idmap[]被用在lj_ffrecord_func这个函数中,有一个关键的数据结构RecordFFData,用来记录在trace过程中被调用函数的参数和返回值个数,和一些辅助数据,opcode,literal等等。通过recff_idmap[]保存的值来区分函数(待仔细研究)

lj_folddef.h:

static const FoldFunc fold_func[] = {
fold_kfold_numarith,
fold_kfold_ldexp,
fold_kfold_fpmath,
fold_kfold_numpow, }; static const uint32_t fold_hash[] = {
0xffffffff,
0xffffffff,
0x5b4c8016, };

用在FOLD optimization中,见lj_opt_fold.c,主要在

if ((fh & 0xffffff) == k || (fh = fold_hash[h+], (fh & 0xffffff) == k)) {
ref = (IRRef)tref_ref(fold_func[fh >> ](J));
if (ref != NEXTFOLD)
break;
}

是根据数组偏移获取函数,直接执行。
(这个Optimation略复杂,以后的博文中再说)

----------------------------------------分割线-------------------------------------------

以上就是buildvm生成代码,在很多.c的文件中,他加入了一些无意义的MARCO,目的是为了能被buildvm识别出

下面说说src根目录下面的文件:

lauxlib.h:
用户开发扩展和与C交互的时候的头文件

lib_*.h /.c:
顾名思义,就是利用LuaAPI写的内部标准库,会在方法上表明是否会被trace ( LJLIB_REC(.) )。

ljamalg.c:
文件的合并

lj_alloc.h /.c:
定制的Memory Allocator

lj_api.c:

Public Lua/C API.

lj_arch.h:

Target architecture selection

lj_jit.h:
jit编译器里面数据结构的定义

lj_asm.h/ .c  lj_asm_*.c lj_emit_*.h lj_target_*.h/.c :
将IR编译成Machine Code,关键的数据结构ASMState,线性扫描的O(n2)分配算法

lj_bc.h/ .c:
Luajit字节码的定义和内存布局

lj_bcdump.c lj_bcread.c  lj_bcwrite.c:
围绕着字节码的操作

lj_carith.c:

C实现的一些数字运算

lj_ccall.h/ .c  lj_ccallback.h / .c :
FFI C语言函数调用和回调绑定

lj_debug.h/.c :
调试与自省用

lj_def.h:
这个很重要,重要的类型和一些宏定义在这里

lj_c*.h/ .c:
和C语言先关的,比如类型转化,char管理,数据管理

lj_frame.h:
Luajit的栈帧管理

lj_func.h/.c:
Function handle和闭包有关的upvalue数据结构

lj_gc.h/.c:
GC相关,GC可以看下luajit的wiki,里面涉及不少增量式GC的paper和作者的看法

lj_gdbjit.h/.c :
对gdb的支持

lj_ir*.h/.c:
SSA,IR相关(这个和bytecode还是不一样的)操作和优化

lj_lex.h/.c  lj_parse.h/.c:
lexer和parser

lj_mcode.h/.c:
Machine Code管理

lj_opt_*.h:
各种bytecode层面上的优化

lj_snap.h/.c:
快照支持

lj_state.h/.c:
LuaState和Stack的操作

lj_str*.h/.c  lj_tab.h/.c:
原生类型string和table操作

lj_udata.h/.c:
类型user data的操作

lj_vm.h/.c  lj_vmevent.h/.c:
vm的API和事件注册(lj_vmevent_send)

lj_vmmath.h/.c:
对vm支持的math库

lua.h:
luaState等基本的Lua结构

lualib.h:
和Lua一样,标准库的API

luajit.h:
luajit 的public API

vm_*.dasc:
编译期被DynASM预处理的源文件,下一篇讲DynASM时候介绍dasc文件

wmain.c:
windows下面的main入口

和Trace相关的:
lj_crecord.h/.c  : C操作的trace record
lj_dispatch.h/.c :  指令分发,调用ASMFuction,处理指令前的hook和记录trace用的hot count,有一个重要的数据结构 GG_State
lj_ff*.h/.c: 上面讲lj_ffdef.h的时候提过,trace的时候 记录Fast Function的调用记数
lj_trace.h/.c: trace的具体过程
lj_traceerr.h : trace error

初识Luajit的更多相关文章

  1. Android动画效果之初识Property Animation(属性动画)

    前言: 前面两篇介绍了Android的Tween Animation(补间动画) Android动画效果之Tween Animation(补间动画).Frame Animation(逐帧动画)Andr ...

  2. 初识Hadoop

    第一部分:              初识Hadoop 一.             谁说大象不能跳舞 业务数据越来越多,用关系型数据库来存储和处理数据越来越感觉吃力,一个查询或者一个导出,要执行很长 ...

  3. python学习笔记(基础四:模块初识、pyc和PyCodeObject是什么)

    一.模块初识(一) 模块,也叫库.库有标准库第三方库. 注意事项:文件名不能和导入的模块名相同 1. sys模块 import sys print(sys.path) #打印环境变量 print(sy ...

  4. 初识IOS,Label控件的应用。

    初识IOS,Label控件的应用. // // ViewController.m // Gua.test // // Created by 郭美男 on 16/5/31. // Copyright © ...

  5. UI篇(初识君面)

    我们的APP要想吸引用户,就要把UI(脸蛋)搞漂亮一点.毕竟好的外貌是增进人际关系的第一步,我们程序员看到一个APP时,第一眼就是看这个软件的功能,不去关心界面是否漂亮,看到好的程序会说"我 ...

  6. Python导出Excel为Lua/Json/Xml实例教程(一):初识Python

    Python导出Excel为Lua/Json/Xml实例教程(一):初识Python 相关链接: Python导出Excel为Lua/Json/Xml实例教程(一):初识Python Python导出 ...

  7. 初识SpringMvc

    初识SpringMvc springMvc简介:SpringMVC也叫Spring Web mvc,属于表现层的框架.Spring MVC是Spring框架的一部分,是在Spring3.0后发布的 s ...

  8. 初识redis数据类型

    初识redis数据类型 1.String(字符串) string是redis最基本的类型,一个key对应一个value. string类型是二进制安全的.意思是redis的string可以包含任何数据 ...

  9. Redis初识、设计思想与一些学习资源推荐

    一.Redis简介 1.什么是Redis Redis 是一个开源的使用ANSI C 语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value 数据库,并提供多种语言的API.从2010 年 ...

随机推荐

  1. 在C语言中使用syslog打印日志到日志文件

    参见 <unix 环境高级编程>第13 章 精灵进程 Syslog为每个事件赋予几个不同的优先级: LOG_EMERG——紧急情况 LOG_ALERT——应该被立即改正的问题,如系统数据库 ...

  2. Java并发之ArrayBlockingQueue

    ArrayBlockingQueue是一个由数组支持的有界阻塞队列.此队列按 FIFO(先进先出)原则对元素进行排序.队列的头部是在队列中存在时间最长的元素.队列的尾部是在队列中存在时间最短的元素.新 ...

  3. 2014年互联网IT待遇

    1. 13k*14~16k*145.美团 13k*15~16k*15,也有更高的.6.去哪儿 11k*16~15k*167.人人技术类(12K-14K)*14 (2014)8.58同城 20w+9.网 ...

  4. UOJ136 开学前的作文

    描述 红包是一个萌萌的男孩子. 红包由于 NOI 惨挂,直到前不久依然无心写作业.如今快开学了,他决定好好完成作业. 对于可以交电子稿的作文,红包有特殊的完成技巧,大致流程是依次选中一段内容→按下 C ...

  5. Oracle的select检索数据

    --Select语法 select [distinct | All] select_list from table_list [where_clause] [group_by_clause] [Hav ...

  6. Quota Management and Enforcement

    Neutron API中大多的resource都需要quota limits. Neutron API暴露出一个extension 来管理quota,Quota limits are enforced ...

  7. User Agent注入攻击及防御

    CloudFlare公司经常会收到客户询问为什么他们的一些请求会被 CloudFlare WAF屏蔽.最近,一位客户就提出他不能理解为什么一个访问他主页简单的 GET 请求会被 WAF 屏蔽. 下面是 ...

  8. Linux课程---8、Linux启动流程

    Linux课程---8.Linux启动流程 一.总结 一句话总结: grub启动引导界面(比如装了多系统,选择系统),找到linux内核 启动init程序,加载各种驱动 1.进入grub界面选择相应的 ...

  9. html怎样可是使文本框内容不可修改

    html怎样可是使文本框内容不可修改 <input type="text" readonly="readonly" onfocus="alert ...

  10. io.js的六大新特性

    io.js是nodejs的友好版的分支("friendly fork”).它支持npm中所有的同样模块,且使用了v8最新版本的截取(v8是被node.js使用js解释器),且修复了很多的bu ...