mirror of
https://github.com/LuaJIT/LuaJIT.git
synced 2025-02-07 15:14:08 +00:00
DUALNUM: Handle integer type in x86/x64 interpreter and libraries.
This commit is contained in:
parent
c031d4b6a0
commit
cead25f928
3234
src/buildvm_x64.h
3234
src/buildvm_x64.h
File diff suppressed because it is too large
Load Diff
3222
src/buildvm_x64win.h
3222
src/buildvm_x64win.h
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3529
src/buildvm_x86.h
3529
src/buildvm_x86.h
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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"; }
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
41
src/lj_lib.c
41
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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user