Lua 源码学习笔记

1.全局环境_G

  • Lua将所有的全局变量保存在一个常规的table中,这个table被称为全局环境,并且将这个table保存在一个全局变量_G中,也就是说在脚本中可以用_G获取这个全局table,并且_G._G 和 _G是等价的,在默认情况,Lua在全局环境_G中添加了标准库比如math、函数比如pairs、print等

2.局部环境_ENV

  • 编译器在编译所有代码段(chunk)前,在外层创建局部变量_ENV;
  • 编译器将所有自由名称var(无local的变量)翻译为_ENV.var;
  • 通常,_G和_ENV指向的是同一个表。按定义,_ENV永远指向的是当前的环境;_G通常指向的是全局变量。_ENV是一个局部变量,所有对“全局变量”的访问实际上访问的都是_ENV指向的全局表
  • 对于每一个chunk,都有一个叫_ENV的upvalue,此时_ENV的初值就是_G。在chunk内的函数,都会有这个upvalue值。那么在该代码块中加入的非local变量,可以直接通过名称在其他chunk中访问到(当然该chunk的_ENV 也得是 _G)。
  • 函数load使用全局环境初始化代码段的第一个upvalue,即Lua语言内部维护的一个普通的表。
  • Lua查找变量定义的规则为:局部变量 -> upvalue -> 全局变量

3.string

  • (1)计算需要新创建的字符串对应的散列值;
    (2)根据散列值找到对应的散列桶,遍历该散列桶的所有元素,如果能够查找到同样的字符串,说明之前已经存在相同的字符串,此时不需要重新分配一份新的字符串数据,直接返回即可。
    (3)如果第(2)步没有找到相同的字符串,调用luaS_newlstr函数创建一个新的字符串
  • Lua虚拟机中global_State的strt字段存放着当前系统中的所有字符串
  • Lua中的字符串变量存放的是字符串的引用,而不是字符串本身
  • 短字符串在Lua虚拟机中只有一份
  • 短字符串比较直接比较地址,长字符串先比较长度再比较内容

4.userdata

  • userdata 是一种用户自定义数据,用于表示一种由应用程序或 C/C++ 语言库所创建的类型,可以将任意 C/C++ 的任意数据类型的数据(通常是 struct 、指针和类)存储到 Lua 变量中调用。

  • udata存储userdata的数据

  • userdata分为两类,”full userdata”和”light userdata”。

  • typedef union Udata {
      	L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
    	struct {
    		CommonHeader;
    		struct Table *metatable;
    	    struct Table *env;
    	    size_t len;
    	  } uv;
    } Udata;

     

  •  

5.table

  • Lua table是数组与哈希表的混合结构
  • 读:如果key为正整数并且小于数组长度,去数组中查找,否则去哈希表中查找
  • 写:(1).先执行一次读操作,如果table中对应的key已经存在,则修改对应的值。(2).对于正整数key,小于数组长度并且数组对应位置为空的情况下,存入数组中。(3).计算key的hash值,根据hash值映射出一个下标,找到对应的哈希桶存入。(4).当出现键冲突时,会用闭散列方法解决冲突,当已经没有空位置的时候,执行rehash操作。(5).rehash:按一定规则重新计算数组与哈希表的大小,重新分配元素。
  •  尽量使用数组域,而不是hash
  •  尽量创建Table时初始化数据,而不是建空Table一个一个插入,因为每次插入都会执行一次写操作。
  • typedef union TKey {
      struct {
        TValuefields;
        int next;  /* for chaining (offset for next node) */
      } nk;
      TValue tvk;
    } TKey;
    
    typedef struct Node {
      TValue i_val;
      TKey i_key;
    } Node;
    
    typedef struct Table {
      CommonHeader;
      lu_byte flags;  /* 1<<p means tagmethod(p) is not present */
      lu_byte lsizenode;  /* log2 of size of 'node' array */
      unsigned int sizearray;  /* size of 'array' array */
      TValue *array;  /* array part */
      Node *node;
      Node *lastfree;  /* any free position is before this position */
      struct Table *metatable;
      GCObject *gclist;
    } Table;

     

6.Tvalue

  • TValue是实现Lua弱数据类型的主要数据结构
  • Tvalue是一个结构体,包括联合体value与int tt_,tt_存储数据类型,value存储值
  • union Value {
        GCObject *gc;    /* collectable objects */
        void *p;         /* light userdata */
        int b;           /* booleans */
        lua_CFunction f; /* light C functions */
        lua_Integer i;   /* integer numbers */
        lua_Number n;    /* float numbers */
    };
    
    
    struct lua_TValue {
        TValuefields;
    };
    
    #define TValuefields    Value value_; int tt_
    
    typedef struct lua_TValue TValue;
    
    
    typedef TValue *StkId;  /* index to stack elements */
    

     

7.Closure

  • closure是funtion在lua运行时的对象,是一个联合体,包含lclosure与cclosure两个结构体
  • typedef struct Proto {
      CommonHeader;
      lu_byte numparams;  /* number of fixed parameters */
      lu_byte is_vararg;
      lu_byte maxstacksize;  /* number of registers needed by this function */
      int sizeupvalues;  /* size of 'upvalues' */
      int sizek;  /* size of 'k' */
      int sizecode;
      int sizelineinfo;
      int sizep;  /* size of 'p' */
      int sizelocvars;
      int linedefined;  /* debug information  */
      int lastlinedefined;  /* debug information  */
      TValue *k;  /* constants used by the function */  // 保存常量用的数组
      Instruction *code;  /* opcodes */  // 保存分析之后生成的OpCode数组
      struct Proto **p;  /* functions defined inside the function */
      int *lineinfo;  /* map from opcodes to source lines (debug information) */
      LocVar *locvars;  /* information about local variables (debug information) */  // 保存局部变量的信息
      Upvaldesc *upvalues;  /* upvalue information */   // 保存UpValue的信息
      struct LClosure *cache;  /* last-created closure with this prototype */
      TString  *source;  /* used for debug information */
      GCObject *gclist;
    } Proto;
    
    # define ClosureHeader \
    CommonHeader; lu_byte nupvalues; GCObject *gclist
    
    typedef struct CClosure {
      ClosureHeader;
      lua_CFunction f;
      TValue upvalue[1];  /* list of upvalues */
    } CClosure;
    
    
    typedef struct LClosure {
      ClosureHeader;
      struct Proto *p;
      UpVal *upvals[1];  /* list of upvalues */
    } LClosure;
    
    
    typedef union Closure {
      CClosure c;
      LClosure l;
    } Closure;

     

8.Lua State

  • lua_newstate函数主要用于创建一个lua_State和global_State的数据结构。

  • lua_State:主线程栈结构,包括数据栈,与调用栈,数据栈实际就是Tvalue的动态数组,调用栈实质上用一个双向链表,链表中的每个节点是用一个CallInfo的结构体来实现,保存着正在调用的函数的运行状态。

  • global_State:全局状态机,维护全局字符串表、内存管理函数、gc等信息

  • lua_State和global_State结构,通过LG的方式进行链接,将全局状态机global_State挂载到lua_State数据结构上

  • global_State结构是完全感知不到的:我们无法用Lua公开的API获取到它的指针、句柄或引用

  • lua_State和global_State之间通过 global_State *l_G 互相建立链接关系。

  • /*
    ** 'global state', shared by all threads of this state
    ** lua 全局状态机
    ** 作用:管理全局数据,全局字符串表、内存管理函数、 GC 把所有对象串联起来的信息、内存等
    */
    typedef struct global_State {
     
      /* 版本号  */
      const lua_Number *version;  /* pointer to version number */
     
      /* 内存管理 */
      lua_Alloc frealloc;  /* Lua的全局内存分配器,用户可以替换成自己的 - function to reallocate memory */
      void *ud;         /* 分配器的userdata - auxiliary data to 'frealloc' */
     
      /* 线程管理 */
      struct lua_State *mainthread; /* 主线程 */
      struct lua_State *twups;  /* 闭包了当前线程变量的其他线程列表 - list of threads with open upvalues */
     
      /* 字符串管理 */
      stringtable strt;  /* 字符串table Lua的字符串分短字符串和长字符串 - hash table for strings */
      TString *strcache[STRCACHE_N][STRCACHE_M];  /* 字符串缓存 - cache for strings in API */
     
      /* 虚函数表 */
      TString *tmname[TM_N];  /* 预定义方法名字数组 -  array with tag-method names */
      struct Table *mt[LUA_NUMTAGS];  /* 每个基本类型一个metatable(整个Lua最重要的Hook机制) - metatables for basic types */
     
      /* 错误处理 */
      lua_CFunction panic;  /* to be called in unprotected errors */
      TString *memerrmsg;  /* memory-error message */
     
      /* GC管理 */
      unsigned int gcfinnum;  /* number of finalizers to call in each GC step */
      int gcpause;  /* size of pause between successive GCs */
      int gcstepmul;  /* GC 'granularity' */
     
      l_mem totalbytes;  /* number of bytes currently allocated - GCdebt */
      l_mem GCdebt;  /* bytes allocated not yet compensated by the collector */
      lu_mem GCmemtrav;  /* memory traversed by the GC */
      lu_mem GCestimate;  /* an estimate of the non-garbage memory in use */
     
      TValue l_registry;
      unsigned int seed;  /* randomized seed for hashes */
      lu_byte currentwhite;
      lu_byte gcstate;  /* state of garbage collector */
      lu_byte gckind;  /* kind of GC running */
      lu_byte gcrunning;  /* true if GC is running */
      GCObject *allgc;  /* list of all collectable objects */
      GCObject **sweepgc;  /* current position of sweep in list */
      GCObject *finobj;  /* list of collectable objects with finalizers */
      GCObject *gray;  /* list of gray objects */
      GCObject *grayagain;  /* list of objects to be traversed atomically */
      GCObject *weak;  /* list of tables with weak values */
      GCObject *ephemeron;  /* list of ephemeron tables (weak keys) */
      GCObject *allweak;  /* list of all-weak tables */
      GCObject *tobefnz;  /* list of userdata to be GC */
      GCObject *fixedgc;  /* list of objects not to be collected */
     
    } global_State;

     

  • struct lua_State {
      CommonHeader;
      unsigned short nci;  /* number of items in 'ci' list */
      lu_byte status;
      StkId top;  /* first free slot in the stack */
      global_State *l_G;
      CallInfo *ci;  /* call info for current function */
      const Instruction *oldpc;  /* last pc traced */
      StkId stack_last;  // 指向stack末尾存放的EXTRA_STACK个数组的起始位置
      StkId stack;  /* stack base */
      UpVal *openupval;  /* list of open upvalues in this stack */
      GCObject *gclist;
      struct lua_State *twups;  /* list of threads with open upvalues */
      struct lua_longjmp *errorJmp;  /* current error recover point */
      CallInfo base_ci;  /* CallInfo for first level (C calling Lua) */
      volatile lua_Hook hook;
      ptrdiff_t errfunc;  /* current error handling function (stack index) */
      int stacksize;
      int basehookcount;
      int hookcount;
      unsigned short nny;  /* number of non-yieldable calls in stack */
      unsigned short nCcalls;  /* number of nested C calls */
      l_signalT hookmask;
      lu_byte allowhook;
    };

     

9.Lua GC

  • lua在每次分配新的内存时,主动调用luaC_checkGC检查是否满足GC条件
  • 三色标记法

    白色:当前白色——待回收状态、非当前白——待访问状态

    灰色:代标记状态,GC已访问,但该对象引用的其他对象还没有被标记

    黑色:不可回收状态

    过程详解:

    1.新建对象,将其颜色标记为非当前白色

    2.达到GC条件(自动、手动),遍历根节点(mainthread主线程, 注册表registry, 全局元表metatable, 上次GC循环中剩余的finalize中的对象)引用的对象,开始标记

    3.当GC遍历到对象A,就将其标记为灰色,然后去遍历对象A引用了哪些可回收对象

       4.当对象A引用的所有可回收对象都被标记以后, 对象A被标记为黑色

       5.GC递归执行3,4步骤直到遍历完所有可达的对象

       6.遍历global_State的allgc链表所有对象,删除白色对象

10.Lua源码编译

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值