• 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;
      }
     }
    }
    

      

  • 相关阅读:
    HDU 1813 Escape from Tetris
    BZOJ 2276 Temperature
    BZOJ 4499 线性函数
    BZOJ 3131 淘金
    HDU 5738 Eureka
    POJ 2409 Let it Bead
    POJ 1286 Necklace of Beads
    POJ 1696 Space Ant
    Fox And Jumping
    Recover the String
  • 原文地址:https://www.cnblogs.com/ashen/p/12629193.html
Copyright © 2020-2023  润新知