• lua 1.1 源码阅读总结


    GC

    1. 怎么回收的lua 中所有已经分配的数据都会用一些指令的数据结构来记录,当需要回收时,先遍历当前栈内所有 object,把 ref 标志位打上 1,遍历符号表(这部分不能回收),反符号表中的所有对象的 ref 标志位也打上 1, 如果有其它不用回收的也同样操作。回收也比较简单,这里遍历所有内部数据结构,如果是 0 就直接释放, 如果是 1 就置 0(可能下次就回收了), 这样就结束了
    2. 何时回收
    这个 1.1 有个内部阀值,当新加 object 的数量到达阀值时,就会触发回收机制。

    数据结构

      Hash

      

    typedef struct Hash
    {
         char           mark;
         unsigned int   nhash;
         Node         **list;
    } Hash;
    
    typedef struct node
    {
         Object ref;
         Object val;
         struct node *next;
    } Node;
    
    typedef union
    {
         Cfunction 	 f;
         real    	 n;
         char      	*s;
         Byte      	*b;
         struct Hash    *a;
         void           *u;
    } Value;
    
    typedef struct Object
    {
     Type  tag;
     Value value;
    } Object;
              
    typedef struct
    {
         char   *name;
         Object  object;
    } Symbol;
    

      全局数据区

      

    extern Symbol *lua_table;       /* key - value 表*/
    extern Word    lua_ntable;
    
    static Symbol  		tablebuffer[MAXSYMBOL] = {
                                        {"type",{T_CFUNCTION,{lua_type}}},
                                        ...
                                        };
    /* list 和数组的结合使用,目地是用 list 和 array 的特性, 参考 lua_findsymbol
    在 list 中查找,找到放到头(这样效率高点,下次再被用的概率大点), 没找到,就在头
    节点上加一个
      */                                    
    Symbol	       	       *lua_table=tablebuffer;
    Word   	 		lua_ntable=7;
    static struct List o6={ tablebuffer+6, 0};
    static struct List o5={ tablebuffer+5, &o6 };
    static struct List o4={ tablebuffer+4, &o5 };
    static struct List o3={ tablebuffer+3, &o4 };
    static struct List o2={ tablebuffer+2, &o3 };
    static struct List o1={ tablebuffer+1, &o2 };
    static struct List o0={ tablebuffer+0, &o1 };
    static struct List *searchlist=&o0;
    
                                        
                                        
    extern char  **lua_constant;    /* 常量表 */
    extern Word    lua_nconstant;
    static char tm[] = " mark";
    static char  	       *constantbuffer[MAXCONSTANT] = {tm+1, ti+1,
                            ...
                            };
                            
    
    
    extern char  **lua_string;    /* 就是普通的字符指针数组 *、
    extern Word    lua_nstring;
    static char 	       *stringbuffer[MAXSTRING];
    char  		      **lua_string = stringbuffer;
    Word    		lua_nstring=0;
    
    
    extern Hash  **lua_array;
    extern Word    lua_narray;
    
    extern char   *lua_file[];    /* 记录指针的数组 */
    extern int     lua_nfile;
    

      ps: lua_next 和 lua_nextval 可以看下,这个有点像迭代器的实现

    虚拟指令

    这个还是建议读下,主要就是对 stack 和 pc 的操作。

    /*
    ** Execute the given opcode. Return 0 in success or 1 on error.
    */
    int lua_execute (Byte *pc)
    {
     Object *oldbase = base;
     base = top;
     while (1)
     {
      OpCode opcode;
      switch (opcode = (OpCode)*pc++)
      {
       case PUSHNIL: tag(top++) = T_NIL; break;
       
       case PUSH0: tag(top) = T_NUMBER; nvalue(top++) = 0; break;
       case PUSH1: tag(top) = T_NUMBER; nvalue(top++) = 1; break;
       case PUSH2: tag(top) = T_NUMBER; nvalue(top++) = 2; break;
    
       case PUSHBYTE: tag(top) = T_NUMBER; nvalue(top++) = *pc++; break;
       
       case PUSHWORD: 
       {
        CodeWord code;
        get_word(code,pc);
        tag(top) = T_NUMBER; nvalue(top++) = code.w;
       }
       break;
       
       case PUSHFLOAT:
       {
        CodeFloat code;
        get_float(code,pc);
        tag(top) = T_NUMBER; nvalue(top++) = code.f;
       }
       break;
    
       case PUSHSTRING:
       {
        CodeWord code;
        get_word(code,pc);
        tag(top) = T_STRING; svalue(top++) = lua_constant[code.w];
       }
       break;
       
       case PUSHLOCAL0: case PUSHLOCAL1: case PUSHLOCAL2:
       case PUSHLOCAL3: case PUSHLOCAL4: case PUSHLOCAL5:
       case PUSHLOCAL6: case PUSHLOCAL7: case PUSHLOCAL8:
       case PUSHLOCAL9: *top++ = *(base + (int)(opcode-PUSHLOCAL0)); break;
       
       case PUSHLOCAL: *top++ = *(base + (*pc++)); break;
       
       case PUSHGLOBAL: 
       {
        CodeWord code;
        get_word(code,pc);
        *top++ = s_object(code.w);
       }
       break;
       
       case PUSHINDEXED:
        --top;
        if (tag(top-1) != T_ARRAY)
        {
         lua_reportbug ("indexed expression not a table");
         return 1;
        }
        {
         Object *h = lua_hashdefine (avalue(top-1), top);
         if (h == NULL) return 1;
         *(top-1) = *h;
        }
       break;
       
       case PUSHMARK: tag(top++) = T_MARK; break;
       
       case PUSHOBJECT: *top = *(top-3); top++; break;
       
       case STORELOCAL0: case STORELOCAL1: case STORELOCAL2:
       case STORELOCAL3: case STORELOCAL4: case STORELOCAL5:
       case STORELOCAL6: case STORELOCAL7: case STORELOCAL8:
       case STORELOCAL9: *(base + (int)(opcode-STORELOCAL0)) = *(--top); break;
        
       case STORELOCAL: *(base + (*pc++)) = *(--top); break;
       
       case STOREGLOBAL:
       {
        CodeWord code;
        get_word(code,pc);
        s_object(code.w) = *(--top);
       }
       break;
    
       case STOREINDEXED0:
        if (tag(top-3) != T_ARRAY)
        {
         lua_reportbug ("indexed expression not a table");
         return 1;
        }
        {
         Object *h = lua_hashdefine (avalue(top-3), top-2);
         if (h == NULL) return 1;
         *h = *(top-1);
        }
        top -= 3;
       break;
       
       case STOREINDEXED:
       {
        int n = *pc++;
        if (tag(top-3-n) != T_ARRAY)
        {
         lua_reportbug ("indexed expression not a table");
         return 1;
        }
        {
         Object *h = lua_hashdefine (avalue(top-3-n), top-2-n);
         if (h == NULL) return 1;
         *h = *(top-1);
        }
        top--;
       }
       break;
       
       case STORELIST0:
       case STORELIST:
       {
        int m, n;
        Object *arr;
        if (opcode == STORELIST0) m = 0;
        else m = *(pc++) * FIELDS_PER_FLUSH;
        n = *(pc++);
        arr = top-n-1;
        if (tag(arr) != T_ARRAY)
        {
         lua_reportbug ("internal error - table expected");
         return 1;
        }
        while (n)
        {
         tag(top) = T_NUMBER; nvalue(top) = n+m;
         *(lua_hashdefine (avalue(arr), top)) = *(top-1);
         top--;
         n--;
        }
       }
       break;
       
       case STORERECORD:
       {
        int n = *(pc++);
        Object *arr = top-n-1;
        if (tag(arr) != T_ARRAY)
        {
         lua_reportbug ("internal error - table expected");
         return 1;
        }
        while (n)
        {
         CodeWord code;
         get_word(code,pc);
         tag(top) = T_STRING; svalue(top) = lua_constant[code.w];
         *(lua_hashdefine (avalue(arr), top)) = *(top-1);
         top--;
         n--;
        }
       }
       break;
       
       case ADJUST:
       {
        Object *newtop = base + *(pc++);
        while (top < newtop) tag(top++) = T_NIL;
        top = newtop;  /* top could be bigger than newtop */
       }
       break;
       
       case CREATEARRAY:
        if (tag(top-1) == T_NIL) 
         nvalue(top-1) = 101;
        else 
        {
         if (tonumber(top-1)) return 1;
         if (nvalue(top-1) <= 0) nvalue(top-1) = 101;
        }
        avalue(top-1) = lua_createarray(nvalue(top-1));
        if (avalue(top-1) == NULL)
         return 1;
        tag(top-1) = T_ARRAY;
       break;
       
       case EQOP:
       {
        Object *l = top-2;
        Object *r = top-1;
        --top;
        if (tag(l) != tag(r)) 
         tag(top-1) = T_NIL;
        else
        {
         switch (tag(l))
         {
          case T_NIL:       tag(top-1) = T_NUMBER; break;
          case T_NUMBER:    tag(top-1) = (nvalue(l) == nvalue(r)) ? T_NUMBER : T_NIL; break;
          case T_ARRAY:     tag(top-1) = (avalue(l) == avalue(r)) ? T_NUMBER : T_NIL; break;
          case T_FUNCTION:  tag(top-1) = (bvalue(l) == bvalue(r)) ? T_NUMBER : T_NIL; break;
          case T_CFUNCTION: tag(top-1) = (fvalue(l) == fvalue(r)) ? T_NUMBER : T_NIL; break;
          case T_USERDATA:  tag(top-1) = (uvalue(l) == uvalue(r)) ? T_NUMBER : T_NIL; break;
          case T_STRING:    tag(top-1) = (strcmp (svalue(l), svalue(r)) == 0) ? T_NUMBER : T_NIL; break;
          case T_MARK:      return 1;
         }
        }
        nvalue(top-1) = 1;
       }
       break;
        
       case LTOP:
       {
        Object *l = top-2;
        Object *r = top-1;
        --top;
        if (tag(l) == T_NUMBER && tag(r) == T_NUMBER)
         tag(top-1) = (nvalue(l) < nvalue(r)) ? T_NUMBER : T_NIL;
        else
        {
         if (tostring(l) || tostring(r))
          return 1;
         tag(top-1) = (strcmp (svalue(l), svalue(r)) < 0) ? T_NUMBER : T_NIL;
        }
        nvalue(top-1) = 1; 
       }
       break;
       
       case LEOP:
       {
        Object *l = top-2;
        Object *r = top-1;
        --top;
        if (tag(l) == T_NUMBER && tag(r) == T_NUMBER)
         tag(top-1) = (nvalue(l) <= nvalue(r)) ? T_NUMBER : T_NIL;
        else
        {
         if (tostring(l) || tostring(r))
          return 1;
         tag(top-1) = (strcmp (svalue(l), svalue(r)) <= 0) ? T_NUMBER : T_NIL;
        }
        nvalue(top-1) = 1; 
       }
       break;
       
       case ADDOP:
       {
        Object *l = top-2;
        Object *r = top-1;
        if (tonumber(r) || tonumber(l))
         return 1;
        nvalue(l) += nvalue(r);
        --top;
       }
       break; 
       
       case SUBOP:
       {
        Object *l = top-2;
        Object *r = top-1;
        if (tonumber(r) || tonumber(l))
         return 1;
        nvalue(l) -= nvalue(r);
        --top;
       }
       break; 
       
       case MULTOP:
       {
        Object *l = top-2;
        Object *r = top-1;
        if (tonumber(r) || tonumber(l))
         return 1;
        nvalue(l) *= nvalue(r);
        --top;
       }
       break; 
       
       case DIVOP:
       {
        Object *l = top-2;
        Object *r = top-1;
        if (tonumber(r) || tonumber(l))
         return 1;
        nvalue(l) /= nvalue(r);
        --top;
       }
       break; 
       
       case CONCOP:
       {
        Object *l = top-2;
        Object *r = top-1;
        if (tostring(r) || tostring(l))
         return 1;
        svalue(l) = lua_createstring (lua_strconc(svalue(l),svalue(r)));
        if (svalue(l) == NULL)
         return 1;
        --top;
       }
       break; 
       
       case MINUSOP:
        if (tonumber(top-1))
         return 1;
        nvalue(top-1) = - nvalue(top-1);
       break; 
       
       case NOTOP:
        tag(top-1) = tag(top-1) == T_NIL ? T_NUMBER : T_NIL;
       break; 
       
       case ONTJMP:
       {
        CodeWord code;
        get_word(code,pc);
        if (tag(top-1) != T_NIL) pc += code.w;
       }
       break;
       
       case ONFJMP:	   
       {
        CodeWord code;
        get_word(code,pc);
        if (tag(top-1) == T_NIL) pc += code.w;
       }
       break;
       
       case JMP:
       {
        CodeWord code;
        get_word(code,pc);
        pc += code.w;
       }
       break;
        
       case UPJMP:
       {
        CodeWord code;
        get_word(code,pc);
        pc -= code.w;
       }
       break;
       
       case IFFJMP:
       {
        CodeWord code;
        get_word(code,pc);
        top--;
        if (tag(top) == T_NIL) pc += code.w;
       }
       break;
    
       case IFFUPJMP:
       {
        CodeWord code;
        get_word(code,pc);
        top--;
        if (tag(top) == T_NIL) pc -= code.w;
       }
       break;
    
       case POP: --top; break;
       
       case CALLFUNC:
       {
        Byte *newpc;
        Object *b = top-1;
        while (tag(b) != T_MARK) b--;
        if (tag(b-1) == T_FUNCTION)
        {
         lua_debugline = 0;			/* always reset debug flag */
         newpc = bvalue(b-1);
         bvalue(b-1) = pc;		        /* store return code */
         nvalue(b) = (base-stack);		/* store base value */
         base = b+1;
         pc = newpc;
         if (MAXSTACK-(base-stack) < STACKGAP)
         {
          lua_error ("stack overflow");
          return 1;
         }
        }
        else if (tag(b-1) == T_CFUNCTION)
        {
         int nparam; 
         lua_debugline = 0;			/* always reset debug flag */
         nvalue(b) = (base-stack);		/* store base value */
         base = b+1;
         nparam = top-base;			/* number of parameters */
         (fvalue(b-1))();			/* call C function */
         
         /* shift returned values */
         { 
          int i;
          int nretval = top - base - nparam;
          top = base - 2;
          base = stack + (int) nvalue(base-1);
          for (i=0; i<nretval; i++)
          {
           *top = *(top+nparam+2);
           ++top;
          }
         }
        }
        else
        {
         lua_reportbug ("call expression not a function");
         return 1;
        }
       }
       break;
       
       case RETCODE:
       {
        int i;
        int shift = *pc++;
        int nretval = top - base - shift;
        top = base - 2;
        pc = bvalue(base-2);
        base = stack + (int) nvalue(base-1);
        for (i=0; i<nretval; i++)
        {
         *top = *(top+shift+2);
         ++top;
        }
       }
       break;
       
       case HALT:
        base = oldbase;
       return 0;		/* success */
       
       case SETFUNCTION:
       {
        CodeWord file, func;
        get_word(file,pc);
        get_word(func,pc);
        if (lua_pushfunction (file.w, func.w))
         return 1;
       }
       break;
       
       case SETLINE:
       {
        CodeWord code;
        get_word(code,pc);
        lua_debugline = code.w;
       }
       break;
       
       case RESET:
        lua_popfunction ();
       break;
       
       default:
        lua_error ("internal error - opcode didn't match");
       return 1;
      }
     }
    }
    

      

  • 相关阅读:
    Postman提取接口返回值设置变量
    Python-浅拷贝与深拷贝
    Python列表
    typeorm查询两个没有关联关系的实体
    springboot去掉数据源自动加载
    docker搭建redis集群
    实习工作记录(一)大文件上传vue+WebUploader
    js重点之promise
    css重点
    git简单命令整理
  • 原文地址:https://www.cnblogs.com/ashen/p/12629193.html
Copyright © 2020-2023  润新知