瀏覽代碼

FFI: Record 64 bit integer comparisons and pointer comparisons.

Mike Pall 14 年之前
父節點
當前提交
f385af7084
共有 4 個文件被更改,包括 49 次插入28 次删除
  1. 9 8
      src/lib_ffi.c
  2. 1 1
      src/lj_asm.c
  3. 38 19
      src/lj_crecord.c
  4. 1 0
      src/lj_record.c

+ 9 - 8
src/lib_ffi.c

@@ -157,14 +157,13 @@ static int ffi_arith_ptr(lua_State *L, CTState *cts, FFIArith *fa, MMS mm)
 	return 1;
       }
     }
-    if (!((mm == MM_add || mm == MM_sub) &&
-	  ctype_isnum(fa->ct[1]->info))) return 0;
+    if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(fa->ct[1]->info)))
+      return 0;
     lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), fa->ct[1],
 		   (uint8_t *)&idx, fa->p[1], 0);
     if (mm == MM_sub) idx = -idx;
-  } else if (mm == MM_add &&
+  } else if (mm == MM_add && ctype_isnum(ctp->info) &&
       (ctype_isptr(fa->ct[1]->info) || ctype_isrefarray(fa->ct[1]->info))) {
-    if (!ctype_isnum(ctp->info)) return 0;
     /* Swap pointer and index. */
     ctp = fa->ct[1]; pp = fa->p[1];
     lj_cconv_ct_ct(cts, ctype_get(cts, CTID_INT_PSZ), fa->ct[0],
@@ -264,8 +263,10 @@ static int ffi_arith(lua_State *L)
   FFIArith fa;
   MMS mm = (MMS)(curr_func(L)->c.ffid - (int)FF_ffi_meta___eq + (int)MM_eq);
   if (ffi_checkarith(L, cts, &fa)) {
-    if (ffi_arith_int64(L, cts, &fa, mm) || ffi_arith_ptr(L, cts, &fa, mm))
+    if (ffi_arith_int64(L, cts, &fa, mm) || ffi_arith_ptr(L, cts, &fa, mm)) {
+      copyTV(L, &G(L)->tmptv2, L->top-1);  /* Remember for trace recorder. */
       return 1;
+    }
   }
   /* NYI: per-cdata metamethods. */
   {
@@ -319,7 +320,7 @@ LJLIB_CF(ffi_meta___newindex)	LJLIB_REC(cdata_index 1)
 }
 
 /* The following functions must be in contiguous ORDER MM. */
-LJLIB_CF(ffi_meta___eq)
+LJLIB_CF(ffi_meta___eq)		LJLIB_REC(cdata_arith MM_eq)
 {
   return ffi_arith(L);
 }
@@ -329,12 +330,12 @@ LJLIB_CF(ffi_meta___len)
   return ffi_arith(L);
 }
 
-LJLIB_CF(ffi_meta___lt)
+LJLIB_CF(ffi_meta___lt)		LJLIB_REC(cdata_arith MM_lt)
 {
   return ffi_arith(L);
 }
 
-LJLIB_CF(ffi_meta___le)
+LJLIB_CF(ffi_meta___le)		LJLIB_REC(cdata_arith MM_le)
 {
   return ffi_arith(L);
 }

+ 1 - 1
src/lj_asm.c

@@ -2927,7 +2927,7 @@ static void asm_comp_(ASMState *as, IRIns *ir, int cc)
     IROp leftop = (IROp)(IR(lref)->o);
     Reg r64 = REX_64IR(ir, 0);
     int32_t imm = 0;
-    lua_assert(irt_isint(ir->t) || irt_isaddr(ir->t));
+    lua_assert(irt_is64(ir->t) || irt_isint(ir->t) || irt_isaddr(ir->t));
     /* Swap constants (only for ABC) and fusable loads to the right. */
     if (irref_isk(lref) || (!irref_isk(rref) && opisfusableload(leftop))) {
       if ((cc & 0xc) == 0xc) cc ^= 3;  /* L <-> G, LE <-> GE */

+ 38 - 19
src/lj_crecord.c

@@ -663,7 +663,20 @@ static TRef crec_arith_int64(jit_State *J, TRef *sp, CType **s, MMS mm)
 	sp[i] = emitconv(sp[i], dt, IRT_INT,
 			 ((st - IRT_I8) & 1) ? 0 : IRCONV_SEXT);
     }
-    if (mm == MM_pow) {
+    if (mm < MM_add) {
+      /* Assume true comparison. Fixup and emit pending guard later. */
+      IROp op;
+      if (mm == MM_eq) {
+	op = IR_EQ;
+      } else {
+	op = mm == MM_lt ? IR_LT : IR_LE;
+	if (dt == IRT_U64)
+	  op += (IR_ULT-IR_LT);
+      }
+      lj_ir_set(J, IRTG(op, dt), sp[0], sp[1]);
+      J->postproc = LJ_POST_FIXGUARD;
+      return TREF_TRUE;
+    } else if (mm == MM_pow) {
       tr = lj_ir_call(J, IRCALL_lj_cdata_powi64, sp[0], sp[1],
 		      lj_ir_kint(J, (int)dt-(int)IRT_I64));
     } else {
@@ -683,35 +696,41 @@ static TRef crec_arith_ptr(jit_State *J, TRef *sp, CType **s, MMS mm)
 {
   CTState *cts = ctype_ctsG(J2G(J));
   CType *ctp = s[0];
-  CTSize sz;
-  if (!(mm == MM_add || mm == MM_sub))
-    return 0;
-  if (ctype_ispointer(ctp->info)) {
-    sz = lj_ctype_size(cts, ctype_cid(ctp->info));
-    if (mm == MM_sub && ctype_ispointer(s[1]->info)) {
-      /* Pointer difference. */
-      TRef tr;
-      if (sz == 0 || (sz & (sz-1)) != 0)
-	return 0;  /* NYI: integer division. */
-      tr = emitir(IRT(IR_SUB, IRT_PTR), sp[0], sp[1]);
-      tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz)));
+  if (ctype_isptr(ctp->info) || ctype_isrefarray(ctp->info)) {
+    if ((mm == MM_sub || mm == MM_eq || mm == MM_lt || mm == MM_le) &&
+	(ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) {
+      if (mm == MM_sub) {  /* Pointer difference. */
+	TRef tr;
+	CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
+	if (sz == 0 || (sz & (sz-1)) != 0)
+	  return 0;  /* NYI: integer division. */
+	tr = emitir(IRT(IR_SUB, IRT_PTR), sp[0], sp[1]);
+	tr = emitir(IRT(IR_BSAR, IRT_INTP), tr, lj_ir_kint(J, lj_fls(sz)));
 #if LJ_64
-      tr = emitconv(tr, IRT_NUM, IRT_INTP, 0);
+	tr = emitconv(tr, IRT_NUM, IRT_INTP, 0);
 #endif
-      return tr;
+	return tr;
+      } else {  /* Pointer comparison (unsigned). */
+	/* Assume true comparison. Fixup and emit pending guard later. */
+	IROp op = mm == MM_eq ? IR_EQ : mm == MM_lt ? IR_ULT : IR_ULE;
+	lj_ir_set(J, IRTG(op, IRT_PTR), sp[0], sp[1]);
+	J->postproc = LJ_POST_FIXGUARD;
+	return TREF_TRUE;
+      }
     }
-    if (!ctype_isnum(s[1]->info)) return 0;
-  } else if (mm == MM_add &&
-	     ctype_isnum(ctp->info) && ctype_ispointer(s[1]->info)) {
+    if (!((mm == MM_add || mm == MM_sub) && ctype_isnum(s[1]->info)))
+      return 0;
+  } else if (mm == MM_add && ctype_isnum(ctp->info) &&
+	     (ctype_isptr(s[1]->info) || ctype_isrefarray(s[1]->info))) {
     TRef tr = sp[0]; sp[0] = sp[1]; sp[1] = tr;  /* Swap pointer and index. */
     ctp = s[1];
-    sz = lj_ctype_size(cts, ctype_cid(ctp->info));
   } else {
     return 0;
   }
   {
     TRef tr = sp[1];
     IRType t = tref_type(tr);
+    CTSize sz = lj_ctype_size(cts, ctype_cid(ctp->info));
     CTypeID id;
 #if LJ_64
     if (t == IRT_NUM || t == IRT_FLOAT)

+ 1 - 0
src/lj_record.c

@@ -819,6 +819,7 @@ static void rec_mm_comp(jit_State *J, RecordIndex *ix, int op)
 /* Setup call to cdata comparison metamethod. */
 static void rec_mm_comp_cdata(jit_State *J, RecordIndex *ix, int op, MMS mm)
 {
+  lj_snap_add(J);
   if (tref_iscdata(ix->val)) {
     ix->tab = ix->val;
     copyTV(J->L, &ix->tabv, &ix->valv);