精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

詳解關于Lua源碼分析學習教程

移動開發 iOS
關于Lua源碼分析學習教程是本文要介紹的內容,主要來了解LUA中源碼的使用方法。Lua首先將源程序編譯成為字節碼,然后交由虛擬機解釋執行.對于每一個函數,Lua的編譯器將創建一個原型.

關于Lua源碼分析學習教程是本文要介紹的內容,主要來了解LUA源碼的使用方法。Lua首先將源程序編譯成為字節碼,然后交由虛擬機解釋執行。對于每一個函數,Lua的編譯器將創建一個原型(prototype),它由一組指令及其使用到的常量組成[1]。最初的Lua虛擬機是基于棧的。到1993年,Lua5.0版本,采用了基于寄存器的虛擬機,使得Lua的解釋效率得到提升。

體系結構與指令系統

與虛擬機和指令相關的文件主要有兩個: lopcodes.c 和 lvm.c。從名稱可以看出來,這兩個文件分別用于描述操作碼(指令)和虛擬機。

首先來看指令:

Lua共有38條指令,在下面兩處地方分別描述了這些指令的名稱和模式, 如下:

  1. lopcodes.c:16  
  2. const char *const luaP_opnames[NUM_OPCODES+1] = {  
  3. "MOVE",  
  4. "LOADK",  
  5. "LOADBOOL",  
  6. "LOADNIL",  
  7. "GETUPVAL",  
  8. "GETGLOBAL",  
  9. "GETTABLE",  
  10. "SETGLOBAL",  
  11. "SETUPVAL",  
  12. "SETTABLE",  
  13. "NEWTABLE",  
  14. "SELF",  
  15. "ADD",  
  16. "SUB",  
  17. "MUL",  
  18. "DIV",  
  19. "MOD",  
  20. "POW",  
  21. "UNM",  
  22. "NOT",  
  23. "LEN",  
  24. "CONCAT",  
  25. "JMP",  
  26. "EQ",  
  27. "LT",  
  28. "LE",  
  29. "TEST",  
  30. "TESTSET",  
  31. "CALL",  
  32. "TAILCALL",  
  33. "RETURN",  
  34. "FORLOOP",  
  35. "FORPREP",  
  36. "TFORLOOP",  
  37. "SETLIST",  
  38. "CLOSE",  
  39. "CLOSURE",  
  40. "VARARG",  
  41. NULL  
  42. };  
  43.  
  44. #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m))  
  45.  
  46. const lu_byte luaP_opmodes[NUM_OPCODES] = {  
  47. /*       T A    B       C     mode           opcode    */  
  48. opmode(0, 1, OpArgR, OpArgN, iABC)         /* OP_MOVE */  
  49. ,opmode(0, 1, OpArgK, OpArgN, iABx)        /* OP_LOADK */  
  50. ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_LOADBOOL */  
  51. ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_LOADNIL */  
  52. ,opmode(0, 1, OpArgU, OpArgN, iABC)        /* OP_GETUPVAL */  
  53. ,opmode(0, 1, OpArgK, OpArgN, iABx)        /* OP_GETGLOBAL */  
  54. ,opmode(0, 1, OpArgR, OpArgK, iABC)        /* OP_GETTABLE */  
  55. ,opmode(0, 0, OpArgK, OpArgN, iABx)        /* OP_SETGLOBAL */  
  56. ,opmode(0, 0, OpArgU, OpArgN, iABC)        /* OP_SETUPVAL */  
  57. ,opmode(0, 0, OpArgK, OpArgK, iABC)        /* OP_SETTABLE */  
  58. ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_NEWTABLE */  
  59. ,opmode(0, 1, OpArgR, OpArgK, iABC)        /* OP_SELF */  
  60. ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_ADD */  
  61. ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_SUB */  
  62. ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_MUL */  
  63. ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_DIV */  
  64. ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_MOD */  
  65. ,opmode(0, 1, OpArgK, OpArgK, iABC)        /* OP_POW */  
  66. ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_UNM */  
  67. ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_NOT */  
  68. ,opmode(0, 1, OpArgR, OpArgN, iABC)        /* OP_LEN */  
  69. ,opmode(0, 1, OpArgR, OpArgR, iABC)        /* OP_CONCAT */  
  70. ,opmode(0, 0, OpArgR, OpArgN, iAsBx)        /* OP_JMP */  
  71. ,opmode(1, 0, OpArgK, OpArgK, iABC)        /* OP_EQ */  
  72. ,opmode(1, 0, OpArgK, OpArgK, iABC)        /* OP_LT */  
  73. ,opmode(1, 0, OpArgK, OpArgK, iABC)        /* OP_LE */  
  74. ,opmode(1, 1, OpArgR, OpArgU, iABC)        /* OP_TEST */  
  75. ,opmode(1, 1, OpArgR, OpArgU, iABC)        /* OP_TESTSET */  
  76. ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_CALL */  
  77. ,opmode(0, 1, OpArgU, OpArgU, iABC)        /* OP_TAILCALL */  
  78. ,opmode(0, 0, OpArgU, OpArgN, iABC)        /* OP_RETURN */  
  79. ,opmode(0, 1, OpArgR, OpArgN, iAsBx)        /* OP_FORLOOP */  
  80. ,opmode(0, 1, OpArgR, OpArgN, iAsBx)        /* OP_FORPREP */  
  81. ,opmode(1, 0, OpArgN, OpArgU, iABC)        /* OP_TFORLOOP */  
  82. ,opmode(0, 0, OpArgU, OpArgU, iABC)        /* OP_SETLIST */  
  83. ,opmode(0, 0, OpArgN, OpArgN, iABC)        /* OP_CLOSE */  
  84. ,opmode(0, 1, OpArgU, OpArgN, iABx)        /* OP_CLOSURE */  
  85. ,opmode(0, 1, OpArgU, OpArgN, iABC)        /* OP_VARARG */  
  86. }; 

前面一個數組容易理解,表示了每條指令的名稱。后面一個數組表示的是指令的模式。奇怪的符號讓人有些費解。在看模式之前, 首先來看Lua指令的格式,如圖:

詳解關于Lua源碼分析學習教程

如上圖, Lua的指令可以分成三種形式. 即在上面的模式數組中也可以看到的iABC, iABx 和 iAsBx. 對于三種形式的指令來說, 前兩部分都是一樣的, 分別是6位的操作碼和8位A操作數; 區別在于, 后面部是分割成為兩個長度為9位的操作符(B, C),一個無符號的18位操作符Bx還是有符號的18位操作符sBx. 這些定義的代碼如下:

  1. lopcodes.c : 34  
  2. /*  
  3. ** size and position of opcode arguments.  
  4. */  
  5. #define SIZE_C        9  
  6. #define SIZE_B        9  
  7. #define SIZE_Bx        (SIZE_C + SIZE_B)  
  8. #define SIZE_A        8  
  9.  
  10. #define SIZE_OP        6  
  11.  
  12. #define POS_OP        0  
  13. #define POS_A        (POS_OP + SIZE_OP)  
  14. #define POS_C        (POS_A + SIZE_A)  
  15. #define POS_B        (POS_C + SIZE_C)  
  16. #define POS_Bx        POS_C 

再來看指令的操作模式, Lua使用一個字節來表示指令的操作模式. 具體的含義如下:

1、使用最高位來表示是否是一條測試指令. 之所以將這一類型的指令特別地標識出來, 是因為Lua的指令長度是32位,對于分支指令來說, 要想在這32位中既表示兩個操作數來做比較, 同時還要表示一個跳轉的地址, 是很困難的. 因此將這種指令分成兩條, 第一條是測試指令, 緊接著一條無條件跳轉. 如果判斷條件成立則將PC(Program Counter, 指示下一條要執行的指令)加一, 跳過下一條無條件跳轉指令, 繼續執行; 否則跳轉.

2、第二位用于表示A操作數是否被設置

3、接下來的二位用于表示操作數B的格式,OpArgN表示操作數未被使用, OpArgU表示操作數被使用(立即數?), OpArgR表示表示操作數是寄存器或者跳轉的偏移量, OpArgK表示操作數是寄存器或者常量.

最后, 給出Lua虛擬機的體系結構圖(根據源代碼分析得出):

詳解關于Lua源碼分析學習教程

首先, 我們注意到, Lua的解釋器還是一個以棧為中心的結構. 在lua_State這個結構中,有許多個字段用于描述這個結構.stack用于指向絕對棧底, 而base指向了當前正在執行的函數的第一個參數, 而top指向棧頂的第一個空元素.

我們可以看到,這個體系結構中并沒有獨立出來的寄存器. 從以下代碼來看:

  1. lvm.c:343  
  2. #define RA(i)    (base+GETARG_A(i))  
  3. /* to be used after possible stack reallocation */  
  4. #define RB(i)    check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i))  
  5. #define RC(i)    check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i))  
  6. #define RKB(i)    check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \  
  7.     ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i))  
  8. #define RKC(i)    check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \  
  9.     ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i))  
  10. #define KBx(i)    check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) 

當指令操作數的類型是寄存器時,它的內容是以base為基址在棧上的索引值.如圖所示.寄存器實際是base之上棧元素的別名;當指令操作數的類型的常數時, 它首先判斷B操作數的最位是否為零.如果是零,則按照和寄存器的處理方法一樣做,如果不是零,則在常數表中找相應的值.

我們知道Lua中函數的執行過程是這樣的. 首先將函數壓棧,然后依次將參數壓棧,形成圖中所示的棧的內容. 因此R[0]到R[n]也分別表示了Arg[1]到Arg[N+1].在第一個參數之下,就是當前正在執行的函數,對于Lua的函數(相對C函數)來說,它是指向類型為 Prototype的TValue, 在Prototype中字段code指向了一個數組用來表示組成這個函數的所有指令,字段k指向一個數組來表示這個函數使用到的所有常量.最后,Lua在解釋執行過程中有專門的變量pc來指向下一條要執行的指令.

指令解釋器

有了前面對指令格式和體系結構的介紹,現在我們可以進入正題, 來看看Lua的指令是如何執行的了.主函數如下:

  1. lvm.c:373  
  2. void luaV_execute (lua_State *L, int nexeccalls) {  
  3. LClosure *cl;  
  4. StkId base;  
  5. TValue *k;  
  6. const Instruction *pc;  
  7. reentry: /* entry point */  
  8. lua_assert(isLua(L->ci));  
  9. pc = L->savedpc;  
  10. cl = &clvalue(L->ci->func)->l;  
  11. base = L->base;  
  12. k = cl->p->k; 

這是最開始的初始化過程.其中, pc被初始化成為了L->savedpc,base被初始化成為了L->base, 即程序從L->savedpc開始執行 (在下一篇專題中,將會介紹到 L->savedpc在函數調用的預處理過程中指向了當前函數的code),而L->base指向棧中當前函數的下一個位置.cl表示當前正在執行閉包(當前可以理解成為函數),k指向當前閉包的常量表.

接下來(注意,為了專注主要邏輯, 我將其中用于Debugger支持,斷言等代碼省略了):

  1. /* main loop of interpreter */  
  2. for (;;) {  
  3.     const Instruction i = *pc++;  
  4.     StkId ra;  
  5.     /* 省略Debugger支持和Coroutine支持*/  
  6.     /* warning!! several calls may realloc the stack and invalidate `ra' */  
  7.     ra = RA(i);  
  8.     /* 省略斷言 */  
  9.     switch (GET_OPCODE(i)) { 

進入到解釋器的主循環,處理很簡單,取得當前指令,pc遞增,初始化ra,然后根據指令的操作碼進行選擇. 接下來的代碼是什么樣的, 估計大家都能想到,一大串的case來指示每條指令的執行.具體的實現可以參考源碼, 在這里不對每一條指令展開, 只是對其中有主要的幾類指令進行說明:

傳值類的指令,與MOVE為代表:

  1. lvm.c:403  
  2.       case OP_MOVE: {  
  3.         setobjs2s(L, ra, RB(i));  
  4.         continue;  
  5.       }  
  6. lopcodes:154  
  7. OP_MOVE,/*    A B    R(A) :R(B)                    */  
  8. lobject.h:161  
  9. #define setobj(L,obj1,obj2) \  
  10. { const TValue *o2=(obj2); TValue *o1=(obj1); \  
  11.     o1->value = o2->value; o1->tt=o2->tt; \  
  12.     checkliveness(G(L),o1); }  
  13.  
  14. /*  
  15. ** different types of sets, according to destination  
  16. */  
  17. /* from stack to (same) stack */  
  18. #define setobjs2s    setobj 

從注釋來看, 這條指令是將操作數A,B都做為寄存器,然后將B的值給A. 而實現也是簡單明了,只使用了一句. 宏展開以后, 可以看到, R[A],R[B]的類型是TValue, 只是將這兩域的值傳過來即可. 對于可回收對象來說,真實值不會保存在棧上,所以只是改了指針,而對于非可回收對象來說,則是直接將值從R[B]賦到R[A].

數值運算類指令,與ADD為代表:

  1. lvm.c:470  
  2.       case OP_ADD: {  
  3.         arith_op(luai_numadd, TM_ADD);  
  4.         continue;  
  5.       }  
  6. lvm.c:360  
  7. #define arith_op(op,tm) { \  
  8.         TValue *rb = RKB(i); \  
  9.         TValue *rc = RKC(i); \  
  10.         if (ttisnumber(rb) && ttisnumber(rc)) { \  
  11.           lua_Number nb = nvalue(rb), nc = nvalue(rc); \  
  12.           setnvalue(ra, op(nb, nc)); \  
  13.         } \  
  14.         else \  
  15.           Protect(Arith(L, ra, rb, rc, tm)); \  
  16.       }  
  17. lopcodes.c:171  
  18. OP_ADD,/*    A B C    R(A) :RK(B) + RK(C)                */ 

如果兩個操作數都是數值的話,關鍵的一行是:

  1. setnvalue(ra,op(nb,nc)); 

即兩個操作數相加以后,把值賦給R[A].值得注意的是,操作數B,C都是RK, 即可能是寄存器也可能是常量,這最決于最B和C的最高位是否為1,如果是1,則是常量,反之則是寄存器.具體可以參考宏ISK的實現.

如果兩個操作數不是數值,即調用了Arith函數,它嘗試將兩個操作轉換成數值進行計算,如果無法轉換,則使用元表機制.該函數的實現如下:

  1. lvm.c:313  
  2. static void Arith (lua_State *L, StkId ra, const TValue *rb,  
  3.                    const TValue *rc, TMS op) {  
  4. TValue tempb, tempc;  
  5. const TValue *b, *c;  
  6. if ((b = luaV_tonumber(rb, &tempb)) != NULL &&  
  7.       (c = luaV_tonumber(rc, &tempc)) != NULL) {  
  8.     lua_Number nb = nvalue(b), nc = nvalue(c);  
  9.     switch (op) {  
  10.       case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break;  
  11.       case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break;  
  12.       case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break;  
  13.       case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break;  
  14.       case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break;  
  15.       case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break;  
  16.       case TM_UNM: setnvalue(ra, luai_numunm(nb)); break;  
  17.       default: lua_assert(0); break;  
  18.     }  
  19. }  
  20. else if (!call_binTM(L, rb, rc, ra, op))  
  21.     luaG_aritherror(L, rb, rc);  

在上面call_binTM用于調用到元表中的元方法,因為在Lua以前的版本中元方法也被叫做tag method, 所以函數最后是以TM結尾的.

  1. lvm:163  
  2. static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2,  
  3.                        StkId res, TMS event) {  
  4. const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */  
  5. if (ttisnil(tm))  
  6.     tm = luaT_gettmbyobj(L, p2, event); /* try second operand */  
  7. if (!ttisfunction(tm)) return 0;  
  8. callTMres(L, res, tm, p1, p2);  
  9. return 1;  

在 這個函數中,試著從二個操作數中找到其中一個操作數的元方法(第一個操作數優先), 這里event表示具體哪一個元方法,找到了之后,再使用函數callTMres()去調用相應的元方法. callTMres()的實現很簡單,只是將元方法,第一,第二操作數先后壓棧,再調用并取因返回值.具體如下:

  1. lvm.c:82  
  2. static void callTMres (lua_State *L, StkId res, const TValue *f,  
  3.                         const TValue *p1, const TValue *p2) {  
  4. ptrdiff_t result = savestack(L, res);  
  5. setobj2s(L, L->top, f); /* push function */  
  6. setobj2s(L, L->top+1, p1); /* 1st argument */  
  7. setobj2s(L, L->top+2, p2); /* 2nd argument */  
  8. luaD_checkstack(L, 3);  
  9. L->top += 3;  
  10. luaD_call(L, L->top - 3, 1);  
  11. res = restorestack(L, result);  
  12. L->top--;  
  13. setobjs2s(L, res, L->top);  

邏輯運算類指令,與EQ為代表:

  1. lvm.c:541  
  2.       case OP_EQ: {  
  3.         TValue *rb = RKB(i);  
  4.         TValue *rc = RKC(i);  
  5.         Protect(  
  6.           if (equalobj(L, rb, rc) == GETARG_A(i))  
  7.             dojump(L, pc, GETARG_sBx(*pc));  
  8.         )  
  9.         pc++;  
  10.         continue;  
  11.       }  
  12. lopcodes.c:185  
  13. OP_EQ,/*    A B C    if ((RK(B) == RK(C)) ~= A) then pc++        */ 

在這條指令實現的過程中,equalobj與之前的算術運算類似,讀者可以自行分析.關鍵看它是如果實現中跳轉的,如果RK[B]==RK[C]并且A為1 的情況下(即條件為真),則會使用pc取出下一條指令,調用dojump進行跳轉,否則pc++,掛空緊接著的無條件跳轉指令. dojump的實現如下:

  1. lvm.c:354  
  2. #define dojump(L,pc,i)    {(pc) += (i); luai_threadyield(L);} 

luai_threadyield只是順序地調用lua_unlock和lua_lock,這里為釋放一次鎖,使得別的線程可以得到調度.

函數調用類指令,與CALL為代表:

  1. lvm.c:582  
  2.       case OP_CALL: {  
  3.         int b = GETARG_B(i);  
  4.         int nresults = GETARG_C(i) - 1;  
  5.         if (b != 0) L->top = ra+b; /* else previous instruction set top */  
  6.         L->savedpc = pc;  
  7.         switch (luaD_precall(L, ra, nresults)) {  
  8.           case PCRLUA: {  
  9.             nexeccalls++;  
  10.             goto reentry; /* restart luaV_execute over new Lua function */  
  11.           }  
  12.           case PCRC: {  
  13.             /* it was a C function (`precall' called it); adjust results */  
  14.             if (nresults >= 0) L->top = L->ci->top;  
  15.             base = L->base;  
  16.             continue;  
  17.           }  
  18.           default: {  
  19.             return; /* yield */  
  20.           }  
  21.         }  
  22.       }  
  23. lopcodes.c:192  
  24.  
  25. OP_CALL,/*    A B C    R(A), ... ,R(A+C-2) :R(A)(R(A+1), ... ,R(A+B-1)) */ 

這一條指令將在下一個介紹Lua函數調用規范的專題中詳細介紹. 在這里只是簡單地說明CALL指令的R[A]表示的是即將要調用的函數,而B和C則分別表示參數個數加1,和返回值個數加1. 之所以這里需要加1,其原因是:B和C使用零來表示變長的參數和變長的返回值,而實際參數個數就向后推了一個.

指令的介紹就先到此為止了, 其它的指令的實現也比較類似.仔細閱讀源碼就可很容易地分析出它的意義來. 下一篇將是一個專題, 詳細地介紹Lua中函數的調用是如何實現的.

小結:詳解關于Lua源碼分析學習教程的內容介紹完了,希望通過本文的學習能對你有所幫助!

責任編輯:zhaolei 來源: 互聯網
相關推薦

2011-08-24 15:42:38

LUA源代碼

2011-08-25 16:20:33

Lua腳本變量

2011-08-23 17:06:03

2011-08-23 15:34:56

Lua模式 匹配

2011-08-24 14:14:13

LUA環境 配置

2011-08-24 11:03:33

LUA環境 安裝

2011-08-23 16:37:05

Lua數學庫

2011-08-24 15:34:44

MinGWLua環境配置

2011-09-02 13:51:00

PhoneGap框架HTML5

2011-08-24 17:09:35

LUA閉包函數

2011-08-24 11:08:09

Lua

2011-08-25 10:07:24

Lua 5.0函數編譯器

2011-08-31 10:20:26

MTK驅動開發

2011-08-24 13:27:07

Lua 游戲C接口腳本

2011-08-24 16:59:59

LuaModule

2011-08-23 16:48:41

Lua 5.1API 函數

2011-08-23 13:54:10

LUA全局變量

2011-08-24 14:33:14

LUA開發環境Decoda

2011-08-25 14:03:32

UbuntuLUA安裝

2011-08-25 17:25:55

LUADelphi
點贊
收藏

51CTO技術棧公眾號

青青草一区二区三区| 九九综合久久| 精品久久久久久久久中文字幕 | 久久精品国产欧美激情| 好吊操视频这里只有精品| 蜜桃av.网站在线观看| 中文子幕无线码一区tr| 成人午夜电影在线播放| 色屁屁影院www国产高清麻豆| 免费欧美激情| 欧美一区二区不卡视频| 播放灌醉水嫩大学生国内精品| 午夜国产福利在线| 99久久婷婷国产综合精品电影| 国产精品91久久久久久| 欧美日韩激情在线观看| 精品国产一区二区三区四区| 日韩欧美色电影| 国产精品一区二区羞羞答答| 男女在线观看视频| 国产精品久久三| 鲁鲁狠狠狠7777一区二区| 911美女片黄在线观看游戏| 亚洲在线网站| 久久免费高清视频| 三级黄色在线观看| 精品国产一区二区三区| 亚洲精品国产精品乱码不99按摩| www.久久久久久久久久久| 亚洲啊v在线| 一区二区三区产品免费精品久久75| 日韩福利视频| 日本黄在线观看| 成人国产一区二区三区精品| 亚洲伊人久久综合| 亚洲视频在线免费播放| 久久久国产亚洲精品| 91av免费观看91av精品在线| 精品无码免费视频| 午夜精品久久99蜜桃的功能介绍| 在线成人激情黄色| 久久久久久久毛片| 久久不见久久见中文字幕免费 | 欧美视频中文在线看| 国产精品无码免费专区午夜| 久操视频在线免费播放| 国产精品久久久久久户外露出| 欧美日韩最好看的视频| 亚洲欧洲视频在线观看| 97久久精品人人做人人爽50路| av噜噜色噜噜久久| 亚洲国产精品无码久久| 国产69精品一区二区亚洲孕妇| 91免费福利视频| 国产精品爽爽久久久久久| 久久99精品一区二区三区| 国产精品夜间视频香蕉| 国产一区二区女内射| 国产一区二区视频在线| 91免费观看| 囯产精品久久久久久| 岛国精品在线观看| 国产免费一区二区| 婷婷综合激情网| 2021中文字幕一区亚洲| 欧美二区在线| 超碰免费在线观看| 日韩理论在线观看| www.日本三级| 97人澡人人添人人爽欧美| 精品福利视频导航| 亚洲欧美另类动漫| 久久精品资源| 欧美mv日韩mv国产网站app| 成人欧美精品一区二区| 亚洲伊人春色| 日韩中文字幕在线免费观看| 青草影院在线观看| 国产日韩欧美一区| 国产精品久久二区| www香蕉视频| 91热门视频在线观看| 午夜视频久久久| 在线观看操人| 色婷婷综合久久久久中文一区二区| 网站一区二区三区| 日韩综合一区二区三区| 精品视频在线播放免| 欧日韩不卡视频| 一区视频在线看| 国产精品旅馆在线| 成人精品在线播放| 国产调教视频一区| 日韩一级特黄毛片| 88xx成人免费观看视频库| 欧美一级免费观看| www.日本高清| 亚洲成av人电影| 69av在线视频| 国产xxxx在线观看| 久久久久久久久久久久久久久99| 亚洲综合av一区| 888av在线视频| 欧美久久一区二区| 91精品人妻一区二区| 最新精品国产| 国产精品日韩在线观看| 无码精品视频一区二区三区| 最新国产成人在线观看| 激情综合网婷婷| 51vv免费精品视频一区二区| 色久欧美在线视频观看| 亚洲伊人成人网| 国产精品99精品久久免费| 精品亚洲欧美日韩| 日本大胆在线观看| 欧美另类videos死尸| 一本色道久久综合亚洲精品图片| 欧美深夜福利| 91精品啪aⅴ在线观看国产| 国产在线超碰| 欧美日在线观看| 四虎成人免费视频| 欧美69视频| 国产精品一二三在线| 免费在线视频你懂得| 亚洲成人午夜影院| 又黄又色的网站| 亚洲电影影音先锋| 国产精品免费网站| 精品99又大又爽又硬少妇毛片| 午夜精品一区在线观看| 无码国产精品一区二区高潮| 一区二区三区四区在线观看国产日韩 | 欧美亚洲愉拍一区二区| brazzers精品成人一区| 99re国产精品| 狠狠色综合色区| 福利写真视频网站在线| 日韩精品一区二区三区三区免费| a级片在线观看免费| 国内精品在线播放| 天天成人综合网| 久久69av| 色综合老司机第九色激情| 国产喷水福利在线视频| 中文字幕亚洲不卡| 男人午夜视频在线观看| 欧美激情视频一区二区三区在线播放 | 国产精品热久久久久夜色精品三区| 欧洲av无码放荡人妇网站| 亚洲动漫精品| 国产精品老女人精品视频| 成人免费在线观看| 欧美精品日韩综合在线| 精品在线观看一区| 国产一区视频在线看| 黄色一级大片免费| 欧美色图婷婷| 日韩暖暖在线视频| 99se视频在线观看| 欧美老女人在线| 国产av 一区二区三区| 国产电影一区二区三区| av女优在线播放| 偷拍视屏一区| 国产精品夜间视频香蕉| a级在线观看| 亚洲精品aⅴ中文字幕乱码| 国产成人亚洲欧洲在线| 久久久不卡网国产精品二区| 国产精品拍拍拍| 亚洲最大黄网| 精品国产中文字幕| 欧美天堂一区| 欧美精品videofree1080p| 丝袜视频国产在线播放| 欧美色图12p| 九九热只有精品| 91婷婷韩国欧美一区二区| 天天色综合天天色| 欧美色图首页| 视频一区视频二区视频三区视频四区国产 | www.免费av| 奇米影视一区二区三区| 欧妇女乱妇女乱视频| 国产精品自拍区| 亚洲www视频| 成人欧美大片| 久热国产精品视频| 亚州视频一区二区三区| 欧美一区永久视频免费观看| 成人免费区一区二区三区| 国产精品色婷婷久久58| 理论片大全免费理伦片| 久久国产精品色婷婷| 黄色三级中文字幕| 成人影视亚洲图片在线| 国产精品国色综合久久| 热久久久久久| 97精品免费视频| 中文在线免费| 中文字幕av一区二区三区谷原希美| 亚洲第一成人av| 欧美午夜精品久久久| 欧美精品亚洲精品日韩精品| 国产精品―色哟哟| 欧美多人猛交狂配| 成人黄色一级视频| 一级网站在线观看| 免费在线视频一区| 成人在线观看黄| 在线观看不卡| 五月天在线免费视频| 精品国产一区二区三区四区| 精品视频高清无人区区二区三区| 国产欧美88| 国产精品自拍视频| 高清电影一区| 91wwwcom在线观看| 91高清视频在线观看| 欧美激情高清视频| 直接在线观看的三级网址| 日韩视频免费看| 超碰免费97在线观看| 亚洲老头同性xxxxx| 天天干天天爱天天操| 日韩午夜电影在线观看| 国产精选久久久| 7878成人国产在线观看| 中日韩在线观看视频| 欧美视频13p| 久久久久久久久影院| 午夜影院久久久| 久久精品免费在线| 亚洲一区在线播放| 精品一区二区三区人妻| 亚洲精品国产a久久久久久| 在线免费观看亚洲视频| 亚洲欧美另类久久久精品2019| 国产传媒免费在线观看| 综合在线观看色| 免费在线观看黄色小视频| 亚洲欧洲三级电影| 亚洲av鲁丝一区二区三区| 亚洲精品视频在线| 国产av无码专区亚洲av毛网站| 亚洲免费高清视频在线| 久草视频免费在线| 午夜精品福利在线| 日本三级一区二区| 日韩欧美国产免费播放| 欧美高清69hd| 欧美日韩成人综合| 国产精品亚洲欧美在线播放| 日韩视频在线观看一区二区| 亚洲美女综合网| 精品性高朝久久久久久久| 九九在线视频| 啊v视频在线一区二区三区| 99热国产在线中文| 久久久亚洲国产| 在线精品亚洲欧美日韩国产| 国产精品美女主播| 国产精品亚洲四区在线观看| 成人自拍网站| 亚洲视频分类| 黄色a级在线观看| 欧美视频网站| www.四虎成人| 久草精品在线观看| 午夜免费福利影院| 国产亚洲婷婷免费| 国产黄在线免费观看| 亚洲国产精品自拍| 无码视频一区二区三区| 欧美一区二区播放| 蜜桃成人在线视频| 久久精品久久久久久| av漫画网站在线观看| 国产成人在线一区| 国产一区二区三区免费观看在线| 国产日韩欧美一区二区三区四区| 奇米狠狠一区二区三区| 男人草女人视频| 久久精品首页| 国产成人精品综合久久久久99| 99久久精品免费看| 潘金莲一级黄色片| 黄色精品一区二区| 一级特黄色大片| 亚洲国产精品高清久久久| 在线观看免费网站黄| 久久久久久亚洲精品不卡| 日本在线中文字幕一区二区三区| 亚洲综合日韩中文字幕v在线| 亚洲三级网页| 欧美在线观看视频免费| 三级欧美在线一区| 色哟哟视频在线| 国产精品成人免费在线| 特级毛片www| 精品久久久久久久久久久院品网 | 99热这里只有精品66| 亚洲免费av网址| 日韩另类在线| 国产在线播放不卡| 精品久久综合| 成人在线免费观看av| 国产九色精品成人porny| 我想看黄色大片| 懂色aⅴ精品一区二区三区蜜月| av一区二区三| 中文字幕亚洲一区二区三区| 成年美女黄网站色大片不卡| aaa级精品久久久国产片| 亚洲一区二区三区| 一区二区三区 欧美| 久久久久久夜精品精品免费| 国产精品99re| 精品久久人人做人人爽| 91三级在线| 91精品视频观看| 国产精品99视频| 爱情岛论坛亚洲首页入口章节| 91丨九色丨尤物| 在线观看黄网站| 日韩av在线电影网| a级片免费在线观看| 成人自拍视频网站| 欧美日韩四区| 污网站免费观看| 亚洲成在人线免费| 免费国产羞羞网站视频| 欧美精品久久久久久久久| 日韩有吗在线观看| 欧美久久久久久久久久久久久久| 精品午夜一区二区三区在线观看| 国产中文字幕久久| 欧美日本国产视频| 米奇精品一区二区三区| 国产主播精品在线| 91精品国产调教在线观看| 婷婷激情综合五月天| 亚洲视频一二三区| www.爱爱.com| 欧美激情视频播放| 老司机成人在线| 久久久免费视频网站| 国产午夜精品久久久久久久| 欧美亚洲另类小说| 中文字幕久久精品| 在线高清欧美| 久久精品xxx| 91麻豆国产精品久久| 销魂美女一区二区| 色婷婷综合成人| 精品一区二区三区四区五区| 亚洲熟妇无码av在线播放| 成人sese在线| 无码人妻久久一区二区三区| 在线播放日韩专区| 涩爱av色老久久精品偷偷鲁| 欧美人成在线观看| 久久久久99精品国产片| 中文字幕一区二区免费| 精品中文字幕在线2019| 加勒比视频一区| 成人在线激情网| 亚洲色图视频免费播放| 国产精品一区二区av白丝下载| 久久久久中文字幕2018| 国产精品欧美日韩一区| 黄色小视频免费网站| 亚洲一区二区三区四区在线| 色视频在线观看| 成人网址在线观看| 亚洲作爱视频| 日本少妇aaa| 日韩电影大片中文字幕| 欧美aaaaaa| 久久久亚洲精品无码| 中文字幕久久午夜不卡| 亚洲精品中文字幕成人片 | 美脚丝袜脚交一区二区| 久久久99精品免费观看不卡| 国产欧美一级片| 欧美综合在线第二页| 欧美在线日韩| 亚洲精品国产91| 欧美tickling网站挠脚心| 国精产品一区一区三区四川| 国产精品videossex国产高清| 久久久精品人体av艺术| www.国产.com| 国产精品视频久久久久| 亚洲国产专区校园欧美| chinese全程对白| 国产一区二区三区在线观看视频 | 精品一区免费av|