From a61df8efbe5bbe3726d65ad0800a3106ed3a8bf0 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 19 Jan 2010 16:58:26 +0100 Subject: [PATCH] Decouple guard vs. INT check vs. TYPECHECK semantics for SLOAD. --- lib/dump.lua | 3 ++- src/lj_asm.c | 6 ++++-- src/lj_ir.h | 1 + src/lj_record.c | 14 +++++++++----- 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/lib/dump.lua b/lib/dump.lua index 00f59977..fb40a8f8 100644 --- a/lib/dump.lua +++ b/lib/dump.lua @@ -209,7 +209,8 @@ local colorize, irtype -- Lookup table to convert some literals into names. local litname = { - ["SLOAD "] = { [0] = "", "I", "R", "RI", "P", "PI", "PR", "PRI", }, + ["SLOAD "] = { [0] = "", "I", "R", "RI", "P", "PI", "PR", "PRI", + "T", "IT", "RT", "RIT", "PT", "PIT", "PRT", "PRIT", }, ["XLOAD "] = { [0] = "", "R", "U", "RU", }, ["TOINT "] = { [0] = "check", "index", "", }, ["FLOAD "] = vmdef.irfield, diff --git a/src/lj_asm.c b/src/lj_asm.c index 6d42cf35..eeb6aeb4 100644 --- a/src/lj_asm.c +++ b/src/lj_asm.c @@ -1852,6 +1852,8 @@ static void asm_sload(ASMState *as, IRIns *ir) IRType1 t = ir->t; Reg base; lua_assert(!(ir->op2 & IRSLOAD_PARENT)); /* Handled by asm_head_side(). */ + lua_assert(!irt_isguard(ir->t) == + !((ir->op2 & IRSLOAD_TYPECHECK) || irt_isint(t))); if (irt_isint(t)) { Reg left = ra_scratch(as, RSET_FPR); asm_tointg(as, ir, left); /* Frees dest reg. Do this before base alloc. */ @@ -1865,11 +1867,11 @@ static void asm_sload(ASMState *as, IRIns *ir) base = ra_alloc1(as, REF_BASE, RSET_GPR); emit_movrmro(as, dest, base, ofs); } else { - if (!irt_isguard(ir->t)) + if (!(ir->op2 & IRSLOAD_TYPECHECK)) return; /* No type check: avoid base alloc. */ base = ra_alloc1(as, REF_BASE, RSET_GPR); } - if (irt_isguard(ir->t)) { + if ((ir->op2 & IRSLOAD_TYPECHECK)) { /* Need type check, even if the load result is unused. */ asm_guardcc(as, irt_isnum(t) ? CC_A : CC_NE); emit_i8(as, ~irt_type(t)); diff --git a/src/lj_ir.h b/src/lj_ir.h index f73dcc40..efc8205e 100644 --- a/src/lj_ir.h +++ b/src/lj_ir.h @@ -192,6 +192,7 @@ IRFLDEF(FLENUM) #define IRSLOAD_INHERIT 1 /* Inherited by exits/side traces. */ #define IRSLOAD_READONLY 2 /* Read-only, omit slot store. */ #define IRSLOAD_PARENT 4 /* Coalesce with parent trace. */ +#define IRSLOAD_TYPECHECK 8 /* Needs type check. */ /* XLOAD mode, stored in op2. */ #define IRXLOAD_READONLY 1 /* Load from read-only data. */ diff --git a/src/lj_record.c b/src/lj_record.c index 950f4d82..5085d735 100644 --- a/src/lj_record.c +++ b/src/lj_record.c @@ -125,7 +125,7 @@ static void rec_check_slots(jit_State *J) /* Specialize a slot to a specific type. Note: slot can be negative! */ static TRef sloadt(jit_State *J, int32_t slot, IRType t, int mode) { - /* No guard, since none of the callers need a type-checking SLOAD. */ + /* Caller may set IRT_GUARD in t. */ TRef ref = emitir_raw(IRT(IR_SLOAD, t), (int32_t)J->baseslot+slot, mode); J->base[slot] = ref; return ref; @@ -135,7 +135,8 @@ static TRef sloadt(jit_State *J, int32_t slot, IRType t, int mode) static TRef sload(jit_State *J, int32_t slot) { IRType t = itype2irt(&J->L->base[slot]); - TRef ref = emitir_raw(IRTG(IR_SLOAD, t), (int32_t)J->baseslot+slot, 0); + TRef ref = emitir_raw(IRTG(IR_SLOAD, t), (int32_t)J->baseslot+slot, + IRSLOAD_TYPECHECK); if (irtype_ispri(t)) ref = TREF_PRI(t); /* Canonicalize primitive refs. */ J->base[slot] = ref; return ref; @@ -251,8 +252,9 @@ static TRef fori_arg(jit_State *J, const BCIns *pc, BCReg slot, IRType t) } if (J->base[slot]) return J->base[slot]; - else - return sloadt(J, (int32_t)slot, t, IRSLOAD_READONLY|IRSLOAD_INHERIT); + if (t == IRT_INT) + t |= IRT_GUARD; + return sloadt(J, (int32_t)slot, t, IRSLOAD_READONLY|IRSLOAD_INHERIT); } /* Simulate the runtime behavior of the FOR loop iterator. @@ -2107,6 +2109,8 @@ static void rec_setup_forl(jit_State *J, const BCIns *fori) k = (int32_t)(dir ? 0x7fffffff : 0x80000000) - k; emitir(IRTGI(dir ? IR_LE : IR_GE), stop, lj_ir_kint(J, k)); } + if (t == IRT_INT) + t |= IRT_GUARD; J->base[ra+FORL_EXT] = sloadt(J, (int32_t)(ra+FORL_IDX), t, IRSLOAD_INHERIT); J->maxslot = ra+FORL_EXT+1; } @@ -2195,7 +2199,7 @@ static void rec_setup_side(jit_State *J, Trace *T) tr = emitir_raw(IRT(IR_FRAME, IRT_PTR), tr, tr); } break; - case IR_SLOAD: /* Inherited SLOADs don't need a guard. */ + case IR_SLOAD: /* Inherited SLOADs don't need a guard or type check. */ tr = emitir_raw(ir->ot & ~IRT_GUARD, s, (ir->op2&IRSLOAD_READONLY) | IRSLOAD_INHERIT|IRSLOAD_PARENT); break;