Browse Source

DUALNUM: Handle integer type in x86/x64 interpreter and libraries.

Mike Pall 14 years ago
parent
commit
cead25f928
16 changed files with 2601 additions and 1898 deletions
  1. 703 642
      src/buildvm_x64.h
  2. 569 516
      src/buildvm_x64win.h
  3. 534 126
      src/buildvm_x86.dasc
  4. 631 589
      src/buildvm_x86.h
  5. 13 1
      src/lib_base.c
  6. 6 6
      src/lib_bit.c
  7. 8 1
      src/lib_io.c
  8. 37 3
      src/lib_math.c
  9. 1 1
      src/lib_package.c
  10. 34 2
      src/lib_string.c
  11. 39 2
      src/lj_lib.c
  12. 6 0
      src/lj_lib.h
  13. 15 4
      src/lj_meta.c
  14. 1 0
      src/lj_parse.c
  15. 3 4
      src/lj_str.c
  16. 1 1
      src/lj_str.h

File diff suppressed because it is too large
+ 703 - 642
src/buildvm_x64.h


File diff suppressed because it is too large
+ 569 - 516
src/buildvm_x64win.h


File diff suppressed because it is too large
+ 534 - 126
src/buildvm_x86.dasc


File diff suppressed because it is too large
+ 631 - 589
src/buildvm_x86.h


+ 13 - 1
src/lib_base.c

@@ -197,6 +197,18 @@ LJLIB_ASM(tonumber)		LJLIB_REC(.)
 #if LJ_HASFFI
     if (tviscdata(o)) {
       CTState *cts = ctype_cts(L);
+      if (LJ_DUALNUM) {
+	CType *ct = ctype_raw(cts, cdataV(o)->typeid);
+	if (ctype_isinteger_or_bool(ct->info)) {
+	  int64_t i;
+	  lj_cconv_ct_tv(cts, ctype_get(cts, CTID_INT64), (uint8_t *)&i, o, 0);
+	  if ((ct->size == 8 && (ct->info & CTF_UNSIGNED)) ?
+	      (uint64_t)i <= 0x7fffffffu : checki32(i)) {
+	    setintV(L->base-1, (int32_t)i);
+	    return FFH_RES(1);
+	  }  /* else: retry and convert to double. */
+	}
+      }
       lj_cconv_ct_tv(cts, ctype_get(cts, CTID_DOUBLE),
 		     (uint8_t *)&(L->base-1)->n, o, 0);
       return FFH_RES(1);
@@ -294,7 +306,7 @@ LJLIB_ASM(pairs)
 LJLIB_NOREGUV LJLIB_ASM(ipairs_aux)	LJLIB_REC(.)
 {
   lj_lib_checktab(L, 1);
-  lj_lib_checknum(L, 2);
+  lj_lib_checkint(L, 2);
   return FFH_UNREACHABLE;
 }
 

+ 6 - 6
src/lib_bit.c

@@ -21,7 +21,7 @@
 
 LJLIB_ASM(bit_tobit)		LJLIB_REC(bit_unary IR_TOBIT)
 {
-  lj_lib_checknum(L, 1);
+  lj_lib_checknumber(L, 1);
   return FFH_RETRY;
 }
 LJLIB_ASM_(bit_bnot)		LJLIB_REC(bit_unary IR_BNOT)
@@ -29,8 +29,8 @@ LJLIB_ASM_(bit_bswap)		LJLIB_REC(bit_unary IR_BSWAP)
 
 LJLIB_ASM(bit_lshift)		LJLIB_REC(bit_shift IR_BSHL)
 {
-  lj_lib_checknum(L, 1);
-  lj_lib_checknum(L, 2);
+  lj_lib_checknumber(L, 1);
+  lj_lib_checkbit(L, 2);
   return FFH_RETRY;
 }
 LJLIB_ASM_(bit_rshift)		LJLIB_REC(bit_shift IR_BSHR)
@@ -41,7 +41,7 @@ LJLIB_ASM_(bit_ror)		LJLIB_REC(bit_shift IR_BROR)
 LJLIB_ASM(bit_band)		LJLIB_REC(bit_nary IR_BAND)
 {
   int i = 0;
-  do { lj_lib_checknum(L, ++i); } while (L->base+i < L->top);
+  do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top);
   return FFH_RETRY;
 }
 LJLIB_ASM_(bit_bor)		LJLIB_REC(bit_nary IR_BOR)
@@ -51,8 +51,8 @@ LJLIB_ASM_(bit_bxor)		LJLIB_REC(bit_nary IR_BXOR)
 
 LJLIB_CF(bit_tohex)
 {
-  uint32_t b = (uint32_t)lj_num2bit(lj_lib_checknum(L, 1));
-  int32_t i, n = L->base+1 >= L->top ? 8 : lj_num2bit(lj_lib_checknum(L, 2));
+  uint32_t b = (uint32_t)lj_lib_checkbit(L, 1);
+  int32_t i, n = L->base+1 >= L->top ? 8 : lj_lib_checkbit(L, 2);
   const char *hexdigits = "0123456789abcdef";
   char buf[8];
   if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }

+ 8 - 1
src/lib_io.c

@@ -137,6 +137,13 @@ static int io_file_readnum(lua_State *L, FILE *fp)
 {
   lua_Number d;
   if (fscanf(fp, LUA_NUMBER_SCAN, &d) == 1) {
+    if (LJ_DUALNUM) {
+      int32_t i = lj_num2int(d);
+      if (d == (lua_Number)i && !tvismzero((cTValue *)&d)) {
+	setintV(L->top++, i);
+	return 1;
+      }
+    }
     setnumV(L->top++, d);
     return 1;
   } else {
@@ -217,7 +224,7 @@ static int io_file_read(lua_State *L, FILE *fp, int start)
 	  io_file_readchars(L, fp, ~((size_t)0));
 	else
 	  lj_err_arg(L, n+1, LJ_ERR_INVFMT);
-      } else if (tvisnum(L->base+n)) {
+      } else if (tvisnumber(L->base+n)) {
 	size_t len = (size_t)lj_lib_checkint(L, n+1);
 	ok = len ? io_file_readchars(L, fp, len) : io_file_testeof(L, fp);
       } else {

+ 37 - 3
src/lib_math.c

@@ -21,12 +21,17 @@
 
 LJLIB_ASM(math_abs)		LJLIB_REC(.)
 {
-  lj_lib_checknum(L, 1);
+  lj_lib_checknumber(L, 1);
   return FFH_RETRY;
 }
 LJLIB_ASM_(math_floor)		LJLIB_REC(math_round IRFPM_FLOOR)
 LJLIB_ASM_(math_ceil)		LJLIB_REC(math_round IRFPM_CEIL)
-LJLIB_ASM_(math_sqrt)		LJLIB_REC(math_unary IRFPM_SQRT)
+
+LJLIB_ASM(math_sqrt)		LJLIB_REC(math_unary IRFPM_SQRT)
+{
+  lj_lib_checknum(L, 1);
+  return FFH_RETRY;
+}
 LJLIB_ASM_(math_log)		LJLIB_REC(math_unary IRFPM_LOG)
 LJLIB_ASM_(math_log10)		LJLIB_REC(math_unary IRFPM_LOG10)
 LJLIB_ASM_(math_exp)		LJLIB_REC(math_unary IRFPM_EXP)
@@ -61,7 +66,7 @@ LJLIB_ASM_(math_fmod)
 LJLIB_ASM(math_min)		LJLIB_REC(math_minmax IR_MIN)
 {
   int i = 0;
-  do { lj_lib_checknum(L, ++i); } while (L->base+i < L->top);
+  do { lj_lib_checknumber(L, ++i); } while (L->base+i < L->top);
   return FFH_RETRY;
 }
 LJLIB_ASM_(math_max)		LJLIB_REC(math_minmax IR_MAX)
@@ -137,13 +142,42 @@ LJLIB_CF(math_random)		LJLIB_REC(.)
   u.u64 = lj_math_random_step(rs);
   d = u.d - 1.0;
   if (n > 0) {
+#if LJ_DUALNUM
+    int isint = 1;
+    double r1;
+    lj_lib_checknumber(L, 1);
+    if (tvisint(L->base)) {
+      r1 = (lua_Number)intV(L->base);
+    } else {
+      isint = 0;
+      r1 = numV(L->base);
+    }
+#else
     double r1 = lj_lib_checknum(L, 1);
+#endif
     if (n == 1) {
       d = floor(d*r1) + 1.0;  /* d is an int in range [1, r1] */
     } else {
+#if LJ_DUALNUM
+      double r2;
+      lj_lib_checknumber(L, 2);
+      if (tvisint(L->base+1)) {
+	r2 = (lua_Number)intV(L->base+1);
+      } else {
+	isint = 0;
+	r2 = numV(L->base+1);
+      }
+#else
       double r2 = lj_lib_checknum(L, 2);
+#endif
       d = floor(d*(r2-r1+1.0)) + r1;  /* d is an int in range [r1, r2] */
     }
+#if LJ_DUALNUM
+    if (isint) {
+      setintV(L->top-1, lj_num2int(d));
+      return 1;
+    }
+#endif
   }  /* else: d is a double in range [0, 1] */
   setnumV(L->top++, d);
   return 1;

+ 1 - 1
src/lib_package.c

@@ -217,7 +217,7 @@ static const char *searchpath (lua_State *L, const char *name,
   lua_pushliteral(L, "");  /* error accumulator */
   while ((path = pushnexttemplate(L, path)) != NULL) {
     const char *filename = luaL_gsub(L, lua_tostring(L, -1),
-                                     LUA_PATH_MARK, name);
+				     LUA_PATH_MARK, name);
     lua_remove(L, -2);  /* remove path template */
     if (readable(filename))  /* does file exist and is readable? */
       return filename;  /* return that file name */

+ 34 - 2
src/lib_string.c

@@ -702,6 +702,38 @@ static void addintlen(char *form)
   form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0';
 }
 
+static unsigned LUA_INTFRM_T num2intfrm(lua_State *L, int arg)
+{
+  if (sizeof(LUA_INTFRM_T) == 4) {
+    return (LUA_INTFRM_T)lj_lib_checkbit(L, arg);
+  } else {
+    cTValue *o;
+    lj_lib_checknumber(L, arg);
+    o = L->base+arg-1;
+    if (tvisint(o))
+      return (LUA_INTFRM_T)intV(o);
+    else
+      return (LUA_INTFRM_T)numV(o);
+  }
+}
+
+static unsigned LUA_INTFRM_T num2uintfrm(lua_State *L, int arg)
+{
+  if (sizeof(LUA_INTFRM_T) == 4) {
+    return (unsigned LUA_INTFRM_T)lj_lib_checkbit(L, arg);
+  } else {
+    cTValue *o;
+    lj_lib_checknumber(L, arg);
+    o = L->base+arg-1;
+    if (tvisint(o))
+      return (unsigned LUA_INTFRM_T)intV(o);
+    else if ((int32_t)o->u32.hi < 0)
+      return (unsigned LUA_INTFRM_T)(LUA_INTFRM_T)numV(o);
+    else
+      return (unsigned LUA_INTFRM_T)numV(o);
+  }
+}
+
 LJLIB_CF(string_format)
 {
   int arg = 1;
@@ -726,11 +758,11 @@ LJLIB_CF(string_format)
 	break;
       case 'd':  case 'i':
 	addintlen(form);
-	sprintf(buff, form, (LUA_INTFRM_T)lj_lib_checknum(L, arg));
+	sprintf(buff, form, num2intfrm(L, arg));
 	break;
       case 'o':  case 'u':  case 'x':  case 'X':
 	addintlen(form);
-	sprintf(buff, form, (unsigned LUA_INTFRM_T)lj_lib_checknum(L, arg));
+	sprintf(buff, form, num2uintfrm(L, arg));
 	break;
       case 'e':  case 'E': case 'f': case 'g': case 'G': {
 	TValue tv;

+ 39 - 2
src/lj_lib.c

@@ -151,13 +151,29 @@ GCstr *lj_lib_optstr(lua_State *L, int narg)
   return (o < L->top && !tvisnil(o)) ? lj_lib_checkstr(L, narg) : NULL;
 }
 
+#if LJ_DUALNUM
+void lj_lib_checknumber(lua_State *L, int narg)
+{
+  TValue *o = L->base + narg-1;
+  if (!(o < L->top &&
+	(tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o)))))
+    lj_err_argt(L, narg, LUA_TNUMBER);
+}
+#endif
+
 lua_Number lj_lib_checknum(lua_State *L, int narg)
 {
   TValue *o = L->base + narg-1;
   if (!(o < L->top &&
 	(tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o)))))
     lj_err_argt(L, narg, LUA_TNUMBER);
-  return numberVnum(o);
+  if (LJ_UNLIKELY(tvisint(o))) {
+    lua_Number n = (lua_Number)intV(o);
+    setnumV(o, n);
+    return n;
+  } else {
+    return numV(o);
+  }
 }
 
 int32_t lj_lib_checkint(lua_State *L, int narg)
@@ -166,7 +182,13 @@ int32_t lj_lib_checkint(lua_State *L, int narg)
   if (!(o < L->top &&
 	(tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o)))))
     lj_err_argt(L, narg, LUA_TNUMBER);
-  return numberVint(o);
+  if (LJ_LIKELY(tvisint(o))) {
+    return intV(o);
+  } else {
+    int32_t i = lj_num2int(numV(o));
+    if (LJ_DUALNUM) setintV(o, i);
+    return i;
+  }
 }
 
 int32_t lj_lib_optint(lua_State *L, int narg, int32_t def)
@@ -175,6 +197,21 @@ int32_t lj_lib_optint(lua_State *L, int narg, int32_t def)
   return (o < L->top && !tvisnil(o)) ? lj_lib_checkint(L, narg) : def;
 }
 
+int32_t lj_lib_checkbit(lua_State *L, int narg)
+{
+  TValue *o = L->base + narg-1;
+  if (!(o < L->top &&
+	(tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o)))))
+    lj_err_argt(L, narg, LUA_TNUMBER);
+  if (LJ_LIKELY(tvisint(o))) {
+    return intV(o);
+  } else {
+    int32_t i = lj_num2bit(numV(o));
+    if (LJ_DUALNUM) setintV(o, i);
+    return i;
+  }
+}
+
 GCfunc *lj_lib_checkfunc(lua_State *L, int narg)
 {
   TValue *o = L->base + narg-1;

+ 6 - 0
src/lj_lib.h

@@ -33,9 +33,15 @@
 LJ_FUNC TValue *lj_lib_checkany(lua_State *L, int narg);
 LJ_FUNC GCstr *lj_lib_checkstr(lua_State *L, int narg);
 LJ_FUNC GCstr *lj_lib_optstr(lua_State *L, int narg);
+#if LJ_DUALNUM
+LJ_FUNC void lj_lib_checknumber(lua_State *L, int narg);
+#else
+#define lj_lib_checknumber(L, narg)	lj_lib_checknum((L), (narg))
+#endif
 LJ_FUNC lua_Number lj_lib_checknum(lua_State *L, int narg);
 LJ_FUNC int32_t lj_lib_checkint(lua_State *L, int narg);
 LJ_FUNC int32_t lj_lib_optint(lua_State *L, int narg, int32_t def);
+LJ_FUNC int32_t lj_lib_checkbit(lua_State *L, int narg);
 LJ_FUNC GCfunc *lj_lib_checkfunc(lua_State *L, int narg);
 LJ_FUNC GCtab *lj_lib_checktab(lua_State *L, int narg);
 LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg);

+ 15 - 4
src/lj_meta.c

@@ -385,10 +385,21 @@ void lj_meta_call(lua_State *L, TValue *func, TValue *top)
 }
 
 /* Helper for FORI. Coercion. */
-void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *base)
+void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o)
 {
-  if (!str2num(base, base)) lj_err_msg(L, LJ_ERR_FORINIT);
-  if (!str2num(base+1, base+1)) lj_err_msg(L, LJ_ERR_FORLIM);
-  if (!str2num(base+2, base+2)) lj_err_msg(L, LJ_ERR_FORSTEP);
+  if (!(tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o))))
+    lj_err_msg(L, LJ_ERR_FORINIT);
+  if (!(tvisnumber(o+1) || (tvisstr(o+1) && lj_str_tonumber(strV(o+1), o+1))))
+    lj_err_msg(L, LJ_ERR_FORLIM);
+  if (!(tvisnumber(o+2) || (tvisstr(o+2) && lj_str_tonumber(strV(o+2), o+2))))
+    lj_err_msg(L, LJ_ERR_FORSTEP);
+#if LJ_DUALNUM
+  /* Ensure all slots are integers or all slots are numbers. */
+  if (!(tvisint(o) && tvisint(o+1) && tvisint(o+2))) {
+    if (tvisint(o)) setnumV(o, (lua_Number)intV(o));
+    if (tvisint(o+1)) setnumV(o+1, (lua_Number)intV(o+1));
+    if (tvisint(o+2)) setnumV(o+2, (lua_Number)intV(o+2));
+  }
+#endif
 }
 

+ 1 - 0
src/lj_parse.c

@@ -935,6 +935,7 @@ static void bcemit_unop(FuncState *fs, BCOp op, ExpDesc *e)
 	    setnumV(o, -(lua_Number)k);
 	  else
 	    setintV(o, -k);
+	  return;
 	} else {
 	  o->u64 ^= U64x(80000000,00000000);
 	  return;

+ 3 - 4
src/lj_str.c

@@ -187,7 +187,7 @@ int LJ_FASTCALL lj_str_tonumber(GCstr *str, TValue *n)
 int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n)
 {
 #if LJ_DUALNUM
-  int sign = 0;
+  int sign = 1;
 #else
   lua_Number sign = 1;
 #endif
@@ -216,7 +216,7 @@ int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n)
     while (LJ_UNLIKELY(lj_char_isspace(*p))) p++;
     if (LJ_LIKELY(*p == '\0')) {
 #if LJ_DUALNUM
-      if (!sign) {
+      if (sign == 1) {
 	if (k < 0x80000000u) {
 	  setintV(n, (int32_t)k);
 	  return 1;
@@ -225,10 +225,9 @@ int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n)
 	setintV(n, -(int32_t)k);
 	return 1;
       }
-#else
+#endif
       setnumV(n, sign * (lua_Number)k);
       return 1;
-#endif
     }
   }
 parsedbl:

+ 1 - 1
src/lj_str.h

@@ -27,7 +27,7 @@ LJ_FUNC size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o);
 LJ_FUNC char * LJ_FASTCALL lj_str_bufint(char *p, int32_t k);
 LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np);
 LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k);
-LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o);
+LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o);
 
 #define LJ_STR_INTBUF		(1+10)
 #define LJ_STR_NUMBUF		LUAI_MAXNUMBER2STR

Some files were not shown because too many files changed in this diff