This commit is contained in:
Sasha Szpakowski
2026-07-23 21:14:56 -03:00
parent 774ba85a81
commit f253a9ac78
39 changed files with 1537 additions and 248 deletions
+1 -1
View File
@@ -1 +1 @@
1781602682
1784580905
+29 -1
View File
@@ -377,6 +377,7 @@ are allowed.</li>
<li><tt>pairs()</tt> and <tt>ipairs()</tt> check for <tt>__pairs</tt> and
<tt>__ipairs</tt>.</li>
<li><tt>coroutine.running()</tt> returns two results.</li>
<li><tt>string.find()</tt> returns <tt>nil</tt> for out-of-range position.</li>
<li><tt>table.pack()</tt> and <tt>table.unpack()</tt>
(same as <tt>unpack()</tt>).</li>
<li><tt>io.write()</tt> and <tt>file:write()</tt> return file handle
@@ -385,7 +386,6 @@ instead of <tt>true</tt>.</li>
exit status.</li>
<li><tt>debug.setmetatable()</tt> returns object.</li>
<li><tt>debug.getuservalue()</tt> and <tt>debug.setuservalue()</tt>.</li>
<li>Remove <tt>math.mod()</tt>, <tt>string.gfind()</tt>.</li>
<li><tt>package.searchers</tt>.</li>
<li><tt>module()</tt> returns the module table.</li>
</ul>
@@ -411,6 +411,34 @@ LuaJIT supports some extensions from Lua&nbsp;5.3:
</li>
</ul>
<h2 id="lj30_bp_syntax">Backported Syntax Extensions from LuaJIT 3.0</h2>
<p>
LuaJIT 2.1 supports some
<a href="https://github.com/LuaJIT/LuaJIT/issues/1475#issuecomment-4769582883"><span class="ext">&raquo;</span>&nbsp;syntax extensions backported from LuaJIT&nbsp;3.0</a>:
</p>
<ul>
<li>Bit Operators: unary <tt>~</tt>, binary <tt>&amp; | ~ &lt;&lt; &gt;&gt; ~&gt;&gt;</tt></li>
<li>Customary Operators: <tt>! && || !=</tt></li>
<li>Ternary <tt>?:</tt> conditional operator</li>
<li>Safe Navigation Operator <tt>?.</tt></li>
<li>nil-Coalescing Operator <tt>??</tt></li>
<li>Compound Assignment Operators: <tt>+= -= *= /= %= &amp;= |= ~= &lt;&lt;= &gt;&gt;= ~&gt;&gt;= ..=</tt></li>
<li><tt>continue</tt> Statement</li>
<li><tt>const</tt> Declaration</li>
<li>Short Function Expression</li>
<li>Underscores in Number Literals</li>
</ul>
<p>
Not backported are:
bit operator metamethods,
floor division operator <tt>//</tt>,
compound assignment metamethods,
named vararg parameter <tt>...name</tt>.
</p>
<p>
Bytecode that uses a bit operator can only be loaded by LuaJIT 2.1.1784535649 or higher.
</p>
<h2 id="exceptions">C++ Exception Interoperability</h2>
<p>
LuaJIT has built-in support for interoperating with C++&nbsp;exceptions.
+1 -1
View File
@@ -1409,7 +1409,7 @@ local map_op = {
dppd_3 = "rmio:660F3A41rMU",
dpps_3 = "rmio:660F3A40rMU",
extractps_3 = "mri/do:660F3A17RmU|rri/qo:660F3A17RXmU",
insertps_3 = "rrio:660F3A41rMU|rxi/od:",
insertps_3 = "rrio:660F3A21rMU|rxi/od:",
movntdqa_2 = "rxo:660F382ArM",
mpsadbw_3 = "rmio:660F3A42rMU",
packusdw_2 = "rmo:660F382BrM",
+1 -1
View File
@@ -372,7 +372,7 @@ ifneq ($(HOST_SYS),$(TARGET_SYS))
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX
else
ifeq (iOS,$(TARGET_SYS))
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX -DTARGET_OS_IPHONE=1
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OSX -DLUAJIT_TARGET_IPHONE=1
else
HOST_XCFLAGS+= -DLUAJIT_OS=LUAJIT_OS_OTHER
endif
+5 -4
View File
@@ -149,7 +149,8 @@ lj_mcode.o: lj_mcode.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_dispatch.h lj_bc.h lj_traceerr.h lj_prng.h lj_vm.h
lj_meta.o: lj_meta.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
lj_err.h lj_errmsg.h lj_buf.h lj_str.h lj_tab.h lj_meta.h lj_frame.h \
lj_bc.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h
lj_bc.h lj_vm.h lj_strscan.h lj_strfmt.h lj_lib.h lj_ctype.h lj_cdata.h \
lj_carith.h
lj_obj.o: lj_obj.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h
lj_opt_dce.o: lj_opt_dce.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_ir.h lj_jit.h lj_iropt.h
@@ -181,9 +182,9 @@ lj_profile.o: lj_profile.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_jit.h lj_ir.h lj_trace.h lj_traceerr.h lj_profile.h luajit.h
lj_record.o: lj_record.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_meta.h lj_frame.h lj_bc.h \
lj_ctype.h lj_gc.h lj_ff.h lj_ffdef.h lj_debug.h lj_ir.h lj_jit.h \
lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h lj_traceerr.h \
lj_record.h lj_ffrecord.h lj_snap.h lj_vm.h lj_prng.h
lj_ctype.h lj_gc.h lj_crecord.h lj_jit.h lj_ir.h lj_ffrecord.h lj_ff.h \
lj_ffdef.h lj_debug.h lj_ircall.h lj_iropt.h lj_trace.h lj_dispatch.h \
lj_traceerr.h lj_record.h lj_snap.h lj_vm.h lj_prng.h
lj_serialize.o: lj_serialize.c lj_obj.h lua.h luaconf.h lj_def.h \
lj_arch.h lj_err.h lj_errmsg.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \
lj_udata.h lj_ctype.h lj_cdata.h lj_ir.h lj_serialize.h
+1 -1
View File
@@ -230,6 +230,7 @@ LJLIB_CF(os_date)
LJLIB_CF(os_time)
{
time_t t;
errno = 0;
if (lua_isnoneornil(L, 1)) { /* called without args? */
t = time(NULL); /* get current time */
} else {
@@ -243,7 +244,6 @@ LJLIB_CF(os_time)
ts.tm_mon = (int)((unsigned int)getfield(L, "month", -1) - 1u);
ts.tm_year = (int)((unsigned int)getfield(L, "year", -1) - 1900u);
ts.tm_isdst = getboolfield(L, "isdst");
errno = 0;
t = mktime(&ts);
}
if (t == (time_t)(-1) && errno != 0)
+1 -1
View File
@@ -127,7 +127,7 @@
#define LJ_TARGET_POSIX (LUAJIT_OS > LUAJIT_OS_WINDOWS)
#define LJ_TARGET_DLOPEN LJ_TARGET_POSIX
#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
#if (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || LUAJIT_TARGET_IPHONE
#define LJ_TARGET_IOS 1
#else
#define LJ_TARGET_IOS 0
+2 -1
View File
@@ -1549,7 +1549,8 @@ static void asm_bitshift(ASMState *as, IRIns *ir, A64Ins ai, A64Shift sh)
int32_t shmask = irt_is64(ir->t) ? 63 : 31;
if (irref_isk(ir->op2)) { /* Constant shifts. */
Reg left, dest = ra_dest(as, ir, RSET_GPR);
int32_t shift = (IR(ir->op2)->i & shmask);
IRIns *irr = IR(ir->op2);
int32_t shift = ((irr->o == IR_KINT ? irr->i : (int32_t)ir_kint64(irr)->u64) & shmask);
IRIns *irl = IR(ir->op1);
if (shmask == 63) ai += A64I_UBFMx - A64I_UBFMw;
+2 -1
View File
@@ -2089,7 +2089,8 @@ static void asm_bitshift(ASMState *as, IRIns *ir, MIPSIns mi, MIPSIns mik)
{
Reg dest = ra_dest(as, ir, RSET_GPR);
if (irref_isk(ir->op2)) { /* Constant shifts. */
uint32_t shift = (uint32_t)IR(ir->op2)->i;
IRIns *irr = IR(ir->op2);
uint32_t shift = (uint32_t)(LJ_32 || irr->o == IR_KINT) ? (uint32_t)irr->i : (uint32_t)ir_kint64(irr)->u64;
if (LJ_64 && irt_is64(ir->t)) mik |= (shift & 32) ? MIPSI_D32 : MIPSI_D;
emit_dta(as, mik, dest, ra_hintalloc(as, ir->op1, dest, RSET_GPR),
(shift & 31));
+10 -6
View File
@@ -1112,10 +1112,12 @@ static void asm_tvptr(ASMState *as, Reg dest, IRRef ref, MSize mode)
} else {
#if LJ_GC64
if (irref_isk(ref)) {
Reg tmp;
TValue k;
lj_ir_kvalue(as->J->L, &k, ir);
emit_movmroi(as, dest, 4, k.u32.hi);
emit_movmroi(as, dest, 0, k.u32.lo);
tmp = ra_scratch(as, rset_exclude(RSET_GPR, dest));
emit_rmro(as, XO_MOVto, tmp|REX_64, dest, 0);
emit_loadu64(as, tmp, k.u64);
} else {
/* TODO: 64 bit store + 32 bit load-modify-store is suboptimal. */
Reg src = ra_alloc1(as, ref, rset_exclude(RSET_GPR, dest));
@@ -2318,9 +2320,10 @@ static void asm_bitshift(ASMState *as, IRIns *ir, x86Shift xs, x86Op xv)
IRIns *irr = IR(rref);
Reg dest;
if (irref_isk(rref)) { /* Constant shifts. */
int shift;
int32_t shift;
dest = ra_dest(as, ir, RSET_GPR);
shift = irr->i & (irt_is64(ir->t) ? 63 : 31);
shift = (LJ_32 || irr->o == IR_KINT) ? irr->i : (int32_t)ir_kint64(irr)->u64;
shift &= (irt_is64(ir->t) ? 63 : 31);
if (!xv && shift && (as->flags & JIT_F_BMI2)) {
Reg left = asm_fuseloadm(as, ir->op1, RSET_GPR, irt_is64(ir->t));
if (left != dest) { /* BMI2 rotate right by constant. */
@@ -2786,8 +2789,9 @@ static void asm_stack_restore(ASMState *as, SnapShot *snap)
emit_i32(as, -1);
emit_rmro(as, XO_MOVmi, REX_64, RID_BASE, ofs);
} else {
emit_movmroi(as, RID_BASE, ofs+4, k.u32.hi);
emit_movmroi(as, RID_BASE, ofs, k.u32.lo);
Reg tmp = ra_scratch(as, rset_exclude(RSET_GPR, RID_BASE));
emit_rmro(as, XO_MOVto, tmp|REX_64, RID_BASE, ofs);
emit_loadu64(as, tmp, k.u64);
}
#else
} else if (!irt_ispri(ir->t)) {
+10 -1
View File
@@ -98,7 +98,7 @@
_(UNM, dst, ___, var, unm) \
_(LEN, dst, ___, var, len) \
\
/* Binary ops. ORDER OPR. VV last, POW must be next. */ \
/* Binary ops. ORDER OPR. ORDER ARITH. VV last, POW must be next. */ \
_(ADDVN, dst, var, num, add) \
_(SUBVN, dst, var, num, sub) \
_(MULVN, dst, var, num, mul) \
@@ -186,6 +186,15 @@
\
_(JMP, rbase, ___, jump, ___) \
\
/* Bit operators. ORDER OPR. ORDER BIT. */ \
_(BNOT, dst, ___, var, ___) \
_(BAND, dst, var, var, ___) \
_(BOR, dst, var, var, ___) \
_(BXOR, dst, var, var, ___) \
_(BSHL, dst, var, var, ___) \
_(BSHR, dst, var, var, ___) \
_(BSAR, dst, var, var, ___) \
\
/* Function headers. I/J = interp/JIT, F/V/C = fixarg/vararg/C func. */ \
_(FUNCF, rbase, ___, ___, ___) \
_(IFUNCF, rbase, ___, ___, ___) \
+2 -1
View File
@@ -43,8 +43,9 @@
#define BCDUMP_F_STRIP 0x02
#define BCDUMP_F_FFI 0x04
#define BCDUMP_F_FR2 0x08
#define BCDUMP_F_BITOP 0x10
#define BCDUMP_F_KNOWN (BCDUMP_F_FR2*2-1)
#define BCDUMP_F_KNOWN (BCDUMP_F_BITOP*2-1)
#define BCDUMP_F_DETERMINISTIC 0x80000000
+3 -2
View File
@@ -340,7 +340,7 @@ static void bcwrite_proto(BCWriteCtx *ctx, GCproto *pt)
p += 5; /* Leave room for final size. */
/* Write prototype header. */
*p++ = (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI));
*p++ = (pt->flags & (PROTO_CHILD|PROTO_VARARG|PROTO_FFI|PROTO_BITOP));
*p++ = pt->numparams;
*p++ = pt->framesize;
*p++ = pt->sizeuv;
@@ -397,7 +397,8 @@ static void bcwrite_header(BCWriteCtx *ctx)
*p++ = BCDUMP_VERSION;
*p++ = (ctx->flags & (BCDUMP_F_STRIP | BCDUMP_F_FR2)) +
LJ_BE*BCDUMP_F_BE +
((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0);
((ctx->pt->flags & PROTO_FFI) ? BCDUMP_F_FFI : 0) +
((ctx->pt->flags & PROTO_BITOP) ? BCDUMP_F_BITOP : 0);
if (!(ctx->flags & BCDUMP_F_STRIP)) {
p = lj_strfmt_wuleb128(p, len);
p = lj_buf_wmem(p, name, len);
+31
View File
@@ -353,6 +353,37 @@ uint64_t lj_carith_check64(lua_State *L, int narg, CTypeID *id)
}
}
/* Check bit operator arguments. No coercion from strings. */
uint64_t lj_carith_checkbit64(lua_State *L, cTValue *o, CTypeID *id)
{
if (tviscdata(o)) {
CTState *cts = ctype_cts(L);
uint8_t *sp = (uint8_t *)cdataptr(cdataV(o));
CTypeID sid = cdataV(o)->ctypeid;
CType *s = ctype_get(cts, sid);
uint64_t x;
if (ctype_isref(s->info)) {
sp = *(void **)sp;
sid = ctype_cid(s->info);
}
s = ctype_raw(cts, sid);
if (ctype_isenum(s->info)) s = ctype_child(cts, s);
if ((s->info & (CTMASK_NUM|CTF_BOOL|CTF_FP|CTF_UNSIGNED)) ==
CTINFO(CT_NUM, CTF_UNSIGNED) && s->size == 8)
*id = CTID_UINT64; /* Use uint64_t, since it has the highest rank. */
else if (!*id)
*id = CTID_INT64; /* Use int64_t, unless already set. */
lj_cconv_ct_ct(cts, ctype_get(cts, *id), s,
(uint8_t *)&x, sp, 0);
return x;
} else if (LJ_LIKELY(tvisint(o))) {
return (uint64_t)intV(o); /* Sign-extended. */
} else {
if (!tvisnum(o)) lj_err_optype(L, o, LJ_ERR_OPARITH);
return (uint64_t)lj_num2bit(numV(o)); /* Sign-extended. */
}
}
/* -- 64 bit integer arithmetic helpers ----------------------------------- */
#if LJ_32 && LJ_HASJIT
+1
View File
@@ -21,6 +21,7 @@ LJ_FUNC uint64_t lj_carith_ror64(uint64_t x, int32_t sh);
#endif
LJ_FUNC uint64_t lj_carith_shift64(uint64_t x, int32_t sh, int op);
LJ_FUNC uint64_t lj_carith_check64(lua_State *L, int narg, CTypeID *id);
LJ_FUNC uint64_t lj_carith_checkbit64(lua_State *L, cTValue *o, CTypeID *id);
#if LJ_32 && LJ_HASJIT
LJ_FUNC int64_t lj_carith_mul64(int64_t x, int64_t k);
+1 -1
View File
@@ -1091,7 +1091,7 @@ static int ccall_set_args(lua_State *L, CTState *cts, CType *ct,
if (CCALL_ALIGN_STACKARG) { /* Align argument on stack. */
MSize align = (1u << ctype_align(ccall_struct_align(cts, d))) - 1;
#if LJ_TARGET_ARM64 && LJ_TARGET_OSX
isva = ctype_isstruct(d->info);
isva |= ctype_isstruct(d->info);
#endif
if (rp || (CCALL_PACK_STACKARG && isva && align < CTSIZE_PTR-1))
align = CTSIZE_PTR-1;
+4
View File
@@ -704,6 +704,10 @@ static void callback_conv_result(CTState *cts, lua_State *L, TValue *o)
if (ctr->size <= 4 &&
(LJ_ABI_SOFTFP || ctype_isinteger_or_bool(ctr->info)))
*(int64_t *)dp = (int64_t)*(int32_t *)dp;
#elif LJ_TARGET_X64
/* Always zero-extend results to 64 bits. */
if (ctr->size <= 4 && ctype_isinteger_or_bool(ctr->info))
*(uint64_t *)dp = (uint64_t)*(uint32_t *)dp;
#endif
#if LJ_TARGET_X86
if (ctype_isfp(ctr->info))
+25 -10
View File
@@ -1884,24 +1884,23 @@ int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd)
return 0;
}
int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd)
int recff_bit64_shift(jit_State *J, TRef *rb, TRef *rc,
TValue *rbv, TValue *rcv, IROp op)
{
CTState *cts = ctype_ctsG(J2G(J));
CTypeID id;
TRef tsh = 0;
if (J->base[0] && tref_iscdata(J->base[1])) {
tsh = crec_bit64_arg(J, ctype_get(cts, CTID_INT64),
J->base[1], &rd->argv[1]);
if (*rb && tref_iscdata(*rc)) {
tsh = crec_bit64_arg(J, ctype_get(cts, CTID_INT64), *rc, rcv);
if (LJ_32 && !tref_isinteger(tsh))
tsh = emitconv(tsh, IRT_INT, tref_type(tsh), 0);
J->base[1] = tsh;
*rc = tsh;
}
id = crec_bit64_type(cts, &rd->argv[0]);
id = crec_bit64_type(cts, rbv);
if (id) {
TRef tr = crec_bit64_arg(J, ctype_get(cts, id), J->base[0], &rd->argv[0]);
uint32_t op = rd->data;
TRef tr = crec_bit64_arg(J, ctype_get(cts, id), *rb, rbv);
IRType t;
if (!tsh) tsh = lj_opt_narrow_tobit(J, J->base[1]);
if (!tsh) tsh = lj_opt_narrow_tobit(J, *rc);
t = tref_isinteger(tsh) ? IRT_INT : tref_type(tsh);
if (!(op < IR_BROL ? LJ_TARGET_MASKSHIFT : LJ_TARGET_MASKROT) &&
!tref_isk(tsh))
@@ -1913,7 +1912,7 @@ int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd)
}
#endif
tr = emitir(IRT(op, id-CTID_INT64+IRT_I64), tr, tsh);
J->base[0] = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
*rb = emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
return 1;
}
return 0;
@@ -1955,6 +1954,22 @@ TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr)
return lj_ir_call(J, IRCALL_lj_strfmt_putfxint, hdr, lj_ir_kint(J, sf), tr);
}
TRef recff_bit64_bitop(jit_State *J, TRef rb, TRef rc,
TValue *rbv, TValue *rcv, IROp op)
{
CTState *cts = ctype_ctsG(J2G(J));
CTypeID id = crec_bit64_type(cts, rbv);
CTypeID id2 = rcv ? crec_bit64_type(cts, rcv) : 0;
CType *ct;
TRef tr, tr2;
if (id < id2) id = id2;
ct = ctype_get(cts, id);
tr = crec_bit64_arg(J, ct, rb, rbv);
tr2 = rcv ? crec_bit64_arg(J, ct, rc, rcv) : 0;
tr = emitir(IRT(op, id-CTID_INT64+IRT_I64), tr, tr2);
return emitir(IRTG(IR_CNEWI, IRT_CDATA), lj_ir_kint(J, id), tr);
}
/* -- Miscellaneous library functions ------------------------------------- */
void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd)
+4 -1
View File
@@ -29,8 +29,11 @@ LJ_FUNC void LJ_FASTCALL recff_ffi_gc(jit_State *J, RecordFFData *rd);
LJ_FUNC void LJ_FASTCALL recff_bit64_tobit(jit_State *J, RecordFFData *rd);
LJ_FUNC int LJ_FASTCALL recff_bit64_unary(jit_State *J, RecordFFData *rd);
LJ_FUNC int LJ_FASTCALL recff_bit64_nary(jit_State *J, RecordFFData *rd);
LJ_FUNC int LJ_FASTCALL recff_bit64_shift(jit_State *J, RecordFFData *rd);
LJ_FUNC int recff_bit64_shift(jit_State *J, TRef *rb, TRef *rc,
TValue *rbv, TValue *rcv, IROp op);
LJ_FUNC TRef recff_bit64_tohex(jit_State *J, RecordFFData *rd, TRef hdr);
LJ_FUNC TRef recff_bit64_bitop(jit_State *J, TRef rb, TRef rc,
TValue *rbv, TValue *rcv, IROp op);
LJ_FUNC void LJ_FASTCALL lj_crecord_tonumber(jit_State *J, RecordFFData *rd);
LJ_FUNC TRef lj_crecord_loadiu64(jit_State *J, TRef tr, cTValue *o);
+1
View File
@@ -49,6 +49,7 @@ extern double __divdf3(double a, double b);
_(lj_dispatch_profile) _(lj_err_throw) \
_(lj_ffh_coroutine_wrap_err) _(lj_func_closeuv) _(lj_func_newL_gc) \
_(lj_gc_barrieruv) _(lj_gc_step) _(lj_gc_step_fixtop) _(lj_meta_arith) \
_(lj_meta_bitop) \
_(lj_meta_call) _(lj_meta_cat) _(lj_meta_comp) _(lj_meta_equal) \
_(lj_meta_for) _(lj_meta_istype) _(lj_meta_len) _(lj_meta_tget) \
_(lj_meta_tset) _(lj_state_growstack) _(lj_strfmt_number) \
+4
View File
@@ -140,9 +140,13 @@ ERRDEF(XDOTS, "cannot use " LUA_QL("...") " outside a vararg function")
ERRDEF(XSYNTAX, "syntax error")
ERRDEF(XFOR, LUA_QL("=") " or " LUA_QL("in") " expected")
ERRDEF(XBREAK, "no loop to break")
ERRDEF(XCONT, "no loop to continue")
ERRDEF(XLUNDEF, "undefined label " LUA_QS)
ERRDEF(XLDUP, "duplicate label " LUA_QS)
ERRDEF(XGSCOPE, "<goto %s> jumps into the scope of local " LUA_QS)
ERRDEF(XCSCOPE, "<continue> jumps into the scope of local " LUA_QS)
ERRDEF(XCONSTA, "attempt to assign to const variable " LUA_QS)
ERRDEF(XCONSTR, "attempt to re-declare const variable " LUA_QS)
/* Bytecode reader errors. */
ERRDEF(BCFMT, "cannot load incompatible bytecode")
+1 -1
View File
@@ -745,7 +745,7 @@ static void LJ_FASTCALL recff_bit_nary(jit_State *J, RecordFFData *rd)
static void LJ_FASTCALL recff_bit_shift(jit_State *J, RecordFFData *rd)
{
#if LJ_HASFFI
if (recff_bit64_shift(J, rd))
if (recff_bit64_shift(J, &J->base[0], &J->base[1], &rd->argv[0], &rd->argv[1], rd->data))
return;
#endif
{
+1 -1
View File
@@ -53,7 +53,7 @@
_(KINT64, N , cst, ___) \
_(KSLOT, N , ref, lit) \
\
/* Bit ops. */ \
/* Bit ops. ORDER BIT */ \
_(BNOT, N , ref, ___) \
_(BSWAP, N , ref, ___) \
_(BAND, C , ref, ref) \
+41 -8
View File
@@ -97,12 +97,18 @@ static void lex_number(LexState *ls, TValue *tv)
StrScanFmt fmt;
LexChar c, xp = 'e';
lj_assertLS(lj_char_isdigit(ls->c), "bad usage");
if ((c = ls->c) == '0' && (lex_savenext(ls) | 0x20) == 'x')
xp = 'p';
if ((c = ls->c) == '0') {
lex_save(ls, c);
do { c = lex_next(ls); } while (c == '_');
if ((c | 0x20) == 'x') xp = 'p';
}
while (lj_char_isident(ls->c) || ls->c == '.' ||
((ls->c == '-' || ls->c == '+') && (c | 0x20) == xp)) {
c = ls->c;
lex_savenext(ls);
if (LJ_LIKELY(ls->c != '_')) {
c = ls->c;
lex_save(ls, ls->c);
}
lex_next(ls);
}
lex_save(ls, '\0');
fmt = lj_strscan_scan((const uint8_t *)ls->sb.b, sbuflen(&ls->sb)-1, tv,
@@ -321,7 +327,9 @@ static LexToken lex_scan(LexState *ls, TValue *tv)
continue;
case '-':
lex_next(ls);
if (ls->c != '-') return '-';
if (ls->c != '-') {
if (ls->c != '>') return '-'; else { lex_next(ls); return TK_arrow; }
}
lex_next(ls);
if (ls->c == '[') { /* Long comment "--[=*[...]=*]". */
int sep = lex_skipeq(ls);
@@ -353,16 +361,41 @@ static LexToken lex_scan(LexState *ls, TValue *tv)
if (ls->c != '=') return '='; else { lex_next(ls); return TK_eq; }
case '<':
lex_next(ls);
if (ls->c != '=') return '<'; else { lex_next(ls); return TK_le; }
if (ls->c == '=') { lex_next(ls); return TK_le; }
if (ls->c == '<') { lex_next(ls); return TK_shl; }
return '<';
case '>':
lex_next(ls);
if (ls->c != '=') return '>'; else { lex_next(ls); return TK_ge; }
if (ls->c == '=') { lex_next(ls); return TK_ge; }
if (ls->c == '>') { lex_next(ls); return TK_shr; }
return '>';
case '~':
lex_next(ls);
if (ls->c != '=') return '~'; else { lex_next(ls); return TK_ne; }
if (ls->c == '=') { lex_next(ls); return TK_ne; }
if (ls->c == '>') {
lex_next(ls);
if (ls->c != '>') lj_lex_error(ls, '~', LJ_ERR_XSYMBOL);
lex_next(ls);
return TK_sar;
}
return '~';
case '!':
lex_next(ls);
if (ls->c != '=') return '!'; else { lex_next(ls); return TK_ne_; }
case ':':
lex_next(ls);
if (ls->c != ':') return ':'; else { lex_next(ls); return TK_label; }
case '?':
lex_next(ls);
if (ls->c == '.') { lex_next(ls); return TK_nav; }
if (ls->c == '?') { lex_next(ls); return TK_coal; }
return '?';
case '&':
lex_next(ls);
if (ls->c != '&') return '&'; else { lex_next(ls); return TK_and_; }
case '|':
lex_next(ls);
if (ls->c != '|') return '|'; else { lex_next(ls); return TK_or_; }
case '"':
case '\'':
lex_string(ls, tv);
+11 -1
View File
@@ -13,10 +13,12 @@
/* Lua lexer tokens. */
#define TKDEF(_, __) \
_(and) _(break) _(do) _(else) _(elseif) _(end) _(false) \
_(and) _(break) _(const) _(continue) _(do) _(else) _(elseif) _(end) _(false) \
_(for) _(function) _(goto) _(if) _(in) _(local) _(nil) _(not) _(or) \
_(repeat) _(return) _(then) _(true) _(until) _(while) \
__(concat, ..) __(dots, ...) __(eq, ==) __(ge, >=) __(le, <=) __(ne, ~=) \
__(nav, ?.) __(coal, \?\?) __(shl, <<) __(shr, >>) __(sar, ~>>) \
__(and_, &&) __(or_, ||) __(ne_, !=) __(arrow, ->) \
__(label, ::) __(number, <number>) __(name, <name>) __(string, <string>) \
__(eof, <eof>)
@@ -39,6 +41,12 @@ typedef struct BCInsLine {
BCLine line; /* Line number for this bytecode. */
} BCInsLine;
/* Index into variable stack. */
typedef uint16_t VarIndex;
#define LJ_VINDEX_HSIZE 32 /* Hash table size. Must be a power of 2. */
#define LJ_VINDEX_MASK (LJ_VINDEX_HSIZE-1)
/* Info for local variables. Only used during bytecode generation. */
typedef struct VarInfo {
GCRef name; /* Local variable name or goto/label name. */
@@ -46,6 +54,7 @@ typedef struct VarInfo {
BCPos endpc; /* First point where the local variable is dead. */
uint8_t slot; /* Variable slot. */
uint8_t info; /* Variable/goto/label info. */
VarIndex prev; /* Previous entry in variable hash chain. */
} VarInfo;
/* Lua lexer state. */
@@ -75,6 +84,7 @@ typedef struct LexState {
uint32_t level; /* Syntactical nesting level. */
int endmark; /* Trust bytecode end marker, even if not at EOF. */
int fr2; /* Generate bytecode for LJ_FR2 mode. */
VarIndex vhash[LJ_VINDEX_HSIZE]; /* Variable hash chain anchors. */
} LexState;
LJ_FUNC int lj_lex_setup(lua_State *L, LexState *ls);
+75
View File
@@ -22,6 +22,11 @@
#include "lj_strscan.h"
#include "lj_strfmt.h"
#include "lj_lib.h"
#if LJ_HASFFI
#include "lj_ctype.h"
#include "lj_cdata.h"
#include "lj_carith.h"
#endif
/* -- Metamethod handling ------------------------------------------------- */
@@ -234,6 +239,76 @@ TValue *lj_meta_arith(lua_State *L, TValue *ra, cTValue *rb, cTValue *rc,
}
}
/* Helper for bit operators. No bitop metamethods in v2.1. */
void lj_meta_bitop(lua_State *L, TValue *ra, cTValue *rb, cTValue *rc, BCReg op)
{
#if LJ_HASFFI
CTypeID id = 0, id_ignore = 0;
uint64_t b = lj_carith_checkbit64(L, rb, &id);
uint64_t c = lj_carith_checkbit64(L, rc, op >= BC_BSHL ? &id_ignore : &id);
if (id) {
if (tvisnum(rb)) {
b = id == CTID_UINT64 ? lj_num2u64(numV(rb)) : lj_num2i64(numV(rb));
}
if (tvisnum(rc)) {
c = id == CTID_UINT64 ? lj_num2u64(numV(rc)) : lj_num2i64(numV(rc));
}
}
switch (op) {
case BC_BNOT: b = ~b; break;
case BC_BAND: b &= c; break;
case BC_BOR: b |= c; break;
case BC_BXOR: b ^= c; break;
default:
if (id) {
b = lj_carith_shift64(b, (int32_t)c, op-BC_BSHL);
} else if (op == BC_BSHL) {
b = (uint64_t)((uint32_t)b << ((uint32_t)c & 31));
} else if (op == BC_BSHR) {
b = (uint64_t)((uint32_t)b >> ((uint32_t)c & 31));
} else {
lj_assertL(op == BC_BSAR, "bad bytecode op %d", op);
b = (uint64_t)(uint32_t)((int32_t)b >> ((uint32_t)c & 31));
}
break;
}
if (id) {
GCcdata *cd = lj_cdata_new_(L, id, 8);
*(uint64_t *)cdataptr(cd) = b;
setcdataV(L, ra, cd);
} else {
setintV(ra, (int32_t)b);
}
#else
#if LJ_DUALNUM
uint32_t b = 0, c = 0;
if (tvisint(rb)) b = (uint32_t)intV(rb);
else if (tvisnum(rb)) b = (uint32_t)lj_num2bit(numV(rb));
else goto err;
if (tvisint(rc)) c = (uint32_t)intV(rc);
else if (tvisnum(rc)) c = (uint32_t)lj_num2bit(numV(rc));
else goto err;
switch (op) {
case BC_BNOT: b = ~b; break;
case BC_BAND: b &= c; break;
case BC_BOR: b |= c; break;
case BC_BXOR: b ^= c; break;
case BC_BSHL: b <<= (c & 31); break;
case BC_BSHR: b >>= (c & 31); break;
case BC_BSAR: b = (uint32_t)((int32_t)b >> (c & 31)); break;
default:
lj_assertL(0, "bad bytecode op %d", op);
break;
}
setintV(ra, (int32_t)b);
return;
err:
#endif
UNUSED(ra); UNUSED(op);
lj_err_optype(L, tvisnumber(rb) ? rc : rb, LJ_ERR_OPARITH);
#endif
}
/* Helper for CAT. Coercion, iterative concat, __concat metamethod. */
TValue *lj_meta_cat(lua_State *L, TValue *top, int left)
{
+2
View File
@@ -26,6 +26,8 @@ LJ_FUNCA cTValue *lj_meta_tget(lua_State *L, cTValue *o, cTValue *k);
LJ_FUNCA TValue *lj_meta_tset(lua_State *L, cTValue *o, cTValue *k);
LJ_FUNCA TValue *lj_meta_arith(lua_State *L, TValue *ra, cTValue *rb,
cTValue *rc, BCReg op);
LJ_FUNCA void lj_meta_bitop(lua_State *L, TValue *ra, cTValue *rb,
cTValue *rc, BCReg op);
LJ_FUNCA TValue *lj_meta_cat(lua_State *L, TValue *top, int left);
LJ_FUNCA TValue * LJ_FASTCALL lj_meta_len(lua_State *L, cTValue *o);
LJ_FUNCA TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne);
+1
View File
@@ -401,6 +401,7 @@ typedef struct GCproto {
#define PROTO_FFI 0x04 /* Uses BC_KCDATA for FFI datatypes. */
#define PROTO_NOJIT 0x08 /* JIT disabled for this function. */
#define PROTO_ILOOP 0x10 /* Patched bytecode with ILOOP etc. */
#define PROTO_BITOP 0x80 /* Uses bit operator bytecodes. */
/* Only used during parsing. */
#define PROTO_HAS_RETURN 0x20 /* Already emitted a return. */
#define PROTO_FIXUP_RETURN 0x40 /* Need to fixup emitted returns. */
+1 -1
View File
@@ -382,8 +382,8 @@ static uint64_t kfold_int64arith(jit_State *J, uint64_t k1, uint64_t k2,
case IR_BSAR: k1 = (uint64_t)((int64_t)k1 >> (k2 & 63)); break;
case IR_BROL: k1 = lj_rol(k1, (k2 & 63)); break;
case IR_BROR: k1 = lj_ror(k1, (k2 & 63)); break;
default: lj_assertJ(0, "bad IR op %d", op); break;
#endif
default: lj_assertJ(0, "bad IR op %d", op); break;
}
return k1;
}
+578 -199
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -359,6 +359,7 @@ LUA_API void luaJIT_profile_stop(lua_State *L)
ProfileState *ps = &profile_state;
global_State *g = ps->g;
if (G(L) == g) { /* Only stop profiler if started by this VM. */
ps->g = NULL;
profile_timer_stop(ps);
g->hookmask &= ~HOOK_PROFILE;
lj_dispatch_update(g, 0);
@@ -368,7 +369,6 @@ LUA_API void luaJIT_profile_stop(lua_State *L)
#endif
lj_buf_free(g, &ps->sb);
ps->sb.w = ps->sb.e = NULL;
ps->g = NULL;
}
}
+40
View File
@@ -17,6 +17,7 @@
#include "lj_frame.h"
#if LJ_HASFFI
#include "lj_ctype.h"
#include "lj_crecord.h"
#endif
#include "lj_bc.h"
#include "lj_ff.h"
@@ -2505,6 +2506,45 @@ void lj_record_ins(jit_State *J)
rc = rec_mm_arith(J, &ix, MM_pow);
break;
/* -- Bit operators ----------------------------------------------------- */
case BC_BNOT:
#if LJ_HASFFI
if (tref_iscdata(rc)) {
rc = recff_bit64_bitop(J, rc, 0, rcv, NULL, IR_BNOT);
break;
}
#endif
rc = lj_opt_narrow_tobit(J, rc);
rc = emitir(IRTI(IR_BNOT), rc, 0);
break;
case BC_BAND: case BC_BOR: case BC_BXOR:
#if LJ_HASFFI
if (tref_iscdata(rb) || tref_iscdata(rc)) {
rc = recff_bit64_bitop(J, rb, rc, rbv, rcv, (int)op - (int)BC_BAND + (int)IR_BAND);
break;
}
#endif
recbit:
rb = lj_opt_narrow_tobit(J, rb);
rc = lj_opt_narrow_tobit(J, rc);
rc = emitir(IRTI((int)op - (int)BC_BAND + (int)IR_BAND), rb, rc);
break;
case BC_BSHL: case BC_BSHR: case BC_BSAR:
#if LJ_HASFFI
{
TRef xrb = rb, xrc = rc;
if (recff_bit64_shift(J, &xrb, &xrc, rbv, rcv, (int)op - (int)BC_BSHL + (int)IR_BSHL)) {
rc = xrb;
break;
}
rc = xrc; /* Shift amount may have been converted. */
}
#endif
goto recbit;
/* -- Miscellaneous ops ------------------------------------------------- */
case BC_CAT:
+75
View File
@@ -848,6 +848,26 @@ static void build_subroutines(BuildCtx *ctx)
#else
| b ->vmeta_binop // Binop call for compatibility.
#endif
|
|//-- Bit operator metamethods -------------------------------------------
|
|->vmeta_bnot:
| add CARG3, BASE, RC
| mov CARG4, CARG3
| b >1
|
|->vmeta_bitop:
| add CARG3, BASE, RB
| add CARG4, BASE, RC
|1:
| decode_OP OP, INS
| add CARG2, BASE, RA
| str BASE, L->base
| mov CARG1, L
| str PC, SAVE_PC
| str OP, ARG5
| bl extern lj_meta_bitop // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
| b ->cont_nop
|
|//-- Call metamethod ----------------------------------------------------
|
@@ -3376,6 +3396,61 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| ins_next3
break;
/* -- Bit ops ----------------------------------------------------------- */
case BC_BNOT:
| // RA = dst, RC = src
| lsl RC, RC, #3
| ldrd CARG12, [BASE, RC]
| checktp CARG1, LJ_TISNUM
| bne ->vmeta_bnot
| mvn CARG1, CARG1
| mvn CARG2, #~LJ_TISNUM
| ins_next1
| ins_next2
| strd CARG12, [BASE, RA]
| ins_next3
break;
|.macro ins_bitop, ins, shop
| decode_RB8 RB, INS
| decode_RC8 RC, INS
| // RA = dst*8, RB = src1*8, RC = src2*8
| ldrd CARG12, [BASE, RB]
| ldrd CARG34, [BASE, RC]
| checktp CARG2, LJ_TISNUM
| checktpeq CARG4, LJ_TISNUM
| bne ->vmeta_bitop
|.if shop == 1
| and CARG3, CARG3, #31
|.endif
| ins CARG1, CARG1, CARG3
| mvn CARG2, #~LJ_TISNUM
| ins_next1
| ins_next2
| strd CARG12, [BASE, RA]
| ins_next3
|.endmacro
case BC_BAND:
| ins_bitop and, 0
break;
case BC_BOR:
| ins_bitop orr, 0
break;
case BC_BXOR:
| ins_bitop eor, 0
break;
case BC_BSHL:
| ins_bitop lsl, 1
break;
case BC_BSHR:
| ins_bitop lsr, 1
break;
case BC_BSAR:
| ins_bitop asr, 1
break;
/* -- Constant ops ------------------------------------------------------ */
case BC_KSTR:
+64
View File
@@ -920,6 +920,25 @@ static void build_subroutines(BuildCtx *ctx)
#else
| b ->vmeta_binop // Binop call for compatibility.
#endif
|
|//-- Bit operator metamethods -------------------------------------------
|
|->vmeta_bnot:
| add CARG3, BASE, RC, lsl #3
| mov CARG4, CARG3
| b >1
|
|->vmeta_bitop:
| add CARG3, BASE, RB, lsl #3
| add CARG4, BASE, RC, lsl #3
|1:
| uxtb CARG5w, INSw
| add CARG2, BASE, RA, lsl #3
| str BASE, L->base
| mov CARG1, L
| str PC, SAVE_PC
| bl extern lj_meta_bitop // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
| b ->cont_nop
|
|//-- Call metamethod ----------------------------------------------------
|
@@ -2878,6 +2897,51 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| ins_next
break;
/* -- Bit ops ----------------------------------------------------------- */
case BC_BNOT:
| // RA = dst, RC = src
| ldr CARG1, [BASE, RC, lsl #3]
| checkint CARG1, ->vmeta_bnot
| mvn CARG1w, CARG1w
| add_TISNUM CARG1, CARG1
| str CARG1, [BASE, RA, lsl #3]
| ins_next
break;
|.macro ins_bitop, ins
| decode_RB RB, INS
| and RC, RC, #255
| // RA = dst, RB = src1, RC = src2
| ldr CARG1, [BASE, RB, lsl #3]
| ldr CARG2, [BASE, RC, lsl #3]
| checkint CARG1, ->vmeta_bitop
| checkint CARG2, ->vmeta_bitop
| ins CARG1w, CARG1w, CARG2w
| add_TISNUM CARG1, CARG1
| str CARG1, [BASE, RA, lsl #3]
| ins_next
|.endmacro
case BC_BAND:
| ins_bitop and
break;
case BC_BOR:
| ins_bitop orr
break;
case BC_BXOR:
| ins_bitop eor
break;
case BC_BSHL:
| ins_bitop lsl
break;
case BC_BSHR:
| ins_bitop lsr
break;
case BC_BSAR:
| ins_bitop asr
break;
/* -- Constant ops ------------------------------------------------------ */
case BC_KSTR:
+75
View File
@@ -981,6 +981,25 @@ static void build_subroutines(BuildCtx *ctx)
| b ->vmeta_binop // Binop call for compatibility.
|. nop
#endif
|
|//-- Bit operator metamethods -------------------------------------------
|
|->vmeta_bnot:
| move RC, RB
|
|->vmeta_bitop:
| load_got lj_meta_bitop
| decode_OP1 TMP0, INS
| sw BASE, L->base
| move CARG2, RA
| sw PC, SAVE_PC
| move CARG3, RB
| move CARG4, RC
| sw TMP0, ARG5
| call_intern lj_meta_bitop // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
|. move CARG1, L
| b ->cont_nop
|. nop
|
|//-- Call metamethod ----------------------------------------------------
|
@@ -3886,6 +3905,62 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| ins_next2
break;
/* -- Bit ops ----------------------------------------------------------- */
case BC_BNOT:
| // RA = dst*8, RD = src*8
| addu RB, BASE, RD
| lw TMP0, HI(RB)
| lw CRET1, LO(RB)
| bne TMP0, TISNUM, ->vmeta_bnot
|. addu RA, BASE, RA
| not CRET1, CRET1
| ins_next1
| sw TISNUM, HI(RA)
| sw CRET1, LO(RA)
| ins_next2
break;
|.macro ins_bitop, ins
| // RA = dst*8, RB = src1*8, RC = src2*8
| decode_RB8a RB, INS
| decode_RB8b RB
| decode_RDtoRC8 RC, RD
| addu RB, BASE, RB
| addu RC, BASE, RC
| lw TMP0, HI(RB)
| lw TMP1, HI(RC)
| lw CRET1, LO(RB)
| bne TMP0, TISNUM, ->vmeta_bitop
|. addu RA, BASE, RA
| lw CRET2, LO(RC)
| bne TMP1, TISNUM, ->vmeta_bitop
|. ins CRET1, CRET1, CRET2
| ins_next1
| sw TISNUM, HI(RA)
| sw CRET1, LO(RA)
| ins_next2
|.endmacro
case BC_BAND:
| ins_bitop and
break;
case BC_BOR:
| ins_bitop or
break;
case BC_BXOR:
| ins_bitop xor
break;
case BC_BSHL:
| ins_bitop sllv
break;
case BC_BSHR:
| ins_bitop srlv
break;
case BC_BSAR:
| ins_bitop srav
break;
/* -- Constant ops ------------------------------------------------------ */
case BC_KSTR:
+77
View File
@@ -1027,6 +1027,24 @@ static void build_subroutines(BuildCtx *ctx)
| b ->vmeta_binop // Binop call for compatibility.
|. nop
#endif
|
|//-- Bit operator metamethods -------------------------------------------
|
|->vmeta_bnot:
| move RC, RB
|
|->vmeta_bitop:
| load_got lj_meta_bitop
| sd BASE, L->base
| move CARG2, RA
| sd PC, SAVE_PC
| move CARG3, RB
| move CARG4, RC
| decode_OP1 CARG5, INS // CARG5 == RB.
| call_intern lj_meta_bitop // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
|. move CARG1, L
| b ->cont_nop
|. nop
|
|//-- Call metamethod ----------------------------------------------------
|
@@ -4113,6 +4131,65 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| ins_next2
break;
/* -- Bit ops ----------------------------------------------------------- */
case BC_BNOT:
| // RA = dst*8, RD = src*8
| daddu RB, BASE, RD
| ld CRET1, 0(RB)
| gettp TMP0, CRET1
| bne TMP0, TISNUM, ->vmeta_bnot
|. daddu RA, BASE, RA
| not CRET1, CRET1
| zextw CRET1, CRET1
| settp CRET1, TISNUM
| ins_next1
| sd CRET1, 0(RA)
| ins_next2
break;
|.macro ins_bitop, ins
| // RA = dst*8, RB = table*8, RC = key*8
| decode_RB8a RB, INS
| decode_RB8b RB
| decode_RDtoRC8 RC, RD
| daddu RB, BASE, RB
| daddu RC, BASE, RC
| ld CRET1, 0(RB)
| ld CRET2, 0(RC)
| gettp TMP0, CRET1
| daddu RA, BASE, RA
| bne TMP0, TISNUM, ->vmeta_bitop
|. gettp TMP1, CRET2
| sextw CRET1, CRET1
| bne TMP1, TISNUM, ->vmeta_bitop
|. ins CRET1, CRET1, CRET2
| zextw CRET1, CRET1
| settp CRET1, TISNUM
| ins_next1
| sd CRET1, 0(RA)
| ins_next2
|.endmacro
case BC_BAND:
| ins_bitop and
break;
case BC_BOR:
| ins_bitop or
break;
case BC_BXOR:
| ins_bitop xor
break;
case BC_BSHL:
| ins_bitop sllv
break;
case BC_BSHR:
| ins_bitop srlv
break;
case BC_BSAR:
| ins_bitop srav
break;
/* -- Constant ops ------------------------------------------------------ */
case BC_KSTR:
+100
View File
@@ -1268,6 +1268,25 @@ static void build_subroutines(BuildCtx *ctx)
#else
| b ->vmeta_binop // Binop call for compatibility.
#endif
|
|//-- Bit operator metamethods -------------------------------------------
|
|->vmeta_bnot:
| mr CARG3, RD
| mr CARG4, RD
| b >1
|
|->vmeta_bitop:
| mr CARG3, RB
| mr CARG4, RC
|1:
| add CARG2, BASE, RA
| stp BASE, L->base
| mr CARG1, L
| stw PC, SAVE_PC
| decode_OP1 CARG5, INS // Caveat: CARG5 overlaps INS.
| bl extern lj_meta_bitop // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
| b ->cont_nop
|
|//-- Call metamethod ----------------------------------------------------
|
@@ -4357,6 +4376,87 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| ins_next2
break;
/* -- Bit ops ----------------------------------------------------------- */
case BC_BNOT:
| lwzux CARG1, RD, BASE
|.if DUALNUM
| lwz CARG2, 4(RD)
| checknum cr0, CARG1
| bne ->vmeta_bnot
|.else
| lfd FARG1, 0(RD)
| checknum cr0, CARG1
| bge ->vmeta_bnot
| fadd FARG1, FARG1, TOBIT
| stfd FARG1, TMPD
| lwz CARG2, TMPD_LO
|.endif
| not CARG2, CARG2
|7:
|.if DUALNUM
| ins_next1
| stwux TISNUM, RA, BASE
| stw CARG2, 4(RA)
|.else
| tonum_u FARG1, CARG2
| ins_next1
| stfdx FARG1, BASE, RA
|.endif
| ins_next2
break;
|.macro ins_bitop, ins, shmod
| // RA = dst*8, RB = src1*8, RC = src2*8
| lwzux CARG1, RB, BASE
| lwzux CARG3, RC, BASE
|.if DUALNUM
| lwz CARG2, 4(RB)
| lwz CARG4, 4(RC)
| checknum cr0, CARG1
| checknum cr1, CARG3
| bne ->vmeta_bitop
| bne cr1, ->vmeta_bitop
|.else
| lfd FARG1, 0(RB)
| lfd FARG2, 0(RC)
| checknum cr0, CARG1
| checknum cr1, CARG3
| bge ->vmeta_bitop
| bge cr1, ->vmeta_bitop
| fadd FARG1, FARG1, TOBIT
| fadd FARG2, FARG2, TOBIT
| stfd FARG1, TMPD
| lwz CARG2, TMPD_LO
| stfd FARG2, TMPD
| lwz CARG4, TMPD_LO
|.endif
|.if shmod == 1
| rlwinm CARG4, CARG4, 0, 27, 31
|.endif
| ins CARG2, CARG2, CARG4
| b <7
|.endmacro
case BC_BAND:
| ins_bitop and, 0
break;
case BC_BOR:
| ins_bitop or, 0
break;
case BC_BXOR:
| ins_bitop xor, 0
break;
case BC_BSHL:
| ins_bitop slw, 1
break;
case BC_BSHR:
| ins_bitop srw, 1
break;
case BC_BSAR:
| ins_bitop sraw, 1
break;
/* -- Constant ops ------------------------------------------------------ */
case BC_KSTR:
+124 -1
View File
@@ -1092,6 +1092,47 @@ static void build_subroutines(BuildCtx *ctx)
#else
| jmp ->vmeta_binop // Binop call for compatibility.
#endif
|
|//-- Bit operator metamethods -------------------------------------------
|
|->vmeta_bnot:
| mov RB, RA
| lea RC, [BASE+RD*8]
| mov RA, RC
| jmp >2
|
|// Caveat: ra=RB rb=RC rc=RA.
|->vmeta_bitop:
|.if DUALNUM
| movzx RCd, PC_RB
| movzx RAd, PC_RC
|.endif
| lea RC, [BASE+RC*8]
| lea RA, [BASE+RA*8]
|2:
|.if X64WIN
| mov CARG3, RC
| mov CARG4, RA
| lea RA, [BASE+RB*8]
| movzx RC, PC_OP
| mov ARG5, RC
| mov L:RB, SAVE_L
| mov L:RB->base, BASE // Caveat: CARG2d == BASE.
| mov CARG2, RA
| mov CARG1, L:RB // Caveat: CARG1d == RA.
|.else
| lea CARG2, [BASE+RB*8]
| // CARG4 == RA.
| movzx CARG5, PC_OP
| mov L:CARG1, SAVE_L
| mov L:CARG1->base, BASE // Caveat: CARG3d == BASE.
| mov CARG3, RC
| mov L:RB, L:CARG1
|.endif
| mov SAVE_PC, PC
| call extern lj_meta_bitop // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
| mov BASE, L:RB->base
| jmp ->cont_nop
|
|//-- Call metamethod ----------------------------------------------------
|
@@ -3416,7 +3457,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|.if DUALNUM
| ins_arithdn intins
|.else
| ins_arith, sseins
| ins_arith sseins
|.endif
|.endmacro
@@ -3476,6 +3517,88 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| ins_next
break;
/* -- Bit ops ----------------------------------------------------------- */
case BC_BNOT:
| ins_AD // RA = dst, RD = src
|.if DUALNUM
| mov RB, [BASE+RD*8]
| checkint RB, ->vmeta_bnot
| not RBd
| setint RB
| mov [BASE+RA*8], RB
| ins_next
|.else
| checknumtp [BASE+RD*8], ->vmeta_bnot
| movsd xmm0, qword [BASE+RD*8]
| sseconst_tobit xmm1, RB
| addsd xmm0, xmm1
| movd RBd, xmm0
| not RBd
| cvtsi2sd xmm0, RBd
| movsd qword [BASE+RA*8], xmm0
| ins_next
|.endif
break;
|.macro ins_bitop, ins, shift
| ins_A // Really ins_ABC. RB = dst, RC = src1, RA = src2
| // Swap registers around to avoid reloading RA.
| mov RB, RA
| movzx RAd, RCL // Really src2 (C).
| movzx RCd, RCH // Really src1 (B).
|.if DUALNUM
| mov RA, [BASE+RA*8]
| mov RC, [BASE+RC*8]
| checkint RA, ->vmeta_bitop
| checkint RC, ->vmeta_bitop
|.if shift == 1
| ins RCd, cl // Assumes RA is ecx.
|.else
| ins RCd, RAd
|.endif
| setint RC
| mov [BASE+RB*8], RC
|.else
| checknumtp [BASE+RA*8], ->vmeta_bitop
| checknumtp [BASE+RC*8], ->vmeta_bitop
| movsd xmm0, qword [BASE+RA*8]
| movsd xmm1, qword [BASE+RC*8]
| sseconst_tobit xmm2, RC
| addsd xmm0, xmm2
| addsd xmm1, xmm2
| movd RAd, xmm0
| movd RCd, xmm1
|.if shift == 1
| ins RCd, cl // Assumes RA is ecx.
|.else
| ins RCd, RAd
|.endif
| cvtsi2sd xmm0, RCd
| movsd qword [BASE+RB*8], xmm0
|.endif
| ins_next
|.endmacro
case BC_BAND:
| ins_bitop and, 0
break;
case BC_BOR:
| ins_bitop or, 0
break;
case BC_BXOR:
| ins_bitop xor, 0
break;
case BC_BSHL:
| ins_bitop shl, 1
break;
case BC_BSHR:
| ins_bitop shr, 1
break;
case BC_BSAR:
| ins_bitop sar, 1
break;
/* -- Constant ops ------------------------------------------------------ */
case BC_KSTR:
+131 -1
View File
@@ -1337,6 +1337,53 @@ static void build_subroutines(BuildCtx *ctx)
#else
| jmp ->vmeta_binop // Binop call for compatibility.
#endif
|
|//-- Bit operator metamethods -------------------------------------------
|
|->vmeta_bnot:
| mov RB, RA
| lea RC, [BASE+RD*8]
| mov RA, RC
| jmp >2
|
|// Caveat: ra=RB rb=RC rc=RA.
|->vmeta_bitop:
| lea RC, [BASE+RC*8]
| lea RA, [BASE+RA*8]
|2:
|.if X64WIN
| mov CARG3d, RC
| mov CARG4d, RA
| lea RA, [BASE+RB*8]
| movzx RC, PC_OP
| mov ARG5d, RC
| mov L:RB, SAVE_L
| mov L:RB->base, BASE // Caveat: CARG2d == BASE.
| mov CARG2d, RA
| mov CARG1d, L:RB // Caveat: CARG1d == RA.
|.elif X64
| lea CARG2, [BASE+RB*8]
| // CARG4d == RA.
| movzx CARG5d, PC_OP
| mov L:CARG1d, SAVE_L
| mov L:CARG1d->base, BASE // Caveat: CARG3d == BASE.
| mov CARG3d, RC
| mov L:RB, L:CARG1d
|.else
| lea RB, [BASE+RB*8]
| mov ARG3, RC
| movzx RC, PC_OP
| mov ARG2, RB
| mov L:RB, SAVE_L
| mov ARG4, RA
| mov ARG5, RC
| mov ARG1, L:RB
| mov L:RB->base, BASE
|.endif
| mov SAVE_PC, PC
| call extern lj_meta_bitop // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
| mov BASE, L:RB->base
| jmp ->cont_nop
|
|//-- Call metamethod ----------------------------------------------------
|
@@ -4006,7 +4053,7 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
|.if DUALNUM
| ins_arithdn intins
|.else
| ins_arith, sseins
| ins_arith sseins
|.endif
|.endmacro
@@ -4092,6 +4139,89 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
| ins_next
break;
/* -- Bit ops ----------------------------------------------------------- */
case BC_BNOT:
| ins_AD // RA = dst, RD = src
|.if DUALNUM
| checkint RD, ->vmeta_bnot
| mov RB, [BASE+RD*8]
| not RB
| mov dword [BASE+RA*8+4], LJ_TISNUM
| mov dword [BASE+RA*8], RB
| ins_next
|.else
| checknum RD, ->vmeta_bnot
| movsd xmm0, qword [BASE+RD*8]
| sseconst_tobit xmm1, RBa
| addsd xmm0, xmm1
| movd RB, xmm0
| not RB
| cvtsi2sd xmm0, RB
| movsd qword [BASE+RA*8], xmm0
| ins_next
|.endif
break;
|.macro ins_bitop, ins, shift
| ins_A // Really ins_ABC. RB = dst, RC = src1, RA = src2
| // Swap registers around to avoid reloading RA.
| mov RB, RA
| movzx RA, RCL // Really src2 (C).
| movzx RC, RCH // Really src1 (B).
|.if DUALNUM
| checkint RA, ->vmeta_bitop
| checkint RC, ->vmeta_bitop
|.if shift == 1
| mov RA, [BASE+RA*8]
| mov RC, [BASE+RC*8]
| ins RC, cl // Assumes RA is ecx.
|.else
| mov RC, [BASE+RC*8]
| ins RC, [BASE+RA*8]
|.endif
| mov dword [BASE+RB*8+4], LJ_TISNUM
| mov dword [BASE+RB*8], RC
|.else
| checknum RA, ->vmeta_bitop
| checknum RC, ->vmeta_bitop
| movsd xmm0, qword [BASE+RA*8]
| movsd xmm1, qword [BASE+RC*8]
| sseconst_tobit xmm2, RCa
| addsd xmm0, xmm2
| addsd xmm1, xmm2
| movd RA, xmm0
| movd RC, xmm1
|.if shift == 1
| ins RC, cl // Assumes RA is ecx.
|.else
| ins RC, RA
|.endif
| cvtsi2sd xmm0, RC
| movsd qword [BASE+RB*8], xmm0
|.endif
| ins_next
|.endmacro
case BC_BAND:
| ins_bitop and, 0
break;
case BC_BOR:
| ins_bitop or, 0
break;
case BC_BXOR:
| ins_bitop xor, 0
break;
case BC_BSHL:
| ins_bitop shl, 1
break;
case BC_BSHR:
| ins_bitop shr, 1
break;
case BC_BSAR:
| ins_bitop sar, 1
break;
/* -- Constant ops ------------------------------------------------------ */
case BC_KSTR: