Browse Source

Decouple guard vs. INT check vs. TYPECHECK semantics for SLOAD.

Mike Pall 15 years ago
parent
commit
a61df8efbe
4 changed files with 16 additions and 8 deletions
  1. 2 1
      lib/dump.lua
  2. 4 2
      src/lj_asm.c
  3. 1 0
      src/lj_ir.h
  4. 9 5
      src/lj_record.c

+ 2 - 1
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,

+ 4 - 2
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));

+ 1 - 0
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. */

+ 9 - 5
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;