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

📄 ljit_x86.dasc

📁 采用C语言写的Lua的解释器的代码!Lua不用介绍了吧
💻 DASC
📖 第 1 页 / 共 5 页
字号:
  |  call &luaH_newkey, L, TABLE:edi, TVALUE:eax  |  add esp, FRAME_OFFSET  |  jmp <2  // Copy to the returned value. See Node/TValue assumption above.  |  |6:  // Key found, but previous value is nil.  |  mov TABLE:ecx, TABLE:edi->metatable  |  test TABLE:ecx, TABLE:ecx  |  jz <2					// No metatable?  |  test byte TABLE:ecx->flags, 1<<TM_NEWINDEX  |  jnz <2					// Or 'no __newindex' flag set?  |  |7:  // Otherwise chain to C code which eventually calls luaV_settable.  |  setsvalue L->env, TSTRING:edx		// Use L->env as temp key.  |  mov ecx, [esp]  |  sub esp, FRAME_OFFSET  |  mov L->savedpc, ecx  |  call &jit_settable_fb, L, TABLE:edi, BASE  |  add esp, FRAME_OFFSET  |  mov BASE, L->base  |  ret  |.endjsub  |  |//-----------------------------------------------------------------------  |.jsub SETTABLE_STR			// Set string entry in table.  |// Call with: TOP (tab), TVALUE:ecx (key), BASE (val)  |  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}/* ------------------------------------------------------------------------ */static void jit_op_newtable(jit_State *J, int dest, int lnarray, int lnhash){  |  call &luaH_new, L, luaO_fb2int(lnarray), luaO_fb2int(lnhash)  |  sethvalue BASE[dest], eax  jit_checkGC(J);}static void jit_op_getglobal(jit_State *J, int dest, int kidx){  const TValue *kk = &J->pt->k[kidx];  jit_assert(ttisstring(kk));  |  mov TSTRING:edx, &&kk->value.gc->ts  |  addidx BASE, dest  |  call ->GETGLOBAL}static void jit_op_setglobal(jit_State *J, int rval, int kidx){  const TValue *kk = &J->pt->k[kidx];  jit_assert(ttisstring(kk));  |  mov TSTRING:edx, &&kk->value.gc->ts  |  addidx BASE, rval  |  call ->SETGLOBAL}enum { TKEY_KSTR = -2, TKEY_STR = -1, TKEY_ANY = 0 };/* Optimize key lookup depending on consts or hints type. */static int jit_keylookup(jit_State *J, int tab, int rkey){  const TValue *tabt = hint_get(J, TYPE);  const TValue *key;  if (!ttistable(tabt)) return TKEY_ANY;  /* Not a table? Use fallback. */  key = ISK(rkey) ? &J->pt->k[INDEXK(rkey)] : hint_get(J, TYPEKEY);  if (ttisstring(key)) {  /* String key? */    if (ISK(rkey)) {      |  lea TOP, BASE[tab]      |  mov TSTRING:edx, &&key->value.gc->ts      return TKEY_KSTR;  /* Const string key. */    } else {      |  lea TOP, BASE[tab]      |  lea TVALUE:ecx, BASE[rkey]      return TKEY_STR;  /* Var string key. */    }  } else if (ttisnumber(key)) {  /* Number key? */    lua_Number n = nvalue(key);    int k;    lua_number2int(k, n);    if (!(k >= 1 && k < (1 << 26) && (lua_Number)k == n))      return TKEY_ANY;  /* Not a proper array key? Use fallback. */    if (ISK(rkey)) {      |  istable tab      |   mov TABLE:edi, BASE[tab].value      |  jne >9					// TYPE hint was wrong?      |  mov ecx, k				// Needed for hash fallback.      |   mov TVALUE:eax, TABLE:edi->array      |  cmp ecx, TABLE:edi->sizearray; ja >5	// Not in array part?      return k;  /* Const array key (>= 1). */    } else {      |  mov eax, BASE[tab].tt; shl eax, 4; or eax, BASE[rkey].tt      |  cmp eax, LUA_TTABLE_NUM; jne >9	// TYPE/TYPEKEY hint was wrong?      if (J->flags & JIT_F_CPU_SSE2) {	|  movsd xmm0, qword BASE[rkey]	|  cvttsd2si eax, xmm0	|  cvtsi2sd xmm1, eax	|  dec eax	|  ucomisd xmm1, xmm0	|  mov TABLE:edi, BASE[tab].value	|  jne >9; jp >9			// Not an integer? Deoptimize.      } else {	|// Annoying x87 stuff: check whether a number is an integer.	|// The latency of fist/fild is the real problem here.	|  fld qword BASE[rkey].value	|  fist dword TMP1	|  fild dword TMP1	|  fcomparepp                           // eax may be modified.	|  jne >9; jp >9			// Not an integer? Deoptimize.	|  mov eax, TMP1	|  mov TABLE:edi, BASE[tab].value	|  dec eax      }      |  cmp eax, TABLE:edi->sizearray; jae >5	// Not in array part?      |  TValuemul eax      |  add eax, TABLE:edi->array      return 1;  /* Variable array key. */    }  }  return TKEY_ANY;  /* Use fallback. */}static void jit_op_gettable(jit_State *J, int dest, int tab, int rkey){  int k = jit_keylookup(J, tab, rkey);  switch (k) {  case TKEY_KSTR:  /* Const string key. */    |  addidx BASE, dest    |  call ->GETTABLE_KSTR    break;  case TKEY_STR:  /* Variable string key. */    |  addidx BASE, dest    |  call ->GETTABLE_STR    break;  case TKEY_ANY:  /* Generic gettable fallback. */    if (ISK(rkey)) {      |  mov ecx, &&J->pt->k[INDEXK(rkey)]    } else {      |  lea ecx, BASE[rkey]    }    |  lea edx, BASE[tab]    |  addidx BASE, dest    |  mov L->savedpc, &J->nextins    |  call &luaV_gettable, L, edx, ecx, BASE    |  mov BASE, L->base    break;  default:  /* Array key. */    |// This is really copyslot BASE[dest], TVALUE:eax[k-1] mixed with compare.    |1:    |  mov edx, TVALUE:eax[k-1].tt    |  test edx, edx; je >6			// Array has nil value?    if (J->flags & JIT_F_CPU_SSE2) {      |  movq xmm0, qword TVALUE:eax[k-1].value      |  movq qword BASE[dest].value, xmm0    } else {      |  mov ecx, TVALUE:eax[k-1].value      |  mov eax, TVALUE:eax[k-1].value.na[1]      |  mov BASE[dest].value, ecx      |  mov BASE[dest].value.na[1], eax    }    |2:    |  mov BASE[dest].tt, edx    |.tail    |5:  // Fallback to hash part. TABLE:edi is callee-saved.    if (ISK(rkey)) {      |  call ->GETTABLE_KNUM    } else {      |  call ->GETTABLE_NUM    }    |  jmp <1					// Slot is at TVALUE:eax[k-1].    |    |6:  // Shortcut for tables without an __index metamethod.    |  mov TABLE:ecx, TABLE:edi->metatable    |  test TABLE:ecx, TABLE:ecx    |  jz <2					// No metatable?    |  test byte TABLE:ecx->flags, 1<<TM_INDEX    |  jnz <2					// Or 'no __index' flag set?    |    |9:  // Otherwise deoptimize.    |  mov edx, &J->nextins    |  jmp ->DEOPTIMIZE    |.code    break;  }  |.jsub GETTABLE_KNUM		// Gettable fallback for const numeric keys.  |  mov TMP2, ecx				// Save k.  |  sub esp, FRAME_OFFSET  |  call &luaH_getnum, TABLE:edi, ecx  |  add esp, FRAME_OFFSET  |  mov ecx, TMP2				// Restore k.  |  TValuemul ecx  |  sub TVALUE:eax, ecx		// Compensate for TVALUE:eax[k-1].  |  add TVALUE:eax, #TVALUE  |  ret  |.endjsub  |  |.jsub GETTABLE_NUM		// Gettable fallback for variable numeric keys.  |  inc eax  |  mov ARG2, TABLE:edi			// Really ARG1 and ARG2.  |  mov ARG3, eax  |  jmp &luaH_getnum				// Chain to C code.  |.endjsub}static void jit_op_settable(jit_State *J, int tab, int rkey, int rval){  const TValue *val = ISK(rval) ? &J->pt->k[INDEXK(rval)] : NULL;  int k = jit_keylookup(J, tab, rkey);  switch (k) {  case TKEY_KSTR:  /* Const string key. */  case TKEY_STR:  /* Variable string key. */    if (ISK(rval)) {      |  mov BASE, &val    } else {      |  addidx BASE, rval    }    if (k == TKEY_KSTR) {      |  call ->SETTABLE_KSTR    } else {      |  call ->SETTABLE_STR    }    break;  case TKEY_ANY:  /* Generic settable fallback. */    if (ISK(rkey)) {      |  mov ecx, &&J->pt->k[INDEXK(rkey)]    } else {      |  lea ecx, BASE[rkey]    }    if (ISK(rval)) {      |  mov edx, &val    } else {      |  lea edx, BASE[rval]    }    |  addidx BASE, tab    |  mov L->savedpc, &J->nextins    |  call &luaV_settable, L, BASE, ecx, edx    |  mov BASE, L->base    break;  default:  /* Array key. */    |1:    |  tvisnil TVALUE:eax[k-1]; je >6		// Previous value is nil?    |2:    |.tail    |5:  // Fallback to hash part. TABLE:edi is callee-saved.    if (ISK(rkey)) {      |  call ->SETTABLE_KNUM    } else {      |  call ->SETTABLE_NUM    }    |  jmp <1					// Slot is at TVALUE:eax[k-1].    |    |6:  // Shortcut for tables without a __newindex metamethod.    |  mov TABLE:ecx, TABLE:edi->metatable    |  test TABLE:ecx, TABLE:ecx    |  jz <2					// No metatable?    |  test byte TABLE:ecx->flags, 1<<TM_NEWINDEX    |  jnz <2					// Or 'no __newindex' flag set?    |    |9:  // Otherwise deoptimize.    |  mov edx, &J->nextins    |  jmp ->DEOPTIMIZE    |.code    if (!ISK(rval) || iscollectable(val)) {      |  test byte TABLE:edi->marked, bitmask(BLACKBIT)  // isblack(table)      |  jnz >7				// Unlikely, but set barrier back.      |3:      |.tail      |7:  // Avoid valiswhite() check -- black2gray(table) is ok.      |  call ->BARRIERBACK      |  jmp <3      |.code    }    if (ISK(rval)) {      |  copyconst TVALUE:eax[k-1], val    } else {      |  copyslot TVALUE:eax[k-1], BASE[rval], ecx, edx, TOP    }    break;  }  |.jsub SETTABLE_KNUM		// Settable fallback for const numeric keys.  |  mov TMP2, ecx				// Save k.  |  sub esp, FRAME_OFFSET  |  call &luaH_setnum, L, TABLE:edi, ecx  |  add esp, FRAME_OFFSET  |  mov ecx, TMP2				// Restore k.  |  TValuemul ecx  |  sub TVALUE:eax, ecx		// Compensate for TVALUE:eax[k-1].  |  add TVALUE:eax, #TVALUE  |  ret  |.endjsub  |  |.jsub SETTABLE_NUM		// Settable fallback for variable numeric keys.  |  inc eax  |  mov ARG2, L				// Really ARG1, ARG2 and ARG3.  |  mov ARG3, TABLE:edi  |  mov ARG4, eax  |  jmp &luaH_setnum				// Chain to C code.  |.endjsub}static void jit_op_self(jit_State *J, int dest, int tab, int rkey){  |  copyslot BASE[dest+1], BASE[tab]  jit_op_gettable(J, dest, tab, rkey);}/* ------------------------------------------------------------------------ */static void jit_op_setlist(jit_State *J, int ra, int num, int batch){  if (batch == 0) { batch = (int)(*J->nextins); J->combine++; }  batch = (batch-1)*LFIELDS_PER_FLUSH;  if (num == 0) {  /* Previous op was open and set TOP: {f()} or {...}. */    |  mov L->env.value, TOP		// Need to save TOP (edi).    |  lea eax, BASE[ra+1]    |  sub eax, TOP    |  neg eax    |  TValuediv eax			// num = (TOP-ra-1)/sizeof(TValue).    |  mov TABLE:edi, BASE[ra].value    |  jz >4				// Nothing to set?    if (batch > 0) {      |  add eax, batch    }    |  cmp dword TABLE:edi->sizearray, eax    |  jae >1				// Skip resize if not needed.    |  // A resize is likely, so inline it.    |  call &luaH_resizearray, L, TABLE:edi, eax    |1:    |  test byte TABLE:edi->marked, bitmask(BLACKBIT)  // isblack(table)    |  mov edx, TABLE:edi->array    |  jnz >6				// Unlikely, but set barrier back.    |  mov TOP, L->env.value    |    |.tail    |6:  // Avoid lots of valiswhite() checks -- black2gray(table) is ok.    |  call ->BARRIERBACK    |  jmp <1  // Need to reload edx.    |.code  } else {  /* Set fixed number of args. */    |  mov TABLE:edi, BASE[ra].value	// edi is callee-save.    |  cmp dword TABLE:edi->sizearray, batch+num    |  jb >5				// Need to resize array?    |1:    |  test byte TABLE:edi->marked, bitmask(BLACKBIT)  // isblack(table)    |  mov edx, TABLE:edi->array    |  jnz >6				// Unlikely, but set barrier back.    |  lea TOP, BASE[ra+1+num]		// Careful: TOP is edi.    |    |.tail    |5:  // A resize is unlikely (impossible?). NEWTABLE should've done it.    |  call &luaH_resizearray, L, TABLE:edi, batch+num    |  jmp <1    |6:  // Avoid lots of valiswhite() checks -- black2gray(table) is ok.    |  call ->BARRIERBACK    |  jmp <1  // Need to reload edx.    |.code  }  if (batch > 0) {    |  add edx, batch*#TVALUE		// edx = &t->array[(batch+1)-1]  }  |  lea ecx, BASE[ra+1]  |3:					// Copy stack slots to array.  |  mov eax, [ecx]  |  add ecx, aword*1  |  mov [edx], eax  |  add edx, aword*1  |  cmp ecx, TOP  |  jb <3  |  |4:  if (num == 0) {  /* Previous op was open. Restore L->top. */    |  lea TOP, BASE[J->pt->maxstacksize]  // Faster than getting L->ci->top.    |  mov L->top, TOP  }}/* ------------------------------------------------------------------------ */static void jit_op_arith(jit_State *J, int dest, int rkb, int rkc, int ev){  const TValue *kkb = ISK(rkb) ? &J->pt->k[INDEXK(rkb)] : NULL;  const TValue *kkc = ISK(rkc) ? &J->pt->k[INDEXK(rkc)] : NULL;  const Value *kval;  int idx, rev;  int target = (ev == TM_LT || ev == TM_LE) ? jit_jmp_target(J) : 0;  int hastail = 0;  /* The bytecode compiler already folds constants except for: k/0, k%0, */  /* NaN results, k1<k2, k1<=k2. No point in optimizing these cases. */  if (ISK(rkb&rkc)) goto fallback;  /* Avoid optimization when non-numeric constants are present. */  if (kkb ? !ttisnumber(kkb) : (kkc && !ttisnumber(kkc))) goto fallback;  /* The TYPE hint selects numeric inlining and/or fallback encoding. */  switch (ttype(hint_get(J, TYPE))) {  case LUA_TNIL: hastail = 1; break;  /* No hint: numeric + fallback. */  case LUA_TNUMBER: break;	      /* Numbers: numeric + deoptimization. */  default: goto fallback;	      /* Mixed/other types: fallback only. */  }  /* The checks above ensure: at most one of the operands is a constant. */  /* Reverse operation and swap operands so the 2nd operand is a variable. */  if (kkc) { kval = &kkc->value; idx = rkb; rev = 1; }  else { kval = kkb ? &kkb->value : NULL; idx = rkc; rev = 0; }  /* Special handling for some operators. */  switch (ev) {  case TM_MOD:    /* Check for modulo with positive numbers, so we can use fprem. */    if (kval) {      if (kval->na[1] < 0) { hastail = 0; goto fallback; }  /* x%-k, -k%x */      |  isnumber idx      |   mov eax, BASE[idx].value.na[1]      |  jne L_DEOPTIMIZEF      |   test eax, eax; js L_DEOPTIMIZEF      |// This will trigger deoptimization in some benchmarks (pidigits).      |// But it's still a win.      if (kkb) {

⌨️ 快捷键说明

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