⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ljit_x86.dasc

📁 采用C语言写的Lua的解释器的代码!Lua不用介绍了吧
💻 DASC
📖 第 1 页 / 共 5 页
字号:
    |  mov L->top, TOP  }  /* Otherwise keep TOP for next instruction. */}static void jit_op_tailcall(jit_State *J, int func, int nargs){  int cltype;  if (!fhint_isset(J, NOCLOSE)) {  /* May need to close open upvalues. */    |  call &luaF_close, L, BASE  }  cltype = jit_inline_call(J, func, nargs, -2);  if (cltype < 0) goto finish;  /* Inlined? */  if (cltype == LUA_TFUNCTION) {    jit_deopt_target(J, nargs);    |  isfunction func    |  jne L_DEOPTIMIZE			// TYPE hint was wrong?  } else {    |  isfunction func; jne >5		// Handle generic callables first.    |.tail    |5:  // Fallback for generic callables.    |  addidx BASE, func    if (nargs >= 0) {      |  lea TOP, BASE[1+nargs]    }    |  mov edx, &J->nextins    |  jmp ->METATAILCALL    |.code    |.jsub METATAILCALL			// TAILCALL to __call metamethod.    |  mov L->savedpc, edx    |  mov L->top, TOP    |  call &luaD_tryfuncTM, L, BASE	// Resolve __call metamethod.    |    |// Relocate [eax, L->top) -> [L->ci->func, *).    |  mov CI, L->ci    |  mov edx, L->top    |  mov TOP, CI->func    |1:    |  mov BASE, [eax]    |  add eax, aword*1    |  mov [TOP], BASE    |  add TOP, aword*1    |  cmp eax, edx    |  jb <1    |    |  mov BASE, CI->func    |  mov LCL, BASE->value    |  sub CI, #CI    |  add esp, FRAME_OFFSET    |  jmp aword LCL->jit_gate		// Chain to callgate.    |.endjsub  }  if (nargs >= 0) {  /* Previous op was not open and did not set TOP. */    int i;    /* Relocate [BASE+func, BASE+func+nargs] -> [ci->func, ci->func+nargs]. */    /* TODO: loop for large nargs? */    if (!J->pt->is_vararg) {  /* Fixarg function. */      |  mov LCL, BASE[func].value      for (i = 0; i < nargs; i++) {	|  copyslot BASE[i], BASE[func+1+i], ecx, edx      }      |  lea TOP, BASE[nargs]      |   sub BASE, #BASE      |  mov CI, L->ci      |  mov BASE->value, LCL		// Sufficient to copy func->value.    } else {  /* Vararg function. */      |   mov CI, L->ci      |  lea TOP, BASE[func]      |   mov BASE, CI->func      |  mov LCL, TOP->value      |  mov BASE->value, LCL		// Sufficient to copy func->value.      for (i = 0; i < nargs; i++) {	|  copyslot BASE[i+1], TOP[i+1], eax, edx      }      |  lea TOP, BASE[1+nargs]      |  mov LCL, BASE->value		// Need to reload LCL = eax.    }  } else {  /* Previous op was open and set TOP. */    |// Relocate [BASE+func, TOP) -> [ci->func, *).    |  mov CI, L->ci    |  addidx BASE, func    |  mov edx, CI->func    |1:    |  mov eax, [BASE]    |  add BASE, aword*1    |  mov [edx], eax    |  add edx, aword*1    |  cmp BASE, TOP    |  jb <1    |  mov BASE, CI->func    |  mov TOP, edx			// Relocated TOP.    |  mov LCL, BASE->value  }  |  sub CI, #CI  |  add esp, FRAME_OFFSET  |  jmp aword LCL->jit_gate		// Chain to JIT function.finish:  J->combine++;  /* Combine with following return instruction. */}/* ------------------------------------------------------------------------ */static void jit_op_move(jit_State *J, int dest, int src){  |  copyslot BASE[dest], BASE[src]}static void jit_op_loadk(jit_State *J, int dest, int kidx){  const TValue *kk = &J->pt->k[kidx];  int rk = jit_return_k(J);  if (rk) dest = 0;  |  copyconst BASE[dest], kk  if (rk) {    |  ret  }}static void jit_op_loadnil(jit_State *J, int first, int last){  int idx, num = last - first + 1;  int rk = jit_return_k(J);  |  xor eax, eax  // Assumes: LUA_TNIL == 0  if (rk) {    |  settt BASE[0], eax    |  ret  } else if (num <= 8) {    for (idx = first; idx <= last; idx++) {      |  settt BASE[idx], eax  // 3/6 bytes    }  } else {    |  lea ecx, BASE[first].tt  // 15-21 bytes    |  lea edx, BASE[last].tt    |1:    |  mov [ecx], eax    |  cmp ecx, edx    |  lea ecx, [ecx+#BASE]  // Preserves CC.    |  jbe <1  }}static void jit_op_loadbool(jit_State *J, int dest, int b, int dojump){  int rk = jit_return_k(J);  if (rk) dest = 0;  |  setbvalue BASE[dest], b  if (rk) {    |  ret  } else if (dojump) {    const TValue *h = hint_getpc(J, COMBINE, J->nextpc);    if (!(ttisboolean(h) && bvalue(h) == 0)) {  /* Avoid jmp around dead ins. */      |  jmp =>J->nextpc+1    }  }}/* ------------------------------------------------------------------------ */static void jit_op_getupval(jit_State *J, int dest, int uvidx){  |  getLCL  |  mov UPVAL:ecx, LCL->upvals[uvidx]  |  mov TOP, UPVAL:ecx->v  |  copyslot BASE[dest], TOP[0]}static void jit_op_setupval(jit_State *J, int src, int uvidx){  |  getLCL  |  mov UPVAL:ecx, LCL->upvals[uvidx]  |  mov TOP, UPVAL:ecx->v  |  // This is really copyslot TOP[0], BASE[src] with compare mixed in.  |   mov eax, BASE[src].tt  |   mov GCOBJECT:edx, BASE[src].value  |   mov TOP->tt, eax  |  cmp eax, LUA_TSTRING				// iscollectable(val)?  |   mov eax, BASE[src].value.na[1]  |   mov TOP->value, GCOBJECT:edx  |   mov TOP->value.na[1], eax  |  jae >5  |4:  |.tail  |5:  |  test byte GCOBJECT:edx->gch.marked, WHITEBITS	// && iswhite(val)  |  jz <4  |  test byte UPVAL:ecx->marked, bitmask(BLACKBIT)	// && isblack(uv)  |  jz <4  |  call ->BARRIERF					// Yes, need barrier.  |  jmp <4  |.code  |.jsub BARRIERF			// luaC_barrierf() with regparms.  |  mov ARG4, GCOBJECT:edx  |  mov ARG3, UPVAL:ecx  |  mov ARG2, L  |  jmp &luaC_barrierf			// Chain to C code.  |.endjsub}/* ------------------------------------------------------------------------ *//* Optimized table lookup routines. Enter via jsub, fallback to C. *//* Fallback for GETTABLE_*. Temporary key is in L->env. */static void jit_gettable_fb(lua_State *L, Table *t, StkId dest){  Table *mt = t->metatable;  const TValue *tm = luaH_getstr(mt, G(L)->tmname[TM_INDEX]);  if (ttisnil(tm)) {  /* No __index method? */    mt->flags |= 1<<TM_INDEX;  /* Cache this fact. */    setnilvalue(dest);  } else if (ttisfunction(tm)) {  /* __index function? */    ptrdiff_t destr = savestack(L, dest);    setobj2s(L, L->top, tm);    sethvalue(L, L->top+1, t);    setobj2s(L, L->top+2, &L->env);    luaD_checkstack(L, 3);    L->top += 3;    luaD_call(L, L->top - 3, 1);    dest = restorestack(L, destr);    L->top--;    setobjs2s(L, dest, L->top);  } else {  /* Let luaV_gettable() continue with the __index object. */    luaV_gettable(L, tm, &L->env, dest);  }  |//-----------------------------------------------------------------------  |.jsub GETGLOBAL			// Lookup global variable.  |// Call with: TSTRING:edx (key), BASE (dest)  |  mov CI, L->ci  |  mov TOP, CI->func  |  mov LCL, TOP->value  |  mov TABLE:edi, LCL->env  |  jmp >9  |.endjsub  |  |//-----------------------------------------------------------------------  |.jsub GETTABLE_KSTR			// Lookup constant string in table.  |// Call with: TOP (tab), TSTRING:edx (key), BASE (dest)  |  cmp dword TOP->tt, LUA_TTABLE  |   mov TABLE:edi, TOP->value  |  jne ->DEOPTIMIZE_CALLER		// Not a table? Deoptimize.  |  |// Common entry: TABLE:edi (tab), TSTRING:edx (key), BASE (dest)  |// Restores BASE, destroys eax, ecx, edx, edi (TOP).  |9:  |  movzx ecx, byte TABLE:edi->lsizenode	// hashstr(t, key).  |  mov eax, 1  |  shl eax, cl  |  dec eax  |  and eax, TSTRING:edx->tsv.hash  |  Nodemul NODE:eax  |  add NODE:eax, TABLE:edi->node  |  |1:  // Start of inner loop. Check node key.  |  cmp dword NODE:eax->i_key.nk.tt, LUA_TSTRING  |  jne >2  |  cmp aword NODE:eax->i_key.nk.value, TSTRING:edx  |  jne >2  |  // Note: swapping the two checks is faster, but valgrind complains.  |// Assumes: (int)&(((Node *)0)->i_val) == (int)&(((StkId)0)->value)  |  |// Ok, key found. Copy node value to destination (stack) slot.  |  mov ecx, NODE:eax->i_val.tt  |  test ecx, ecx; je >3			// Node has nil value?  ||if (J->flags & JIT_F_CPU_SSE2) {  |  movq xmm0, qword NODE:eax->i_val.value  |  movq qword BASE->value, xmm0  ||} else {  |  mov edx, NODE:eax->i_val.value  |  mov edi, NODE:eax->i_val.value.na[1]  |  mov BASE->value, edx  |  mov BASE->value.na[1], edi  ||}  |  mov BASE->tt, ecx  |  mov BASE, L->base  |  ret  |2:  |  mov NODE:eax, NODE:eax->i_key.nk.next	// Get next key in chain.  |  test NODE:eax, NODE:eax  |  jnz <1					// Loop if non-NULL.  |  |  xor ecx, ecx  |3:  |  mov TABLE:eax, TABLE:edi->metatable  |  test TABLE:eax, TABLE:eax  |  jz >4					// No metatable?  |  test byte TABLE:eax->flags, 1<<TM_INDEX  |  jz >5					// Or 'no __index' flag set?  |4:  |  settt BASE[0], ecx				// Yes, set to nil.  |  mov BASE, L->base  |  ret  |  |5:  // Otherwise chain to C code which eventually calls luaV_gettable.  |  setsvalue L->env, TSTRING:edx		// Use L->env as temp key.  |  mov ecx, [esp]  |  sub esp, FRAME_OFFSET  |  mov L->savedpc, ecx  |  call &jit_gettable_fb, L, TABLE:edi, BASE  |  add esp, FRAME_OFFSET  |  mov BASE, L->base  |  ret  |.endjsub  |  |//-----------------------------------------------------------------------  |.jsub GETTABLE_STR			// Lookup string in table.  |// Call with: TOP (tab), TVALUE:ecx (key), BASE (dest)  |  mov eax, TOP->tt; shl eax, 4; or eax, TVALUE:ecx->tt  |  cmp eax, LUA_TTABLE_STR  |   mov TABLE:edi, TOP->value  |   mov TSTRING:edx, TVALUE:ecx->value  |  je <9					// Types ok? Continue above.  |  jmp ->DEOPTIMIZE_CALLER		// Otherwise deoptimize.  |.endjsub}/* Fallback for SETTABLE_*STR. Temporary (string) key is in L->env. */static void jit_settable_fb(lua_State *L, Table *t, StkId val){  Table *mt = t->metatable;  const TValue *tm = luaH_getstr(mt, G(L)->tmname[TM_NEWINDEX]);  if (ttisnil(tm)) {  /* No __newindex method? */    mt->flags |= 1<<TM_NEWINDEX;  /* Cache this fact. */    t->flags = 0;  /* But need to clear the cache for the table itself. */    setobj2t(L, luaH_setstr(L, t, rawtsvalue(&L->env)), val);    luaC_barriert(L, t, val);  } else if (ttisfunction(tm)) {  /* __newindex function? */    setobj2s(L, L->top, tm);    sethvalue(L, L->top+1, t);    setobj2s(L, L->top+2, &L->env);    setobj2s(L, L->top+3, val);    luaD_checkstack(L, 4);    L->top += 4;    luaD_call(L, L->top - 4, 0);  } else {  /* Let luaV_settable() continue with the __newindex object. */    luaV_settable(L, tm, &L->env, val);  }  |//-----------------------------------------------------------------------  |.jsub BARRIERBACK			// luaC_barrierback() with regparms.  |// Call with: TABLE:edi (table). Destroys ecx, edx.  |  mov GL:ecx, L->l_G  |   and byte TABLE:edi->marked, (~bitmask(BLACKBIT))&0xff  |  mov edx, GL:ecx->grayagain  |   mov GL:ecx->grayagain, TABLE:edi  |  mov TABLE:edi->gclist, edx  |  ret  |.endjsub  |  |//-----------------------------------------------------------------------  |.jsub SETGLOBAL			// Set global variable.  |// Call with: TSTRING:edx (key), BASE (val)  |  mov CI, L->ci  |  mov TOP, CI->func  |  mov LCL, TOP->value  |  mov TABLE:edi, LCL->env  |  jmp >9  |.endjsub  |  |//-----------------------------------------------------------------------  |.jsub SETTABLE_KSTR			// Set constant string entry in table.  |// Call with: TOP (tab), TSTRING:edx (key), BASE (val)  |  cmp dword TOP->tt, LUA_TTABLE  |   mov TABLE:edi, TOP->value  |  jne ->DEOPTIMIZE_CALLER		// Not a table? Deoptimize.  |  |// Common entry: TABLE:edi (tab), TSTRING:edx (key), BASE (val)  |// Restores BASE, destroys eax, ecx, edx, edi (TOP).  |9:  |  movzx ecx, byte TABLE:edi->lsizenode	// hashstr(t, key).  |  mov eax, 1  |  shl eax, cl  |  dec eax  |  and eax, TSTRING:edx->tsv.hash  |  Nodemul NODE:eax  |  add NODE:eax, TABLE:edi->node  |  |1:  // Start of inner loop. Check node key.  |  cmp dword NODE:eax->i_key.nk.tt, LUA_TSTRING  |  jne >4  |  cmp aword NODE:eax->i_key.nk.value, TSTRING:edx  |  jne >4  |  // Note: swapping the two checks is faster, but valgrind complains.  |  |// Ok, key found. Copy new value to node value.  |  cmp dword NODE:eax->i_val.tt, LUA_TNIL	// Previous value is nil?  |  je >6  |  // Assumes: (int)&(((Node *)0)->i_val) == (int)&(((StkId)0)->value)  |2:  |  mov byte TABLE:edi->flags, 0		// Clear metamethod cache.  |3:  // Target for SETTABLE_NUM below.  |  test byte TABLE:edi->marked, bitmask(BLACKBIT)  // isblack(table)  |  jnz >8				// Unlikely, but set barrier back.  |7:  // Caveat: recycled label.  |  copyslot TVALUE:eax[0], BASE[0], ecx, edx, TOP  |  mov BASE, L->base  |  ret  |  |8:  // Avoid valiswhite() check -- black2gray(table) is ok.  |  call ->BARRIERBACK  |  jmp <7  |  |4:  |  mov NODE:eax, NODE:eax->i_key.nk.next	// Get next key in chain.  |  test NODE:eax, NODE:eax  |  jnz <1					// Loop if non-NULL.  |  |// Key not found. Add a new one, but check metatable first.  |  mov TABLE:ecx, TABLE:edi->metatable  |  test TABLE:ecx, TABLE:ecx  |  jz >5					// No metatable?  |  test byte TABLE:ecx->flags, 1<<TM_NEWINDEX  |  jz >7					// Or 'no __newindex' flag set?  |  |5:  // Add new key.  |  // No need for setting L->savedpc since only LUA_ERRMEM may be thrown.  |  lea TVALUE:eax, L->env  |  setsvalue TVALUE:eax[0], TSTRING:edx  |  sub esp, FRAME_OFFSET

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -