zoukankan      html  css  js  c++  java
  • Lua源码分析(原创)[持续更新中]

    关于Lua源码的基础型别、内存分配、字符串存储、垃圾回收机制、table原理等部分讲解,我发现有位仁兄写得相当之好,强烈推荐大家先认真阅读下面这篇文章,链接如下

    http://simohayha.iteye.com/blog/517748

     

    本文将只对Lua的字节码和虚拟机的运行相关内容做重点分析

     

    LUA OPCODE格式分析

    Lopcodes.c

    Lua Opcode的格式关键在下面这个宏:

     

    #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))

     

    t(7)

    a(6)

    b(4~5)

    c(2~3)

    m(0~1)

     

    如图,第0~1bitm, 2~3bit c,4~5 bitb位,6bita位,7bitt

    t,a,b,c,m四部分,一起组成1 byteopcode。下面依次分析下t,a,b,c,m各自扮演什么角色。

     

    lua所有指令编码都在下面这个结构中

    const lu_byte luaP_opmodes[NUM_OPCODES] = {

    /*       T  A    B       C     mode        opcode   */

      opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_MOVE */

     ,opmode(0, 1, OpArgK, OpArgN, iABx)        /* OP_LOADK */

     ......(此处略去78行,有需要请参考附录A LUA OPCODE一览)

     ,opmode(0, 1, OpArgU, OpArgN, iABC)        /* OP_VARARG */

    };

    enum OpArgMask {

      OpArgN,  /* 参数未被使用 */

      OpArgU,  /* 已使用参数 */

      OpArgR,  /* 该参数是寄存器或跳转偏移 */

      OpArgK   /* 该参数是个常量或寄存器常量, Kconst之意 */

    };

    结合上面定义以及源码注释,不难分析出如下结论:

     

    含义

    t

    是否是测试操作,测试意味着跳转,跳转和测试指令该位为1

    a

    是否是寄存器操作

    b

    B参数OpArgMask类型

    c

    C参数,OpArgMask类型

    m

    op mode

     

     

    LUA 指令格式分析

    任意一条指令由操作码(opcode)和操作数组成。

    上一章主要对操作码的格式进行了分析,下面来整体分析下Lua中单条指令的格式。

     

    Lua中单条指令为32位,依参数的类型和个数不同,有三种模式:

     

        ------------------------->  

    iABC:

    B(23~31)

    C(14~22)

    A(6~13)

    opcode(0~5)

     

    iABx:

    Bx(  14~31 )      

    A(6~13)

    opcode(0~5)

     

    iAsBx:

    sBx( 14~31 )      

    A(6~13)

    opcode(0~5)

     

    三种模式中i表示6位的opcode,iABC表示三个参数的指令,iABx将iABC中的B和C合并为18位的无符号数,

    iAsBx将iABC中的B和C合并为18位的有符号数。

     

     

    相关元素SIZEPOS定义如下:

    #define SIZE_C      9

    #define SIZE_B      9

    #define SIZE_Bx     (SIZE_C + SIZE_B)

    #define SIZE_A      8

     

    #define SIZE_OP     6

     

    #define POS_OP      0

    #define POS_A       (POS_OP + SIZE_OP)

    #define POS_C       (POS_A + SIZE_A)

    #define POS_B       (POS_C + SIZE_C)

    #define POS_Bx      POS_C

     

     

     

    附录A

    LUA OPCODE一览

    const lu_byte luaP_opmodes[NUM_OPCODES] = {

    /*       T  A    B       C     mode        opcode   */

      opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_MOVE */

     ,opmode(0, 1, OpArgK, OpArgN, iABx)        /* OP_LOADK */

     ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_LOADBOOL */

     ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_LOADNIL */

     ,opmode(0, 1, OpArgU, OpArgN, iABC)        /* OP_GETUPVAL */

     ,opmode(0, 1, OpArgK, OpArgN, iABx)        /* OP_GETGLOBAL */

     ,opmode(0, 1, OpArgR, OpArgK, iABC)        /* OP_GETTABLE */

     ,opmode(0, 0, OpArgK, OpArgN, iABx)        /* OP_SETGLOBAL */

     ,opmode(0, 0, OpArgU, OpArgN, iABC)        /* OP_SETUPVAL */

     ,opmode(0, 0, OpArgK, OpArgK, iABC)        /* OP_SETTABLE */

     ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_NEWTABLE */

     ,opmode(0, 1, OpArgR, OpArgK, iABC)        /* OP_SELF */

     ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_ADD */

     ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_SUB */

     ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_MUL */

     ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_DIV */

     ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_MOD */

     ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_POW */

     ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_UNM */

     ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_NOT */

     ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_LEN */

     ,opmode(0, 1, OpArgR, OpArgR, iABC)        /* OP_CONCAT */

     ,opmode(0, 0, OpArgR, OpArgN, iAsBx)       /* OP_JMP */

     ,opmode(1, 0, OpArgK, OpArgK, iABC)        /* OP_EQ */

     ,opmode(1, 0, OpArgK, OpArgK, iABC)        /* OP_LT */

     ,opmode(1, 0, OpArgK, OpArgK, iABC)        /* OP_LE */

     ,opmode(1, 1, OpArgR, OpArgU, iABC)        /* OP_TEST */

     ,opmode(1, 1, OpArgR, OpArgU, iABC)        /* OP_TESTSET */

     ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_CALL */

     ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_TAILCALL */

     ,opmode(0, 0, OpArgU, OpArgN, iABC)        /* OP_RETURN */

     ,opmode(0, 1, OpArgR, OpArgN, iAsBx)       /* OP_FORLOOP */

     ,opmode(0, 1, OpArgR, OpArgN, iAsBx)       /* OP_FORPREP */

     ,opmode(1, 0, OpArgN, OpArgU, iABC)        /* OP_TFORLOOP */

     ,opmode(0, 0, OpArgU, OpArgU, iABC)        /* OP_SETLIST */

     ,opmode(0, 0, OpArgN, OpArgN, iABC)        /* OP_CLOSE */

     ,opmode(0, 1, OpArgU, OpArgN, iABx)        /* OP_CLOSURE */

     ,opmode(0, 1, OpArgU, OpArgN, iABC)        /* OP_VARARG */

    };

     

    typedef enum {

    /*----------------------------------------------------------------------

    name        args    description

    ------------------------------------------------------------------------*/

    OP_MOVE,/*  A B R(A) := R(B)                    */

    OP_LOADK,/* A Bx    R(A) := Kst(Bx)                 */

    OP_LOADBOOL,/*  A B C   R(A) := (Bool)B; if (C) pc++            */

    OP_LOADNIL,/*   A B R(A) := ... := R(B) := nil          */

    OP_GETUPVAL,/*  A B R(A) := UpValue[B]              */

     

    OP_GETGLOBAL,/* A Bx    R(A) := Gbl[Kst(Bx)]                */

    OP_GETTABLE,/*  A B C   R(A) := R(B)[RK(C)]             */

     

    OP_SETGLOBAL,/* A Bx    Gbl[Kst(Bx)] := R(A)                */

    OP_SETUPVAL,/*  A B UpValue[B] := R(A)              */

    OP_SETTABLE,/*  A B C   R(A)[RK(B)] := RK(C)                */

     

    OP_NEWTABLE,/*  A B C   R(A) := {} (size = B,C)             */

     

    OP_SELF,/*  A B C   R(A+1) := R(B); R(A) := R(B)[RK(C)]     */

     

    OP_ADD,/*   A B C   R(A) := RK(B) + RK(C)               */

    OP_SUB,/*   A B C   R(A) := RK(B) - RK(C)               */

    OP_MUL,/*   A B C   R(A) := RK(B) * RK(C)               */

    OP_DIV,/*   A B C   R(A) := RK(B) / RK(C)               */

    OP_MOD,/*   A B C   R(A) := RK(B) % RK(C)               */

    OP_POW,/*   A B C   R(A) := RK(B) ^ RK(C)               */

    OP_UNM,/*   A B R(A) := -R(B)                   */

    OP_NOT,/*   A B R(A) := not R(B)                */

    OP_LEN,/*   A B R(A) := length of R(B)              */

     

    OP_CONCAT,/*    A B C   R(A) := R(B).. ... ..R(C)           */

     

    OP_JMP,/*   sBx pc+=sBx                 */

     

    OP_EQ,/*    A B C   if ((RK(B) == RK(C)) ~= A) then pc++        */

    OP_LT,/*    A B C   if ((RK(B) <  RK(C)) ~= A) then pc++        */

    OP_LE,/*    A B C   if ((RK(B) <= RK(C)) ~= A) then pc++        */

     

    OP_TEST,/*  A C if not (R(A) <=> C) then pc++           */

    OP_TESTSET,/*   A B C   if (R(B) <=> C) then R(A) := R(B) else pc++ */

     

    OP_CALL,/*  A B C   R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */

    OP_TAILCALL,/*  A B C   return R(A)(R(A+1), ... ,R(A+B-1))      */

    OP_RETURN,/*    A B return R(A), ... ,R(A+B-2)  (see note)  */

     

    OP_FORLOOP,/*   A sBx   R(A)+=R(A+2);

                if R(A) <?= R(A+1) then { pc+=sBx; R(A+3)=R(A) }*/

    OP_FORPREP,/*   A sBx   R(A)-=R(A+2); pc+=sBx               */

     

    OP_TFORLOOP,/*  A C R(A+3), ... ,R(A+2+C) := R(A)(R(A+1), R(A+2));

                            if R(A+3) ~= nil then R(A+2)=R(A+3) else pc++   */

    OP_SETLIST,/*   A B C   R(A)[(C-1)*FPF+i] := R(A+i), 1 <= i <= B    */

     

    OP_CLOSE,/* A   close all variables in the stack up to (>=) R(A)*/

    OP_CLOSURE,/*   A Bx    R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n))  */

     

    OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg        */

    } OpCode;

  • 相关阅读:
    C#数据结构一:基础知识
    使用工厂方法模式实现多数据库WinForm手机号码查询器(附源码)
    我的个人年度总结
    CutePsWheel javascript libary:控制输入文本框为可使用滚轮控制的js库
    CSS制作无图片圆角矩形
    将SqlServer数据库转换Sqlite的工具
    原创电子书:C#难点逐个击破
    (译)在非IE浏览器中实现“灰阶化”
    extjs 记录一下
    Ext.Window相关
  • 原文地址:https://www.cnblogs.com/billin/p/1978452.html
Copyright © 2011-2022 走看看