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

This commit is contained in:
Mike Pall 2011-02-27 01:36:59 +01:00
parent c031d4b6a0
commit cead25f928
16 changed files with 6913 additions and 4238 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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;
}

View File

@ -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"; }

View File

@ -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 {

View File

@ -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;

View File

@ -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 */

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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
}

View File

@ -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;

View File

@ -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:

View File

@ -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