DUALNUM: Add integer type to core VM.

This commit is contained in:
Mike Pall 2011-02-17 00:44:14 +01:00
parent 963f05c7e1
commit 03946ac978
23 changed files with 403 additions and 189 deletions

View File

@ -190,8 +190,8 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
int32_t base = lj_lib_optint(L, 2, 10);
if (base == 10) {
TValue *o = lj_lib_checkany(L, 1);
if (tvisnum(o) || (tvisstr(o) && lj_str_tonum(strV(o), o))) {
setnumV(L->base-1, numV(o));
if (tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o))) {
copyTV(L, L->base-1, o);
return FFH_RES(1);
}
#if LJ_HASFFI
@ -212,7 +212,10 @@ LJLIB_ASM(tonumber) LJLIB_REC(.)
if (p != ep) {
while (lj_char_isspace((unsigned char)(*ep))) ep++;
if (*ep == '\0') {
setnumV(L->base-1, cast_num(ul));
if (LJ_DUALNUM && LJ_LIKELY(ul < 0x80000000u))
setintV(L->base-1, (int32_t)ul);
else
setnumV(L->base-1, (lua_Number)ul);
return FFH_RES(1);
}
}
@ -234,8 +237,8 @@ LJLIB_ASM(tostring) LJLIB_REC(.)
return FFH_TAILCALL;
} else {
GCstr *s;
if (tvisnum(o)) {
s = lj_str_fromnum(L, &o->n);
if (tvisnumber(o)) {
s = lj_str_fromnumber(L, o);
} else if (tvispri(o)) {
s = strV(lj_lib_upvalue(L, -(int32_t)itype(o)));
} else {
@ -359,7 +362,7 @@ static const char *reader_func(lua_State *L, void *ud, size_t *size)
if (tvisnil(L->top)) {
*size = 0;
return NULL;
} else if (tvisstr(L->top) || tvisnum(L->top)) {
} else if (tvisstr(L->top) || tvisnumber(L->top)) {
copyTV(L, L->base+2, L->top); /* Anchor string in reserved stack slot. */
return lua_tolstring(L, 3, size);
} else {
@ -385,7 +388,7 @@ LJLIB_CF(dofile)
if (luaL_loadfile(L, fname ? strdata(fname) : NULL) != 0)
lua_error(L);
lua_call(L, 0, LUA_MULTRET);
return cast_int(L->top - L->base) - 1;
return (int)(L->top - L->base) - 1;
}
/* -- Base library: GC control -------------------------------------------- */
@ -402,7 +405,7 @@ LJLIB_CF(collectgarbage)
"\4stop\7restart\7collect\5count\1\377\4step\10setpause\12setstepmul");
int32_t data = lj_lib_optint(L, 2, 0);
if (opt == LUA_GCCOUNT) {
setnumV(L->top, cast_num(G(L)->gc.total)/1024.0);
setnumV(L->top, (lua_Number)G(L)->gc.total/1024.0);
} else {
int res = lua_gc(L, opt, data);
if (opt == LUA_GCSTEP)
@ -464,8 +467,13 @@ LJLIB_CF(print)
if (shortcut && tvisstr(o)) {
str = strVdata(o);
size = strV(o)->len;
} else if (shortcut && tvisint(o)) {
char buf[LJ_STR_INTBUF];
char *p = lj_str_bufint(buf, intV(o));
size = (size_t)(buf+LJ_STR_INTBUF-p);
str = p;
} else if (shortcut && tvisnum(o)) {
char buf[LUAI_MAXNUMBER2STR];
char buf[LJ_STR_NUMBUF];
size = lj_str_bufnum(buf, o);
str = buf;
} else {
@ -604,7 +612,7 @@ static void newproxy_weaktable(lua_State *L)
setgcref(t->metatable, obj2gco(t));
setstrV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "__mode")),
lj_str_newlit(L, "kv"));
t->nomm = cast_byte(~(1u<<MM_mode));
t->nomm = (uint8_t)(~(1u<<MM_mode));
}
LUALIB_API int luaopen_base(lua_State *L)

View File

@ -195,7 +195,7 @@ static int io_file_readchars(lua_State *L, FILE *fp, size_t n)
static int io_file_read(lua_State *L, FILE *fp, int start)
{
int ok, n, nargs = cast_int(L->top - L->base) - start;
int ok, n, nargs = (int)(L->top - L->base) - start;
clearerr(fp);
if (nargs == 0) {
ok = io_file_readline(L, fp);
@ -240,10 +240,15 @@ static int io_file_write(lua_State *L, FILE *fp, int start)
if (tvisstr(tv)) {
MSize len = strV(tv)->len;
status = status && (fwrite(strVdata(tv), 1, len, fp) == len);
} else if (tvisint(tv)) {
char buf[LJ_STR_INTBUF];
char *p = lj_str_bufint(buf, intV(tv));
size_t len = (size_t)(buf+LJ_STR_INTBUF-p);
status = status && (fwrite(p, 1, len, fp) == len);
} else if (tvisnum(tv)) {
status = status && (fprintf(fp, LUA_NUMBER_FMT, numV(tv)) > 0);
} else {
lj_err_argt(L, cast_int(tv - L->base) + 1, LUA_TSTRING);
lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING);
}
}
return io_pushresult(L, status, NULL);
@ -279,37 +284,42 @@ LJLIB_CF(io_method_seek)
{
FILE *fp = io_tofile(L)->fp;
int opt = lj_lib_checkopt(L, 2, 1, "\3set\3cur\3end");
lua_Number ofs;
int64_t ofs = 0;
cTValue *o;
int res;
if (opt == 0) opt = SEEK_SET;
else if (opt == 1) opt = SEEK_CUR;
else if (opt == 2) opt = SEEK_END;
lj_lib_opt(L, 3,
ofs = lj_lib_checknum(L, 3);
,
ofs = 0;
)
o = L->base+2;
if (o < L->top) {
if (tvisint(o))
ofs = (int64_t)intV(o);
else if (tvisnum(o))
ofs = (int64_t)numV(o);
else if (!tvisnil(o))
lj_err_argt(L, 3, LUA_TNUMBER);
}
#if LJ_TARGET_POSIX
res = fseeko(fp, (int64_t)ofs, opt);
res = fseeko(fp, ofs, opt);
#elif _MSC_VER >= 1400
res = _fseeki64(fp, (int64_t)ofs, opt);
res = _fseeki64(fp, ofs, opt);
#elif defined(__MINGW32__)
res = fseeko64(fp, (int64_t)ofs, opt);
res = fseeko64(fp, ofs, opt);
#else
res = fseek(fp, (long)ofs, opt);
#endif
if (res)
return io_pushresult(L, 0, NULL);
#if LJ_TARGET_POSIX
ofs = cast_num(ftello(fp));
ofs = ftello(fp);
#elif _MSC_VER >= 1400
ofs = cast_num(_ftelli64(fp));
ofs = _ftelli64(fp);
#elif defined(__MINGW32__)
ofs = cast_num(ftello64(fp));
ofs = ftello64(fp);
#else
ofs = cast_num(ftell(fp));
ofs = (int64_t)ftell(fp);
#endif
setnumV(L->top-1, ofs);
setint64V(L->top-1, ofs);
return 1;
}

View File

@ -70,7 +70,7 @@ LJLIB_CF(jit_off)
LJLIB_CF(jit_flush)
{
#if LJ_HASJIT
if (L->base < L->top && (tvisnum(L->base) || tvisstr(L->base))) {
if (L->base < L->top && !tvisnil(L->base)) {
int traceno = lj_lib_checkint(L, 1);
luaJIT_setmode(L, traceno, LUAJIT_MODE_FLUSH|LUAJIT_MODE_TRACE);
return 0;
@ -202,8 +202,8 @@ LJLIB_CF(jit_util_funcinfo)
t = tabV(L->top-1);
if (!iscfunc(fn))
setintfield(L, t, "ffid", fn->c.ffid);
setnumV(lj_tab_setstr(L, t, lj_str_newlit(L, "addr")),
cast_num((intptr_t)fn->c.f));
setintptrV(lj_tab_setstr(L, t, lj_str_newlit(L, "addr")),
(intptr_t)(void *)fn->c.f);
setintfield(L, t, "upvalues", fn->c.nupvalues);
}
return 1;
@ -233,7 +233,7 @@ LJLIB_CF(jit_util_funck)
ptrdiff_t idx = (ptrdiff_t)lj_lib_checkint(L, 2);
if (idx >= 0) {
if (idx < (ptrdiff_t)pt->sizekn) {
setnumV(L->top-1, proto_knum(pt, idx));
copyTV(L, L->top-1, proto_knumtv(pt, idx));
return 1;
}
} else {
@ -358,7 +358,7 @@ LJLIB_CF(jit_util_tracemc)
GCtrace *T = jit_checktrace(L);
if (T && T->mcode != NULL) {
setstrV(L, L->top-1, lj_str_new(L, (const char *)T->mcode, T->szmcode));
setnumV(L->top++, cast_num((intptr_t)T->mcode));
setintptrV(L->top++, (intptr_t)(void *)T->mcode);
setintV(L->top++, T->mcloop);
return 3;
}
@ -371,7 +371,7 @@ LJLIB_CF(jit_util_traceexitstub)
ExitNo exitno = (ExitNo)lj_lib_checkint(L, 1);
jit_State *J = L2J(L);
if (exitno < EXITSTUBS_PER_GROUP*LJ_MAX_EXITSTUBGR) {
setnumV(L->top-1, cast_num((intptr_t)exitstub_addr(J, exitno)));
setintptrV(L->top-1, (intptr_t)(void *)exitstub_addr(J, exitno));
return 1;
}
return 0;
@ -382,7 +382,7 @@ LJLIB_CF(jit_util_ircalladdr)
{
uint32_t idx = (uint32_t)lj_lib_checkint(L, 1);
if (idx < IRCALL__MAX) {
setnumV(L->top-1, cast_num((uintptr_t)(void *)lj_ir_callinfo[idx].func));
setintptrV(L->top-1, (intptr_t)(void *)lj_ir_callinfo[idx].func);
return 1;
}
return 0;
@ -462,11 +462,14 @@ static int jitopt_param(jit_State *J, const char *str)
int i;
for (i = 0; i < JIT_P__MAX; i++) {
size_t len = *(const uint8_t *)lst;
TValue tv;
lua_assert(len != 0);
if (strncmp(str, lst+1, len) == 0 && str[len] == '=' &&
lj_str_numconv(&str[len+1], &tv)) {
J->param[i] = lj_num2int(tv.n);
if (strncmp(str, lst+1, len) == 0 && str[len] == '=') {
int32_t n = 0;
const char *p = &str[len+1];
while (*p >= '0' && *p <= '9')
n = n*10 + (*p++ - '0');
if (*p) return 0; /* Malformed number. */
J->param[i] = n;
if (i == JIT_P_hotloop)
lj_dispatch_init_hotcount(J2G(J));
return 1; /* Ok. */

View File

@ -129,7 +129,7 @@ static void random_init(RandomState *rs, double d)
LJLIB_PUSH(top-2) /* Upvalue holds userdata with RandomState. */
LJLIB_CF(math_random) LJLIB_REC(.)
{
int n = cast_int(L->top - L->base);
int n = (int)(L->top - L->base);
RandomState *rs = (RandomState *)(uddata(udataV(lj_lib_upvalue(L, 1))));
U64double u;
double d;

View File

@ -61,7 +61,7 @@ LJLIB_ASM(string_byte) LJLIB_REC(string_range 0)
LJLIB_ASM(string_char)
{
int i, nargs = cast_int(L->top - L->base);
int i, nargs = (int)(L->top - L->base);
char *buf = lj_str_needbuf(L, &G(L)->tmpbuf, (size_t)nargs);
for (i = 1; i <= nargs; i++) {
int32_t k = lj_lib_checkint(L, i);
@ -737,7 +737,7 @@ LJLIB_CF(string_format)
tv.n = lj_lib_checknum(L, arg);
if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) {
/* Canonicalize output of non-finite values. */
char *p, nbuf[LUAI_MAXNUMBER2STR];
char *p, nbuf[LJ_STR_NUMBUF];
size_t len = lj_str_bufnum(nbuf, &tv);
if (strfrmt[-1] == 'E' || strfrmt[-1] == 'G') {
nbuf[len-3] = nbuf[len-3] - 0x20;
@ -801,7 +801,7 @@ LUALIB_API int luaopen_string(lua_State *L)
g = G(L);
setgcref(basemt_it(g, LJ_TSTR), obj2gco(mt));
settabV(L, lj_tab_setstr(L, mt, mmname_str(g, MM_index)), tabV(L->top-1));
mt->nomm = cast_byte(~(1u<<MM_index));
mt->nomm = (uint8_t)(~(1u<<MM_index));
return 1;
}

View File

@ -82,8 +82,10 @@ LJLIB_CF(table_maxn)
}
node = noderef(t->node);
for (i = (ptrdiff_t)t->hmask; i >= 0; i--)
if (tvisnum(&node[i].key) && numV(&node[i].key) > m)
m = numV(&node[i].key);
if (tvisnumber(&node[i].key)) {
lua_Number n = numberVnum(&node[i].key);
if (n > m) m = n;
}
setnumV(L->top-1, m);
return 1;
}
@ -154,7 +156,7 @@ LJLIB_CF(table_concat)
cTValue *o;
lua_rawgeti(L, 1, i);
o = L->top-1;
if (!(tvisstr(o) || tvisnum(o)))
if (!(tvisstr(o) || tvisnumber(o)))
lj_err_callerv(L, LJ_ERR_TABCAT, typename(o), i);
luaL_addvalue(&b);
if (i++ == e) break;

View File

@ -115,7 +115,7 @@ LUA_API void lua_xmove(lua_State *from, lua_State *to, int n)
LUA_API int lua_gettop(lua_State *L)
{
return cast_int(L->top - L->base);
return (int)(L->top - L->base);
}
LUA_API void lua_settop(lua_State *L, int idx)
@ -186,7 +186,7 @@ LUA_API void lua_pushvalue(lua_State *L, int idx)
LUA_API int lua_type(lua_State *L, int idx)
{
cTValue *o = index2adr(L, idx);
if (tvisnum(o)) {
if (tvisnumber(o)) {
return LUA_TNUMBER;
#if LJ_64
} else if (tvislightud(o)) {
@ -234,13 +234,13 @@ LUA_API int lua_isnumber(lua_State *L, int idx)
{
cTValue *o = index2adr(L, idx);
TValue tmp;
return (tvisnum(o) || (tvisstr(o) && lj_str_tonum(strV(o), &tmp)));
return (tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), &tmp)));
}
LUA_API int lua_isstring(lua_State *L, int idx)
{
cTValue *o = index2adr(L, idx);
return (tvisstr(o) || tvisnum(o));
return (tvisstr(o) || tvisnumber(o));
}
LUA_API int lua_isuserdata(lua_State *L, int idx)
@ -260,8 +260,10 @@ LUA_API int lua_equal(lua_State *L, int idx1, int idx2)
{
cTValue *o1 = index2adr(L, idx1);
cTValue *o2 = index2adr(L, idx2);
if (tvisnum(o1) && tvisnum(o2)) {
return numV(o1) == numV(o2);
if (tvisint(o1) && tvisint(o2)) {
return intV(o1) == intV(o2);
} else if (tvisnumber(o1) && tvisnumber(o2)) {
return numberVnum(o1) == numberVnum(o2);
} else if (itype(o1) != itype(o2)) {
return 0;
} else if (tvispri(o1)) {
@ -293,8 +295,10 @@ LUA_API int lua_lessthan(lua_State *L, int idx1, int idx2)
cTValue *o2 = index2adr(L, idx2);
if (o1 == niltv(L) || o2 == niltv(L)) {
return 0;
} else if (tvisnum(o1) && tvisnum(o2)) {
return numV(o1) < numV(o2);
} else if (tvisint(o1) && tvisint(o2)) {
return intV(o1) < intV(o2);
} else if (tvisnumber(o1) && tvisnumber(o2)) {
return numberVnum(o1) < numberVnum(o2);
} else {
TValue *base = lj_meta_comp(L, o1, o2, 0);
if ((uintptr_t)base <= 1) {
@ -312,8 +316,8 @@ LUA_API lua_Number lua_tonumber(lua_State *L, int idx)
{
cTValue *o = index2adr(L, idx);
TValue tmp;
if (LJ_LIKELY(tvisnum(o)))
return numV(o);
if (LJ_LIKELY(tvisnumber(o)))
return numberVnum(o);
else if (tvisstr(o) && lj_str_tonum(strV(o), &tmp))
return numV(&tmp);
else
@ -324,8 +328,8 @@ LUALIB_API lua_Number luaL_checknumber(lua_State *L, int idx)
{
cTValue *o = index2adr(L, idx);
TValue tmp;
if (tvisnum(o))
return numV(o);
if (LJ_LIKELY(tvisnumber(o)))
return numberVnum(o);
else if (!(tvisstr(o) && lj_str_tonum(strV(o), &tmp)))
lj_err_argt(L, idx, LUA_TNUMBER);
return numV(&tmp);
@ -335,8 +339,8 @@ LUALIB_API lua_Number luaL_optnumber(lua_State *L, int idx, lua_Number def)
{
cTValue *o = index2adr(L, idx);
TValue tmp;
if (tvisnum(o))
return numV(o);
if (LJ_LIKELY(tvisnumber(o)))
return numberVnum(o);
else if (tvisnil(o))
return def;
else if (!(tvisstr(o) && lj_str_tonum(strV(o), &tmp)))
@ -349,12 +353,17 @@ LUA_API lua_Integer lua_tointeger(lua_State *L, int idx)
cTValue *o = index2adr(L, idx);
TValue tmp;
lua_Number n;
if (LJ_LIKELY(tvisnum(o)))
if (LJ_LIKELY(tvisint(o))) {
return intV(o);
} else if (LJ_LIKELY(tvisnum(o))) {
n = numV(o);
else if (tvisstr(o) && lj_str_tonum(strV(o), &tmp))
} else {
if (!(tvisstr(o) && lj_str_tonumber(strV(o), &tmp)))
return 0;
if (tvisint(&tmp))
return (lua_Integer)intV(&tmp);
n = numV(&tmp);
else
return 0;
}
#if LJ_64
return (lua_Integer)n;
#else
@ -367,12 +376,17 @@ LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int idx)
cTValue *o = index2adr(L, idx);
TValue tmp;
lua_Number n;
if (LJ_LIKELY(tvisnum(o)))
if (LJ_LIKELY(tvisint(o))) {
return intV(o);
} else if (LJ_LIKELY(tvisnum(o))) {
n = numV(o);
else if (tvisstr(o) && lj_str_tonum(strV(o), &tmp))
} else {
if (!(tvisstr(o) && lj_str_tonumber(strV(o), &tmp)))
lj_err_argt(L, idx, LUA_TNUMBER);
if (tvisint(&tmp))
return (lua_Integer)intV(&tmp);
n = numV(&tmp);
else
lj_err_argt(L, idx, LUA_TNUMBER);
}
#if LJ_64
return (lua_Integer)n;
#else
@ -385,14 +399,19 @@ LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int idx, lua_Integer def)
cTValue *o = index2adr(L, idx);
TValue tmp;
lua_Number n;
if (LJ_LIKELY(tvisnum(o)))
if (LJ_LIKELY(tvisint(o))) {
return intV(o);
} else if (LJ_LIKELY(tvisnum(o))) {
n = numV(o);
else if (tvisnil(o))
} else if (tvisnil(o)) {
return def;
else if (tvisstr(o) && lj_str_tonum(strV(o), &tmp))
} else {
if (!(tvisstr(o) && lj_str_tonumber(strV(o), &tmp)))
lj_err_argt(L, idx, LUA_TNUMBER);
if (tvisint(&tmp))
return (lua_Integer)intV(&tmp);
n = numV(&tmp);
else
lj_err_argt(L, idx, LUA_TNUMBER);
}
#if LJ_64
return (lua_Integer)n;
#else
@ -412,10 +431,10 @@ LUA_API const char *lua_tolstring(lua_State *L, int idx, size_t *len)
GCstr *s;
if (LJ_LIKELY(tvisstr(o))) {
s = strV(o);
} else if (tvisnum(o)) {
} else if (tvisnumber(o)) {
lj_gc_check(L);
o = index2adr(L, idx); /* GC may move the stack. */
s = lj_str_fromnum(L, &o->n);
s = lj_str_fromnumber(L, o);
} else {
if (len != NULL) *len = 0;
return NULL;
@ -430,10 +449,10 @@ LUALIB_API const char *luaL_checklstring(lua_State *L, int idx, size_t *len)
GCstr *s;
if (LJ_LIKELY(tvisstr(o))) {
s = strV(o);
} else if (tvisnum(o)) {
} else if (tvisnumber(o)) {
lj_gc_check(L);
o = index2adr(L, idx); /* GC may move the stack. */
s = lj_str_fromnum(L, &o->n);
s = lj_str_fromnumber(L, o);
} else {
lj_err_argt(L, idx, LUA_TSTRING);
}
@ -451,10 +470,10 @@ LUALIB_API const char *luaL_optlstring(lua_State *L, int idx,
} else if (tvisnil(o)) {
if (len != NULL) *len = def ? strlen(def) : 0;
return def;
} else if (tvisnum(o)) {
} else if (tvisnumber(o)) {
lj_gc_check(L);
o = index2adr(L, idx); /* GC may move the stack. */
s = lj_str_fromnum(L, &o->n);
s = lj_str_fromnumber(L, o);
} else {
lj_err_argt(L, idx, LUA_TSTRING);
}
@ -484,8 +503,8 @@ LUA_API size_t lua_objlen(lua_State *L, int idx)
return cast(size_t, lj_tab_len(tabV(o)));
else if (tvisudata(o))
return udataV(o)->len;
else if (tvisnum(o))
return lj_str_fromnum(L, &o->n)->len;
else if (tvisnumber(o))
return lj_str_fromnumber(L, o)->len;
else
return 0;
}
@ -551,7 +570,7 @@ LUA_API void lua_pushnumber(lua_State *L, lua_Number n)
LUA_API void lua_pushinteger(lua_State *L, lua_Integer n)
{
setnumV(L->top, cast_num(n));
setintptrV(L->top, n);
incr_top(L);
}
@ -687,7 +706,7 @@ LUA_API void lua_concat(lua_State *L, int n)
L->top -= n;
break;
}
n -= cast_int(L->top - top);
n -= (int)(L->top - top);
L->top = top+2;
lj_vm_call(L, top, 1+1);
L->top--;
@ -1085,7 +1104,7 @@ LUA_API int lua_yield(lua_State *L, int nresults)
setcont(top+1, lj_cont_hook);
setframe_pc(top+1, cframe_pc(cf)-1);
setframe_gc(top+2, obj2gco(L));
top[2].fr.tp.ftsz = cast_int((char *)(top+3)-(char *)L->base)+FRAME_CONT;
top[2].fr.tp.ftsz = (int)((char *)(top+3)-(char *)L->base)+FRAME_CONT;
L->top = L->base = top+3;
}
L->cframe = NULL;
@ -1160,10 +1179,10 @@ LUA_API int lua_gc(lua_State *L, int what, int data)
lj_gc_fullgc(L);
break;
case LUA_GCCOUNT:
res = cast_int(g->gc.total >> 10);
res = (int)(g->gc.total >> 10);
break;
case LUA_GCCOUNTB:
res = cast_int(g->gc.total & 0x3ff);
res = (int)(g->gc.total & 0x3ff);
break;
case LUA_GCSTEP: {
MSize a = (MSize)data << 10;
@ -1176,11 +1195,11 @@ LUA_API int lua_gc(lua_State *L, int what, int data)
break;
}
case LUA_GCSETPAUSE:
res = cast_int(g->gc.pause);
res = (int)(g->gc.pause);
g->gc.pause = (MSize)data;
break;
case LUA_GCSETSTEPMUL:
res = cast_int(g->gc.stepmul);
res = (int)(g->gc.stepmul);
g->gc.stepmul = (MSize)data;
break;
default:

View File

@ -522,7 +522,7 @@ GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned)
/* Convert complex to string with 'i' or 'I' suffix. */
GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size)
{
char buf[2*LUAI_MAXNUMBER2STR+2+1];
char buf[2*LJ_STR_NUMBUF+2+1];
TValue re, im;
size_t len;
if (size == 2*sizeof(double)) {

View File

@ -81,7 +81,6 @@ typedef unsigned __int32 uintptr_t;
#define U64x(hi, lo) (((uint64_t)0x##hi << 32) + (uint64_t)0x##lo)
#define cast_byte(i) cast(uint8_t, (i))
#define cast_num(i) cast(lua_Number, (i))
#define cast_int(i) cast(int, (i))
#define i32ptr(p) ((int32_t)(intptr_t)(void *)(p))
#define u32ptr(p) ((uint32_t)(intptr_t)(void *)(p))

View File

@ -320,7 +320,7 @@ static void callhook(lua_State *L, int event, BCLine line)
ar.event = event;
ar.currentline = line;
/* Top frame, nextframe = NULL. */
ar.i_ci = cast_int((L->base-1) - tvref(L->stack));
ar.i_ci = (int)((L->base-1) - tvref(L->stack));
lj_state_checkstack(L, 1+LUA_MINSTACK);
hook_enter(g);
hookf(L, &ar);

View File

@ -397,7 +397,7 @@ cTValue *lj_err_getframe(lua_State *L, int level, int *size)
if (frame_gc(frame) == obj2gco(L))
level++; /* Skip dummy frames. See lj_meta_call(). */
if (level-- == 0) {
*size = cast_int(nextframe - frame);
*size = (int)(nextframe - frame);
return frame; /* Level found. */
}
nextframe = frame;
@ -418,7 +418,7 @@ LUA_API int lua_getstack(lua_State *L, int level, lua_Debug *ar)
int size;
cTValue *frame = lj_err_getframe(L, level, &size);
if (frame) {
ar->i_ci = (size << 16) + cast_int(frame - tvref(L->stack));
ar->i_ci = (size << 16) + (int)(frame - tvref(L->stack));
return 1;
} else {
ar->i_ci = level - size;
@ -486,7 +486,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
if (cframe_canyield(cf)) { /* Resume? */
if (errcode) {
L->cframe = NULL;
L->status = cast_byte(errcode);
L->status = (uint8_t)errcode;
}
return cf;
}
@ -534,7 +534,7 @@ static void *err_unwind(lua_State *L, void *stopcf, int errcode)
#define LJ_UEXCLASS 0x4c55414a49543200ULL /* LUAJIT2\0 */
#define LJ_UEXCLASS_MAKE(c) (LJ_UEXCLASS | (_Unwind_Exception_Class)(c))
#define LJ_UEXCLASS_CHECK(cl) (((cl) ^ LJ_UEXCLASS) <= 0xff)
#define LJ_UEXCLASS_ERRCODE(cl) (cast_int((cl) & 0xff))
#define LJ_UEXCLASS_ERRCODE(cl) ((int)((cl) & 0xff))
/* DWARF2 personality handler referenced from interpreter .eh_frame. */
LJ_FUNCA int lj_err_unwind_dwarf(int version, _Unwind_Action actions,
@ -642,7 +642,7 @@ extern __DestructExceptionObject(EXCEPTION_RECORD *rec, int nothrow);
#define LJ_EXCODE ((DWORD)0xe24c4a00)
#define LJ_EXCODE_MAKE(c) (LJ_EXCODE | (DWORD)(c))
#define LJ_EXCODE_CHECK(cl) (((cl) ^ LJ_EXCODE) <= 0xff)
#define LJ_EXCODE_ERRCODE(cl) (cast_int((cl) & 0xff))
#define LJ_EXCODE_ERRCODE(cl) ((int)((cl) & 0xff))
/* Win64 exception handler for interpreter frame. */
LJ_FUNCA EXCEPTION_DISPOSITION lj_err_unwind_win64(EXCEPTION_RECORD *rec,
@ -945,7 +945,7 @@ LJ_NORET LJ_NOINLINE static void err_argmsg(lua_State *L, int narg,
const char *fname = "?";
const char *ftype = getfuncname(L, L->base - 1, &fname);
if (narg < 0 && narg > LUA_REGISTRYINDEX)
narg = cast_int(L->top - L->base) + narg + 1;
narg = (int)(L->top - L->base) + narg + 1;
if (ftype && ftype[3] == 'h' && --narg == 0) /* Check for "method". */
msg = lj_str_pushf(L, err2msg(LJ_ERR_BADSELF), fname, msg);
else

View File

@ -98,7 +98,7 @@ GCfunc *lj_func_newC(lua_State *L, MSize nelems, GCtab *env)
GCfunc *fn = cast(GCfunc *, lj_mem_newgco(L, sizeCfunc(nelems)));
fn->c.gct = ~LJ_TFUNC;
fn->c.ffid = FF_C;
fn->c.nupvalues = cast_byte(nelems);
fn->c.nupvalues = (uint8_t)nelems;
/* NOBARRIER: The GCfunc is new (marked white). */
setmref(fn->c.pc, &G(L)->bc_cfunc_ext);
setgcref(fn->c.env, obj2gco(env));
@ -110,7 +110,7 @@ GCfunc *lj_func_newL(lua_State *L, GCproto *pt, GCtab *env)
GCfunc *fn = cast(GCfunc *, lj_mem_newgco(L, sizeLfunc((MSize)pt->sizeuv)));
fn->l.gct = ~LJ_TFUNC;
fn->l.ffid = FF_LUA;
fn->l.nupvalues = cast_byte(pt->sizeuv);
fn->l.nupvalues = (uint8_t)pt->sizeuv;
/* NOBARRIER: Really a setgcref. But the GCfunc is new (marked white). */
setmref(fn->l.pc, proto_bc(pt));
setgcref(fn->l.env, obj2gco(env));

View File

@ -170,10 +170,15 @@ static void lex_number(LexState *ls, TValue *tv)
if (c == 'I') { /* Return cdata holding a complex number. */
GCcdata *cd = lj_cdata_new_(ls->L, CTID_COMPLEX_DOUBLE, 2*sizeof(double));
((double *)cdataptr(cd))[0] = 0;
((double *)cdataptr(cd))[1] = tv->n;
((double *)cdataptr(cd))[1] = numberVnum(tv);
lj_parse_keepcdata(ls, tv, cd);
}
#endif
if (LJ_DUALNUM && tvisnum(tv)) {
int32_t k = lj_num2int(numV(tv));
if ((lua_Number)k == numV(tv)) /* -0 cannot end up here. */
setintV(tv, k);
}
return;
}
lj_lex_error(ls, TK_number, LJ_ERR_XNUMBER);
@ -506,7 +511,7 @@ void lj_lex_init(lua_State *L)
for (i = 0; i < TK_RESERVED; i++) {
GCstr *s = lj_str_newz(L, tokennames[i]);
fixstring(s); /* Reserved words are never collected. */
s->reserved = cast_byte(i+1);
s->reserved = (uint8_t)(i+1);
}
}

View File

@ -135,8 +135,8 @@ GCstr *lj_lib_checkstr(lua_State *L, int narg)
if (o < L->top) {
if (LJ_LIKELY(tvisstr(o))) {
return strV(o);
} else if (tvisnum(o)) {
GCstr *s = lj_str_fromnum(L, &o->n);
} else if (tvisnumber(o)) {
GCstr *s = lj_str_fromnumber(L, o);
setstrV(L, o, s);
return s;
}
@ -155,14 +155,18 @@ lua_Number lj_lib_checknum(lua_State *L, int narg)
{
TValue *o = L->base + narg-1;
if (!(o < L->top &&
(tvisnum(o) || (tvisstr(o) && lj_str_tonum(strV(o), o)))))
(tvisnumber(o) || (tvisstr(o) && lj_str_tonumber(strV(o), o)))))
lj_err_argt(L, narg, LUA_TNUMBER);
return numV(o);
return numberVnum(o);
}
int32_t lj_lib_checkint(lua_State *L, int narg)
{
return lj_num2int(lj_lib_checknum(L, 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 numberVint(o);
}
int32_t lj_lib_optint(lua_State *L, int narg, int32_t def)

View File

@ -41,10 +41,6 @@ LJ_FUNC GCtab *lj_lib_checktab(lua_State *L, int narg);
LJ_FUNC GCtab *lj_lib_checktabornil(lua_State *L, int narg);
LJ_FUNC int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst);
#define lj_lib_opt(L, narg, gotarg, noarg) \
{ TValue *_o = L->base + (narg)-1; \
if (_o < L->top && !tvisnil(_o)) { gotarg } else { noarg } }
/* Avoid including lj_frame.h. */
#define lj_lib_upvalue(L, n) \
(&gcref((L->base-1)->fr.func)->fn.c.upvalue[(n)-1])

View File

@ -44,7 +44,7 @@ cTValue *lj_meta_cache(GCtab *mt, MMS mm, GCstr *name)
cTValue *mo = lj_tab_getstr(mt, name);
lua_assert(mm <= MM_FAST);
if (!mo || tvisnil(mo)) { /* No metamethod? */
mt->nomm |= cast_byte(1u<<mm); /* Set negative cache flag. */
mt->nomm |= (uint8_t)(1u<<mm); /* Set negative cache flag. */
return NULL;
}
return mo;
@ -156,6 +156,8 @@ static cTValue *str2num(cTValue *o, TValue *n)
{
if (tvisnum(o))
return o;
else if (tvisint(o))
return (setnumV(n, (lua_Number)intV(o)), n);
else if (tvisstr(o) && lj_str_tonum(strV(o), n))
return n;
else
@ -192,8 +194,8 @@ static LJ_AINLINE int tostring(lua_State *L, TValue *o)
{
if (tvisstr(o)) {
return 1;
} else if (tvisnum(o)) {
setstrV(L, o, lj_str_fromnum(L, &o->n));
} else if (tvisnumber(o)) {
setstrV(L, o, lj_str_fromnumber(L, o));
return 1;
} else {
return 0;
@ -205,12 +207,12 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left)
{
do {
int n = 1;
if (!(tvisstr(top-1) || tvisnum(top-1)) || !tostring(L, top)) {
if (!(tvisstr(top-1) || tvisnumber(top-1)) || !tostring(L, top)) {
cTValue *mo = lj_meta_lookup(L, top-1, MM_concat);
if (tvisnil(mo)) {
mo = lj_meta_lookup(L, top, MM_concat);
if (tvisnil(mo)) {
if (tvisstr(top-1) || tvisnum(top-1)) top++;
if (tvisstr(top-1) || tvisnumber(top-1)) top++;
lj_err_optype(L, top-1, LJ_ERR_OPCAT);
return NULL; /* unreachable */
}

View File

@ -27,9 +27,9 @@ int lj_obj_equal(cTValue *o1, cTValue *o2)
return 1;
if (!tvisnum(o1))
return gcrefeq(o1->gcr, o2->gcr);
} else if (!tvisnum(o1) || !tvisnum(o2)) {
} else if (!tvisnumber(o1) || !tvisnumber(o2)) {
return 0;
}
return numV(o1) == numV(o2);
return numberVnum(o1) == numberVnum(o2);
}

View File

@ -140,7 +140,10 @@ typedef LJ_ALIGN(8) union TValue {
lua_Number n; /* Number object overlaps split tag/value object. */
struct {
LJ_ENDIAN_LOHI(
GCRef gcr; /* GCobj reference (if any). */
union {
GCRef gcr; /* GCobj reference (if any). */
int32_t i; /* Integer value. */
};
, uint32_t it; /* Internal object tag. Must overlap MSW of number. */
)
};
@ -180,6 +183,7 @@ typedef const TValue cTValue;
** lightuserdata | itype | void * | (32 bit platforms)
** lightuserdata |ffff| void * | (64 bit platforms, 47 bit pointers)
** GC objects | itype | GCRef |
** int (LJ_DUALNUM)| itype | int |
** number -------double------
**
** ORDER LJ_T
@ -203,6 +207,7 @@ typedef const TValue cTValue;
/* This is just the canonical number type used in some places. */
#define LJ_TNUMX (~13u)
/* Integers have itype == LJ_TISNUM doubles have itype < LJ_TISNUM */
#if LJ_64
#define LJ_TISNUM 0xfffeffffu
#else
@ -322,6 +327,8 @@ typedef struct GCproto {
gcref(mref((pt)->k, GCRef)[(idx)]))
#define proto_knum(pt, idx) \
check_exp((uintptr_t)(idx) < (pt)->sizekn, mref((pt)->k, lua_Number)[(idx)])
#define proto_knumtv(pt, idx) \
check_exp((uintptr_t)(idx) < (pt)->sizekn, &mref((pt)->k, TValue)[(idx)])
#define proto_bc(pt) ((BCIns *)((char *)(pt) + sizeof(GCproto)))
#define proto_bcpos(pt, pc) ((BCPos)((pc) - proto_bc(pt)))
#define proto_uv(pt) (mref((pt)->uv, uint16_t))
@ -650,7 +657,9 @@ typedef union GCobj {
#define tviscdata(o) (itype(o) == LJ_TCDATA)
#define tvistab(o) (itype(o) == LJ_TTAB)
#define tvisudata(o) (itype(o) == LJ_TUDATA)
#define tvisnum(o) (itype(o) <= LJ_TISNUM)
#define tvisnumber(o) (itype(o) <= LJ_TISNUM)
#define tvisint(o) (LJ_DUALNUM && itype(o) == LJ_TISNUM)
#define tvisnum(o) (itype(o) < LJ_TISNUM)
#define tvistruecond(o) (itype(o) < LJ_TISTRUECOND)
#define tvispri(o) (itype(o) >= LJ_TISPRI)
@ -659,6 +668,11 @@ typedef union GCobj {
/* Special macros to test numbers for NaN, +0, -0, +1 and raw equality. */
#define tvisnan(o) ((o)->n != (o)->n)
#if LJ_64
#define tviszero(o) (((o)->u64 << 1) == 0)
#else
#define tviszero(o) (((o)->u32.lo | ((o)->u32.hi << 1)) == 0)
#endif
#define tvispzero(o) ((o)->u64 == 0)
#define tvismzero(o) ((o)->u64 == U64x(80000000,00000000))
#define tvispone(o) ((o)->u64 == U64x(3ff00000,00000000))
@ -667,9 +681,9 @@ typedef union GCobj {
/* Macros to convert type ids. */
#if LJ_64
#define itypemap(o) \
(tvisnum(o) ? ~LJ_TNUMX : tvislightud(o) ? ~LJ_TLIGHTUD : ~itype(o))
(tvisnumber(o) ? ~LJ_TNUMX : tvislightud(o) ? ~LJ_TLIGHTUD : ~itype(o))
#else
#define itypemap(o) (tvisnum(o) ? ~LJ_TNUMX : ~itype(o))
#define itypemap(o) (tvisnumber(o) ? ~LJ_TNUMX : ~itype(o))
#endif
/* Macros to get tagged values. */
@ -690,6 +704,7 @@ typedef union GCobj {
#define tabV(o) check_exp(tvistab(o), &gcval(o)->tab)
#define udataV(o) check_exp(tvisudata(o), &gcval(o)->ud)
#define numV(o) check_exp(tvisnum(o), (o)->n)
#define intV(o) check_exp(tvisint(o), (int32_t)(o)->i)
/* Macros to set tagged values. */
#define setitype(o, i) ((o)->it = (i))
@ -741,7 +756,29 @@ define_setV(setudataV, GCudata, LJ_TUDATA)
#define setnanV(o) ((o)->u64 = U64x(fff80000,00000000))
#define setpinfV(o) ((o)->u64 = U64x(7ff00000,00000000))
#define setminfV(o) ((o)->u64 = U64x(fff00000,00000000))
#define setintV(o, i) ((o)->n = cast_num((int32_t)(i)))
static LJ_AINLINE void setintV(TValue *o, int32_t i)
{
#if LJ_DUALNUM
o->i = (uint32_t)i; setitype(o, LJ_TISNUM);
#else
o->n = (lua_Number)i;
#endif
}
static LJ_AINLINE void setint64V(TValue *o, int64_t i)
{
if (LJ_DUALNUM && LJ_LIKELY(i == (int64_t)(int32_t)i))
setintV(o, (int32_t)i);
else
setnumV(o, (lua_Number)i);
}
#if LJ_64
#define setintptrV(o, i) setint64V((o), (i))
#else
#define setintptrV(o, i) setintV((o), (i))
#endif
/* Copy tagged values. */
static LJ_AINLINE void copyTV(lua_State *L, TValue *o1, const TValue *o2)
@ -774,6 +811,22 @@ static LJ_AINLINE uint64_t lj_num2u64(lua_Number n)
return (uint64_t)n;
}
static LJ_AINLINE int32_t numberVint(cTValue *o)
{
if (LJ_LIKELY(tvisint(o)))
return intV(o);
else
return lj_num2int(numV(o));
}
static LJ_AINLINE lua_Number numberVnum(cTValue *o)
{
if (LJ_UNLIKELY(tvisint(o)))
return (lua_Number)intV(o);
else
return numV(o);
}
/* -- Miscellaneous object handling --------------------------------------- */
/* Names and maps for internal and external object tags. */

View File

@ -73,7 +73,8 @@ typedef struct ExpDesc {
#define expr_isnumk_nojump(e) (expr_isnumk(e) && !expr_hasjump(e))
#define expr_isstrk(e) ((e)->k == VKSTR)
#define expr_numV(e) check_exp(expr_isnumk((e)), numV(&(e)->u.nval))
#define expr_numtv(e) check_exp(expr_isnumk((e)), &(e)->u.nval)
#define expr_numberV(e) numberVnum(expr_numtv((e)))
/* Initialize expression. */
static LJ_AINLINE void expr_init(ExpDesc *e, ExpKind k, uint32_t info)
@ -83,6 +84,13 @@ static LJ_AINLINE void expr_init(ExpDesc *e, ExpKind k, uint32_t info)
e->f = e->t = NO_JMP;
}
/* Check number constant for +-0. */
static int expr_numiszero(ExpDesc *e)
{
TValue *o = expr_numtv(e);
return tvisint(o) ? (intV(o) == 0) : tviszero(o);
}
/* Per-function linked list of scope blocks. */
typedef struct FuncScope {
struct FuncScope *prev; /* Link to outer scope. */
@ -174,16 +182,19 @@ LJ_NORET static void err_limit(FuncState *fs, uint32_t limit, const char *what)
/* Return bytecode encoding for primitive constant. */
#define const_pri(e) check_exp((e)->k <= VKTRUE, (e)->k)
#define tvhaskslot(o) ((o)->u32.hi == 0)
#define tvkslot(o) ((o)->u32.lo)
/* Add a number constant. */
static BCReg const_num(FuncState *fs, ExpDesc *e)
{
lua_State *L = fs->L;
TValue *val;
TValue *o;
lua_assert(expr_isnumk(e));
val = lj_tab_set(L, fs->kt, &e->u.nval);
if (tvisnum(val))
return val->u32.lo;
val->u64 = fs->nkn;
o = lj_tab_set(L, fs->kt, &e->u.nval);
if (tvhaskslot(o))
return tvkslot(o);
o->u64 = fs->nkn;
return fs->nkn++;
}
@ -191,13 +202,13 @@ static BCReg const_num(FuncState *fs, ExpDesc *e)
static BCReg const_gc(FuncState *fs, GCobj *gc, uint32_t itype)
{
lua_State *L = fs->L;
TValue o, *val;
setgcV(L, &o, gc, itype);
TValue key, *o;
setgcV(L, &key, gc, itype);
/* NOBARRIER: the key is new or kept alive. */
val = lj_tab_set(L, fs->kt, &o);
if (tvisnum(val))
return val->u32.lo;
val->u64 = fs->nkgc;
o = lj_tab_set(L, fs->kt, &key);
if (tvhaskslot(o))
return tvkslot(o);
o->u64 = fs->nkgc;
return fs->nkgc++;
}
@ -344,7 +355,7 @@ static void bcreg_bump(FuncState *fs, BCReg n)
if (sz > fs->framesize) {
if (sz >= LJ_MAX_SLOTS)
err_syntax(fs->ls, LJ_ERR_XSLOTS);
fs->framesize = cast_byte(sz);
fs->framesize = (uint8_t)sz;
}
}
@ -478,11 +489,18 @@ static void expr_toreg_nobranch(FuncState *fs, ExpDesc *e, BCReg reg)
if (e->k == VKSTR) {
ins = BCINS_AD(BC_KSTR, reg, const_str(fs, e));
} else if (e->k == VKNUM) {
lua_Number n = expr_numV(e);
#if LJ_DUALNUM
cTValue *tv = expr_numtv(e);
if (tvisint(tv) && checki16(intV(tv)))
ins = BCINS_AD(BC_KSHORT, reg, (BCReg)(uint16_t)intV(tv));
else
#else
lua_Number n = expr_numberV(e);
int32_t k = lj_num2int(n);
if (checki16(k) && n == cast_num(k))
if (checki16(k) && n == (lua_Number)k)
ins = BCINS_AD(BC_KSHORT, reg, (BCReg)(uint16_t)k);
else
#endif
ins = BCINS_AD(BC_KNUM, reg, const_num(fs, e));
#if LJ_HASFFI
} else if (e->k == VKCDATA) {
@ -720,10 +738,19 @@ static void bcemit_branch_f(FuncState *fs, ExpDesc *e)
static int foldarith(BinOpr opr, ExpDesc *e1, ExpDesc *e2)
{
TValue o;
lua_Number n;
if (!expr_isnumk_nojump(e1) || !expr_isnumk_nojump(e2)) return 0;
setnumV(&o, lj_vm_foldarith(expr_numV(e1), expr_numV(e2), (int)opr-OPR_ADD));
n = lj_vm_foldarith(expr_numberV(e1), expr_numberV(e2), (int)opr-OPR_ADD);
setnumV(&o, n);
if (tvisnan(&o) || tvismzero(&o)) return 0; /* Avoid NaN and -0 as consts. */
setnumV(&e1->u.nval, numV(&o));
if (LJ_DUALNUM) {
int32_t k = lj_num2int(n);
if ((lua_Number)k == n) {
setintV(&e1->u.nval, k);
return 1;
}
}
setnumV(&e1->u.nval, n);
return 1;
}
@ -900,9 +927,18 @@ static void bcemit_unop(FuncState *fs, BCOp op, ExpDesc *e)
return;
} else
#endif
if (expr_isnumk(e) && expr_numV(e) != 0) { /* Avoid folding to -0. */
e->u.nval.u64 ^= U64x(80000000,00000000);
return;
if (expr_isnumk(e) && !expr_numiszero(e)) { /* Avoid folding to -0. */
TValue *o = expr_numtv(e);
if (tvisint(o)) {
int32_t k = intV(o);
if (k == -k)
setnumV(o, -(lua_Number)k);
else
setintV(o, -k);
} else {
o->u64 ^= U64x(80000000,00000000);
return;
}
}
}
expr_toanyreg(fs, e);
@ -986,7 +1022,7 @@ static void var_new(LexState *ls, BCReg n, GCstr *name)
static void var_add(LexState *ls, BCReg nvars)
{
FuncState *fs = ls->fs;
fs->nactvar = cast_byte(fs->nactvar + nvars);
fs->nactvar = (uint8_t)(fs->nactvar + nvars);
for (; nvars; nvars--)
var_get(ls, fs, fs->nactvar - nvars).startpc = fs->pc;
}
@ -1094,16 +1130,33 @@ static void fs_fixup_k(FuncState *fs, GCproto *pt, void *kptr)
kt = fs->kt;
array = tvref(kt->array);
for (i = 0; i < kt->asize; i++)
if (tvisnum(&array[i]))
((lua_Number *)kptr)[array[i].u32.lo] = cast_num(i);
if (tvhaskslot(&array[i])) {
TValue *tv = &((TValue *)kptr)[tvkslot(&array[i])];
if (LJ_DUALNUM)
setintV(tv, (int32_t)i);
else
setnumV(tv, (lua_Number)i);
}
node = noderef(kt->node);
hmask = kt->hmask;
for (i = 0; i <= hmask; i++) {
Node *n = &node[i];
if (tvisnum(&n->val)) {
ptrdiff_t kidx = (ptrdiff_t)n->val.u32.lo;
if (tvhaskslot(&n->val)) {
ptrdiff_t kidx = (ptrdiff_t)tvkslot(&n->val);
lua_assert(!tvisint(&n->key));
if (tvisnum(&n->key)) {
((lua_Number *)kptr)[kidx] = numV(&n->key);
TValue *tv = &((TValue *)kptr)[kidx];
if (LJ_DUALNUM) {
lua_Number nn = numV(&n->key);
int32_t k = lj_num2int(nn);
lua_assert(!tvismzero(&n->key));
if ((lua_Number)k == nn)
setintV(tv, k);
else
*tv = n->key;
} else {
*tv = n->key;
}
} else {
GCobj *o = gcV(&n->key);
setgcref(((GCRef *)kptr)[~kidx], o);
@ -1286,12 +1339,22 @@ static void expr_index(FuncState *fs, ExpDesc *t, ExpDesc *e)
/* Already called: expr_toval(fs, e). */
t->k = VINDEXED;
if (expr_isnumk(e)) {
lua_Number n = expr_numV(e);
#if LJ_DUALNUM
if (tvisint(expr_numtv(e))) {
int32_t k = intV(expr_numtv(e));
if (checku8(k)) {
t->u.s.aux = BCMAX_C+1+(uint32_t)k; /* 256..511: const byte key */
return;
}
}
#else
lua_Number n = expr_numberV(e);
int32_t k = lj_num2int(n);
if (checku8(k) && n == cast_num(k)) {
if (checku8(k) && n == (lua_Number)k) {
t->u.s.aux = BCMAX_C+1+(uint32_t)k; /* 256..511: const byte key */
return;
}
#endif
} else if (expr_isstrk(e)) {
BCReg idx = const_str(fs, e);
if (idx <= BCMAX_C) {
@ -1331,8 +1394,8 @@ static void expr_kvalue(TValue *v, ExpDesc *e)
setgcref(v->gcr, obj2gco(e->u.sval));
setitype(v, LJ_TSTR);
} else {
lua_assert(e->k == VKNUM);
setnumV(v, expr_numV(e));
lua_assert(tvisnumber(expr_numtv(e)));
*v = *expr_numtv(e);
}
}
@ -1357,7 +1420,7 @@ static void expr_table(LexState *ls, ExpDesc *e)
if (ls->token == '[') {
expr_bracket(ls, &key); /* Already calls expr_toval. */
if (!expr_isk(&key)) expr_index(fs, e, &key);
if (expr_isnumk(&key) && expr_numV(&key) == 0) needarr = 1; else nhash++;
if (expr_isnumk(&key) && expr_numiszero(&key)) needarr = 1; else nhash++;
lex_check(ls, '=');
} else if (ls->token == TK_name && lj_lex_lookahead(ls) == '=') {
expr_str(ls, &key);
@ -2119,10 +2182,10 @@ static int predict_next(LexState *ls, FuncState *fs, BCPos pc)
case BC_GGET:
/* There's no inverse index (yet), so lookup the strings. */
o = lj_tab_getstr(fs->kt, lj_str_newlit(ls->L, "pairs"));
if (o && tvisnum(o) && o->u32.lo == bc_d(ins))
if (o && tvhaskslot(o) && tvkslot(o) == bc_d(ins))
return 1;
o = lj_tab_getstr(fs->kt, lj_str_newlit(ls->L, "next"));
if (o && tvisnum(o) && o->u32.lo == bc_d(ins))
if (o && tvhaskslot(o) && tvkslot(o) == bc_d(ins))
return 1;
return 0;
default:

View File

@ -289,7 +289,7 @@ const BCIns *lj_snap_restore(jit_State *J, void *exptr)
Reg r = regsp_reg(rs);
lua_assert(ra_hasreg(r));
if (irt_isinteger(t)) {
setintV(o, ex->gpr[r-RID_MIN_GPR]);
setintV(o, (int32_t)ex->gpr[r-RID_MIN_GPR]);
} else if (irt_isnum(t)) {
setnumV(o, ex->fpr[r-RID_MIN_FPR]);
#if LJ_64

View File

@ -171,6 +171,14 @@ void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s)
/* Convert string object to number. */
int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n)
{
int ok = lj_str_numconv(strdata(str), n);
if (ok && tvisint(n))
setnumV(n, (lua_Number)intV(n));
return ok;
}
int LJ_FASTCALL lj_str_tonumber(GCstr *str, TValue *n)
{
return lj_str_numconv(strdata(str), n);
}
@ -178,7 +186,11 @@ int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n)
/* Convert string to number. */
int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n)
{
#if LJ_DUALNUM
int sign = 0;
#else
lua_Number sign = 1;
#endif
const uint8_t *p = (const uint8_t *)s;
while (lj_char_isspace(*p)) p++;
if (*p == '-') { p++; sign = -1; } else if (*p == '+') { p++; }
@ -189,21 +201,34 @@ int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n)
if (!lj_char_isxdigit(*p))
return 0; /* Don't accept '0x' without hex digits. */
do {
if (k >= 0x10000000) goto parsedbl;
if (k >= 0x10000000u) goto parsedbl;
k = (k << 4) + (*p & 15u);
if (!lj_char_isdigit(*p)) k += 9;
p++;
} while (lj_char_isxdigit(*p));
} else {
while ((uint32_t)(*p - '0') < 10) {
if (k >= 0x19999999) goto parsedbl;
if (LJ_UNLIKELY(k >= 429496729) && (k != 429496729 || *p > '5'))
goto parsedbl;
k = k * 10u + (uint32_t)(*p++ - '0');
}
}
while (LJ_UNLIKELY(lj_char_isspace(*p))) p++;
if (LJ_LIKELY(*p == '\0')) {
setnumV(n, sign * cast_num(k));
#if LJ_DUALNUM
if (!sign) {
if (k < 0x80000000u) {
setintV(n, (int32_t)k);
return 1;
}
} else if (k <= 0x80000000u) {
setintV(n, -(int32_t)k);
return 1;
}
#else
setnumV(n, sign * (lua_Number)k);
return 1;
#endif
}
}
parsedbl:
@ -239,26 +264,36 @@ size_t LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o)
}
}
/* Print integer to buffer. Returns pointer to start. */
char * LJ_FASTCALL lj_str_bufint(char *p, int32_t k)
{
uint32_t u = (uint32_t)(k < 0 ? -k : k);
p += 1+10;
do { *--p = (char)('0' + u % 10); } while (u /= 10);
if (k < 0) *--p = '-';
return p;
}
/* Convert number to string. */
GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np)
{
char buf[LUAI_MAXNUMBER2STR];
char buf[LJ_STR_NUMBUF];
size_t len = lj_str_bufnum(buf, (TValue *)np);
return lj_str_new(L, buf, len);
}
#if LJ_HASJIT
/* Convert integer to string. */
GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k)
{
char s[1+10];
char *p = s+sizeof(s);
uint32_t i = (uint32_t)(k < 0 ? -k : k);
do { *--p = (char)('0' + i % 10); } while (i /= 10);
if (k < 0) *--p = '-';
char *p = lj_str_bufint(s, k);
return lj_str_new(L, p, (size_t)(s+sizeof(s)-p));
}
#endif
GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o)
{
return tvisint(o) ? lj_str_fromint(L, intV(o)) : lj_str_fromnum(L, &o->n);
}
/* -- String formatting --------------------------------------------------- */
@ -307,38 +342,34 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp)
addchar(L, sb, va_arg(argp, int));
break;
case 'd': {
char buff[1+10];
char *p = buff+sizeof(buff);
int32_t k = va_arg(argp, int32_t);
uint32_t i = (uint32_t)(k < 0 ? -k : k);
do { *--p = (char)('0' + i % 10); } while (i /= 10);
if (k < 0) *--p = '-';
addstr(L, sb, p, (MSize)(buff+sizeof(buff)-p));
char buf[LJ_STR_INTBUF];
char *p = lj_str_bufint(buf, va_arg(argp, int32_t));
addstr(L, sb, p, (MSize)(buf+LJ_STR_INTBUF-p));
break;
}
case 'f': {
char buf[LUAI_MAXNUMBER2STR];
char buf[LJ_STR_NUMBUF];
TValue tv;
MSize len;
tv.n = cast_num(va_arg(argp, LUAI_UACNUMBER));
tv.n = (lua_Number)(va_arg(argp, LUAI_UACNUMBER));
len = (MSize)lj_str_bufnum(buf, &tv);
addstr(L, sb, buf, len);
break;
}
case 'p': {
#define FMTP_CHARS (2*sizeof(ptrdiff_t))
char buff[2+FMTP_CHARS];
char buf[2+FMTP_CHARS];
ptrdiff_t p = (ptrdiff_t)(va_arg(argp, void *));
ptrdiff_t i, lasti = 2+FMTP_CHARS;
#if LJ_64
if ((p >> 32) == 0) /* Shorten output for true 32 bit pointers. */
lasti = 2+2*4;
#endif
buff[0] = '0';
buff[1] = 'x';
buf[0] = '0';
buf[1] = 'x';
for (i = lasti-1; i >= 2; i--, p >>= 4)
buff[i] = "0123456789abcdef"[(p & 15)];
addstr(L, sb, buff, (MSize)lasti);
buf[i] = "0123456789abcdef"[(p & 15)];
addstr(L, sb, buf, (MSize)lasti);
break;
}
case '%':

View File

@ -22,11 +22,15 @@ LJ_FUNC void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s);
/* Type conversions. */
LJ_FUNC int LJ_FASTCALL lj_str_numconv(const char *s, TValue *n);
LJ_FUNC int LJ_FASTCALL lj_str_tonum(GCstr *str, TValue *n);
LJ_FUNC int LJ_FASTCALL lj_str_tonumber(GCstr *str, TValue *n);
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);
#if LJ_HASJIT
LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k);
#endif
LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o);
#define LJ_STR_INTBUF (1+10)
#define LJ_STR_NUMBUF LUAI_MAXNUMBER2STR
/* String formatting. */
LJ_FUNC const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp);

View File

@ -34,6 +34,7 @@ static LJ_AINLINE Node *hashmask(const GCtab *t, uint32_t hash)
/* Hash an arbitrary key and return its anchor position in the hash table. */
static Node *hashkey(const GCtab *t, cTValue *key)
{
lua_assert(!tvisint(key));
if (tvisstr(key))
return hashstr(t, strV(key));
else if (tvisnum(key))
@ -100,7 +101,7 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
lua_assert((sizeof(GCtab) & 7) == 0);
t = (GCtab *)lj_mem_newgco(L, sizetabcolo(asize));
t->gct = ~LJ_TTAB;
t->nomm = cast_byte(~0);
t->nomm = (uint8_t)~0;
t->colo = (int8_t)asize;
setmref(t->array, (TValue *)((char *)t + sizeof(GCtab)));
setgcrefnull(t->metatable);
@ -110,7 +111,7 @@ static GCtab *newtab(lua_State *L, uint32_t asize, uint32_t hbits)
} else { /* Otherwise separately allocate the array part. */
t = lj_mem_newobj(L, GCtab);
t->gct = ~LJ_TTAB;
t->nomm = cast_byte(~0);
t->nomm = (uint8_t)~0;
t->colo = 0;
setmref(t->array, NULL);
setgcrefnull(t->metatable);
@ -275,10 +276,11 @@ static void resizetab(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits)
static uint32_t countint(cTValue *key, uint32_t *bins)
{
lua_assert(!tvisint(key));
if (tvisnum(key)) {
lua_Number nk = numV(key);
int32_t k = lj_num2int(nk);
if ((uint32_t)k < LJ_MAX_ASIZE && nk == cast_num(k)) {
if ((uint32_t)k < LJ_MAX_ASIZE && nk == (lua_Number)k) {
bins[(k > 2 ? lj_fls((uint32_t)(k-1)) : 0)]++;
return 1;
}
@ -360,7 +362,7 @@ cTValue * LJ_FASTCALL lj_tab_getinth(GCtab *t, int32_t key)
{
TValue k;
Node *n;
k.n = cast_num(key);
k.n = (lua_Number)key;
n = hashnum(t, &k);
do {
if (tvisnum(&n->key) && n->key.n == k.n)
@ -385,10 +387,14 @@ cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key)
cTValue *tv = lj_tab_getstr(t, strV(key));
if (tv)
return tv;
} else if (tvisint(key)) {
cTValue *tv = lj_tab_getint(t, intV(key));
if (tv)
return tv;
} else if (tvisnum(key)) {
lua_Number nk = numV(key);
int32_t k = lj_num2int(nk);
if (nk == cast_num(k)) {
if (nk == (lua_Number)k) {
cTValue *tv = lj_tab_getint(t, k);
if (tv)
return tv;
@ -466,7 +472,7 @@ TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key)
{
TValue k;
Node *n;
k.n = cast_num(key);
k.n = (lua_Number)key;
n = hashnum(t, &k);
do {
if (tvisnum(&n->key) && n->key.n == k.n)
@ -493,10 +499,12 @@ TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key)
t->nomm = 0; /* Invalidate negative metamethod cache. */
if (tvisstr(key)) {
return lj_tab_setstr(L, t, strV(key));
} else if (tvisint(key)) {
return lj_tab_setint(L, t, intV(key));
} else if (tvisnum(key)) {
lua_Number nk = numV(key);
int32_t k = lj_num2int(nk);
if (nk == cast_num(k))
if (nk == (lua_Number)k)
return lj_tab_setint(L, t, k);
if (tvisnan(key))
lj_err_msg(L, LJ_ERR_NANIDX);
@ -517,10 +525,17 @@ TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key)
/* Get the traversal index of a key. */
static uint32_t keyindex(lua_State *L, GCtab *t, cTValue *key)
{
if (tvisnum(key)) {
TValue tmp;
if (tvisint(key)) {
int32_t k = intV(key);
if ((uint32_t)k < t->asize)
return (uint32_t)k; /* Array key indexes: [0..t->asize-1] */
setnumV(&tmp, (lua_Number)k);
key = &tmp;
} else if (tvisnum(key)) {
lua_Number nk = numV(key);
int32_t k = lj_num2int(nk);
if ((uint32_t)k < t->asize && nk == cast_num(k))
if ((uint32_t)k < t->asize && nk == (lua_Number)k)
return (uint32_t)k; /* Array key indexes: [0..t->asize-1] */
}
if (!tvisnil(key)) {