From 03946ac978d9a1a3230619e3da048002e5fda2d1 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Thu, 17 Feb 2011 00:44:14 +0100 Subject: [PATCH] DUALNUM: Add integer type to core VM. --- src/lib_base.c | 28 ++++++---- src/lib_io.c | 42 +++++++++------ src/lib_jit.c | 25 +++++---- src/lib_math.c | 2 +- src/lib_string.c | 6 +-- src/lib_table.c | 8 +-- src/lj_api.c | 103 +++++++++++++++++++++--------------- src/lj_ctype.c | 2 +- src/lj_def.h | 1 - src/lj_dispatch.c | 2 +- src/lj_err.c | 12 ++--- src/lj_func.c | 4 +- src/lj_lex.c | 9 +++- src/lj_lib.c | 14 +++-- src/lj_lib.h | 4 -- src/lj_meta.c | 12 +++-- src/lj_obj.c | 4 +- src/lj_obj.h | 63 ++++++++++++++++++++-- src/lj_parse.c | 129 ++++++++++++++++++++++++++++++++++------------ src/lj_snap.c | 2 +- src/lj_str.c | 79 +++++++++++++++++++--------- src/lj_str.h | 8 ++- src/lj_tab.c | 33 ++++++++---- 23 files changed, 403 insertions(+), 189 deletions(-) diff --git a/src/lib_base.c b/src/lib_base.c index 1a9a6df2..746a4fd6 100644 --- a/src/lib_base.c +++ b/src/lib_base.c @@ -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<nomm = (uint8_t)(~(1u<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; } diff --git a/src/lib_jit.c b/src/lib_jit.c index 66a00523..8f809875 100644 --- a/src/lib_jit.c +++ b/src/lib_jit.c @@ -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. */ diff --git a/src/lib_math.c b/src/lib_math.c index 79d91e73..46841e08 100644 --- a/src/lib_math.c +++ b/src/lib_math.c @@ -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; diff --git a/src/lib_string.c b/src/lib_string.c index 0b1c98a9..61f73060 100644 --- a/src/lib_string.c +++ b/src/lib_string.c @@ -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<nomm = (uint8_t)(~(1u<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; diff --git a/src/lj_api.c b/src/lj_api.c index 92699078..f33748ce 100644 --- a/src/lj_api.c +++ b/src/lj_api.c @@ -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: diff --git a/src/lj_ctype.c b/src/lj_ctype.c index 585039ef..956f0a09 100644 --- a/src/lj_ctype.c +++ b/src/lj_ctype.c @@ -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)) { diff --git a/src/lj_def.h b/src/lj_def.h index ac457cf5..f6f03318 100644 --- a/src/lj_def.h +++ b/src/lj_def.h @@ -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)) diff --git a/src/lj_dispatch.c b/src/lj_dispatch.c index a8aa0731..0b14e21c 100644 --- a/src/lj_dispatch.c +++ b/src/lj_dispatch.c @@ -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); diff --git a/src/lj_err.c b/src/lj_err.c index 12f32af2..2503c218 100644 --- a/src/lj_err.c +++ b/src/lj_err.c @@ -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 diff --git a/src/lj_func.c b/src/lj_func.c index 83dab3b1..b3564091 100644 --- a/src/lj_func.c +++ b/src/lj_func.c @@ -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)); diff --git a/src/lj_lex.c b/src/lj_lex.c index ac0d1e95..78458572 100644 --- a/src/lj_lex.c +++ b/src/lj_lex.c @@ -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); } } diff --git a/src/lj_lib.c b/src/lj_lib.c index a6681f2b..930e59a0 100644 --- a/src/lj_lib.c +++ b/src/lj_lib.c @@ -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) diff --git a/src/lj_lib.h b/src/lj_lib.h index b9bd4c2d..ae4be384 100644 --- a/src/lj_lib.h +++ b/src/lj_lib.h @@ -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]) diff --git a/src/lj_meta.c b/src/lj_meta.c index 0df1de08..32024e85 100644 --- a/src/lj_meta.c +++ b/src/lj_meta.c @@ -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<nomm |= (uint8_t)(1u<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 */ } diff --git a/src/lj_obj.c b/src/lj_obj.c index 60f5dd3a..1476f0b2 100644 --- a/src/lj_obj.c +++ b/src/lj_obj.c @@ -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); } diff --git a/src/lj_obj.h b/src/lj_obj.h index 1bd50809..88289f3e 100644 --- a/src/lj_obj.h +++ b/src/lj_obj.h @@ -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. */ diff --git a/src/lj_parse.c b/src/lj_parse.c index 0f5577e1..858891d2 100644 --- a/src/lj_parse.c +++ b/src/lj_parse.c @@ -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: diff --git a/src/lj_snap.c b/src/lj_snap.c index fa2a20e0..e04da81f 100644 --- a/src/lj_snap.c +++ b/src/lj_snap.c @@ -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 diff --git a/src/lj_str.c b/src/lj_str.c index 20049ab3..dea02858 100644 --- a/src/lj_str.c +++ b/src/lj_str.c @@ -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 '%': diff --git a/src/lj_str.h b/src/lj_str.h index 26b932e0..406e2522 100644 --- a/src/lj_str.h +++ b/src/lj_str.h @@ -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); diff --git a/src/lj_tab.c b/src/lj_tab.c index d64a0426..c8e4efe1 100644 --- a/src/lj_tab.c +++ b/src/lj_tab.c @@ -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)) {