Selaa lähdekoodia

From Lua 5.2: __len for tables. Needs -DLUAJIT_ENABLE_LUA52COMPAT.

Mike Pall 14 vuotta sitten
vanhempi
commit
31d566428f
11 muutettua tiedostoa jossa 1936 lisäystä ja 1808 poistoa
  1. 22 1
      src/buildvm_arm.dasc
  2. 176 168
      src/buildvm_arm.h
  3. 25 1
      src/buildvm_ppc.dasc
  4. 199 187
      src/buildvm_ppcspe.h
  5. 463 460
      src/buildvm_x64.h
  6. 460 457
      src/buildvm_x64win.h
  7. 22 1
      src/buildvm_x86.dasc
  8. 519 517
      src/buildvm_x86.h
  9. 11 2
      src/lj_meta.c
  10. 3 3
      src/lj_obj.h
  11. 36 11
      src/lj_record.c

+ 22 - 1
src/buildvm_arm.dasc

@@ -767,9 +767,16 @@ static void build_subroutines(BuildCtx *ctx)
   |  mov CARG1, L
   |   str PC, SAVE_PC
   |  bl extern lj_meta_len		// (lua_State *L, TValue *o)
-  |  // Returns TValue * (metamethod base).
+  |  // Returns NULL (retry) or TValue * (metamethod base).
   |  IOS ldr BASE, L->base
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+  |  cmp CRET1, #0
+  |  bne ->vmeta_binop			// Binop call for compatibility.
+  |  ldr TAB:CARG1, [BASE, RC]
+  |  b ->BC_LEN_Z
+#else
   |  b ->vmeta_binop			// Binop call for compatibility.
+#endif
   |
   |//-- Call metamethod ----------------------------------------------------
   |
@@ -2546,11 +2553,25 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |   ins_next3
     |2:
     |  checktab CARG2, ->vmeta_len
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+    |  ldr TAB:CARG3, TAB:CARG1->metatable
+    |  cmp TAB:CARG3, #0
+    |  bne >9
+    |3:
+#endif
+    |->BC_LEN_Z:
     |  IOS mov RC, BASE
     |  bl extern lj_tab_len		// (GCtab *t)
     |  // Returns uint32_t (but less than 2^31).
     |  IOS mov BASE, RC
     |  b <1
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+    |9:
+    |  ldrb CARG4, TAB:CARG3->nomm
+    |  tst CARG4, #1<<MM_len
+    |  bne <3				// 'no __len' flag set: done.
+    |  b ->vmeta_len
+#endif
     break;
 
   /* -- Binary ops -------------------------------------------------------- */

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 176 - 168
src/buildvm_arm.h


+ 25 - 1
src/buildvm_ppc.dasc

@@ -818,13 +818,23 @@ static void build_subroutines(BuildCtx *ctx)
   |  b ->vm_call_dispatch
   |
   |->vmeta_len:
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+  |  mr SAVE0, CARG1
+#endif
   |  add CARG2, BASE, RD
   |   stw BASE, L->base
   |  mr CARG1, L
   |   stw PC, SAVE_PC
   |  bl extern lj_meta_len		// (lua_State *L, TValue *o)
-  |  // Returns TValue * (metamethod base).
+  |  // Returns NULL (retry) or TValue * (metamethod base).
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+  |  cmplwi CRET1, 0
+  |  bne ->vmeta_binop			// Binop call for compatibility.
+  |  mr CARG1, SAVE0
+  |  b ->BC_LEN_Z
+#else
   |  b ->vmeta_binop			// Binop call for compatibility.
+#endif
   |
   |//-- Call metamethod ----------------------------------------------------
   |
@@ -2337,9 +2347,23 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop)
     |2:
     |  checktab CARG1
     |  checkfail ->vmeta_len
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+    |  lwz TAB:TMP2, TAB:CARG1->metatable
+    |  cmplwi TAB:TMP2, 0
+    |  bne >9
+    |3:
+#endif
+    |->BC_LEN_Z:
     |  bl extern lj_tab_len		// (GCtab *t)
     |  // Returns uint32_t (but less than 2^31).
     |  b <1
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+    |9:
+    |  lbz TMP0, TAB:TMP2->nomm
+    |  andi. TMP0, TMP0, 1<<MM_len
+    |  bne <3				// 'no __len' flag set: done.
+    |  b ->vmeta_len
+#endif
     break;
 
   /* -- Binary ops -------------------------------------------------------- */

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 199 - 187
src/buildvm_ppcspe.h


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 463 - 460
src/buildvm_x64.h


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 460 - 457
src/buildvm_x64win.h


+ 22 - 1
src/buildvm_x86.dasc

@@ -1167,9 +1167,17 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
   |  mov L:FCARG1, L:RB
   |  mov SAVE_PC, PC
   |  call extern lj_meta_len@8		// (lua_State *L, TValue *o)
-  |  // TValue * (metamethod) returned in eax (RC).
+  |  // NULL (retry) or TValue * (metamethod) returned in eax (RC).
   |  mov BASE, L:RB->base
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+  |  test RC, RC
+  |  jne ->vmeta_binop			// Binop call for compatibility.
+  |  movzx RD, PC_RD
+  |  mov TAB:FCARG1, [BASE+RD*8]
+  |  jmp ->BC_LEN_Z
+#else
   |  jmp ->vmeta_binop			// Binop call for compatibility.
+#endif
   |
   |//-- Call metamethod ----------------------------------------------------
   |
@@ -4244,6 +4252,13 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
     |2:
     |  checktab RD, ->vmeta_len
     |  mov TAB:FCARG1, [BASE+RD*8]
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+    |  mov TAB:RB, TAB:FCARG1->metatable
+    |  cmp TAB:RB, 0
+    |  jnz >9
+    |3:
+#endif
+    |->BC_LEN_Z:
     |  mov RB, BASE			// Save BASE.
     |  call extern lj_tab_len@4		// (GCtab *t)
     |  // Length of table returned in eax (RD).
@@ -4260,6 +4275,12 @@ static void build_ins(BuildCtx *ctx, BCOp op, int defop, int cmov, int sse)
     |  mov BASE, RB			// Restore BASE.
     |  movzx RA, PC_RA
     |  jmp <1
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+    |9:  // Check for __len.
+    |  test byte TAB:RB->nomm, 1<<MM_len
+    |  jnz <3
+    |  jmp ->vmeta_len			// 'no __len' flag NOT set: check.
+#endif
     break;
 
   /* -- Binary ops -------------------------------------------------------- */

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 519 - 517
src/buildvm_x86.h


+ 11 - 2
src/lj_meta.c

@@ -309,10 +309,19 @@ TValue * LJ_FASTCALL lj_meta_len(lua_State *L, cTValue *o)
 {
   cTValue *mo = lj_meta_lookup(L, o, MM_len);
   if (tvisnil(mo)) {
-    lj_err_optype(L, o, LJ_ERR_OPLEN);
-    return NULL;  /* unreachable */
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+    if (tvistab(o))
+      tabref(tabV(o)->metatable)->nomm |= (uint8_t)(1u<<MM_len);
+    else
+#endif
+      lj_err_optype(L, o, LJ_ERR_OPLEN);
+    return NULL;
   }
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+  return mmcall(L, lj_cont_ra, mo, o, o);
+#else
   return mmcall(L, lj_cont_ra, mo, o, niltv(L));
+#endif
 }
 
 /* Helper for equality comparisons. __eq metamethod. */

+ 3 - 3
src/lj_obj.h

@@ -441,9 +441,9 @@ enum {
 #endif
 
 #define MMDEF(_) \
-  _(index) _(newindex) _(gc) _(mode) _(eq) \
+  _(index) _(newindex) _(gc) _(mode) _(eq) _(len) \
   /* Only the above (fast) metamethods are negative cached (max. 8). */ \
-  _(len) _(lt) _(le) _(concat) _(call) \
+  _(lt) _(le) _(concat) _(call) \
   /* The following must be in ORDER ARITH. */ \
   _(add) _(sub) _(mul) _(div) _(mod) _(pow) _(unm) \
   /* The following are used in the standard libraries. */ \
@@ -455,7 +455,7 @@ MMDEF(MMENUM)
 #undef MMENUM
   MM__MAX,
   MM____ = MM__MAX,
-  MM_FAST = MM_eq
+  MM_FAST = MM_len
 } MMS;
 
 /* GC root IDs. */

+ 36 - 11
src/lj_record.c

@@ -819,7 +819,7 @@ nocheck:
   return 0;  /* No metamethod. */
 }
 
-/* Record call to arithmetic metamethod (and MM_len). */
+/* Record call to arithmetic metamethod. */
 static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
 {
   /* Set up metamethod call first to save ix->tab and ix->tabv. */
@@ -830,7 +830,7 @@ static TRef rec_mm_arith(jit_State *J, RecordIndex *ix, MMS mm)
   copyTV(J->L, basev+1, &ix->tabv);
   copyTV(J->L, basev+2, &ix->keyv);
   if (!lj_record_mm_lookup(J, ix, mm)) {  /* Lookup mm on 1st operand. */
-    if (mm != MM_len) {
+    if (mm != MM_unm) {
       ix->tab = ix->key;
       copyTV(J->L, &ix->tabv, &ix->keyv);
       if (lj_record_mm_lookup(J, ix, mm))  /* Lookup mm on 2nd operand. */
@@ -845,6 +845,34 @@ ok:
   return 0;  /* No result yet. */
 }
 
+/* Record call to __len metamethod. */
+static TRef rec_mm_len(jit_State *J, TRef tr, TValue *tv)
+{
+  RecordIndex ix;
+  ix.tab = tr;
+  copyTV(J->L, &ix.tabv, tv);
+  if (lj_record_mm_lookup(J, &ix, MM_len)) {
+    BCReg func = rec_mm_prep(J, lj_cont_ra);
+    TRef *base = J->base + func;
+    TValue *basev = J->L->base + func;
+    base[0] = ix.mobj; copyTV(J->L, basev+0, &ix.mobjv);
+    base[1] = tr; copyTV(J->L, basev+1, tv);
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+    base[2] = tr; copyTV(J->L, basev+2, tv);
+#else
+    base[2] = TREF_NIL; setnilV(basev+2);
+#endif
+    lj_record_call(J, func, 2);
+  } else {
+#ifdef LUAJIT_ENABLE_LUA52COMPAT
+    if (tref_istab(tr))
+      return lj_ir_call(J, IRCALL_lj_tab_len, tr);
+#endif
+    lj_trace_err(J, LJ_TRERR_NOMM);
+  }
+  return 0;  /* No result yet. */
+}
+
 /* Call a comparison metamethod. */
 static void rec_mm_callcomp(jit_State *J, RecordIndex *ix, int op)
 {
@@ -1667,17 +1695,14 @@ void lj_record_ins(jit_State *J)
     break;
 
   case BC_LEN:
-    if (tref_isstr(rc)) {
+    if (tref_isstr(rc))
       rc = emitir(IRTI(IR_FLOAD), rc, IRFL_STR_LEN);
-    } else if (tref_istab(rc)) {
+#ifndef LUAJIT_ENABLE_LUA52COMPAT
+    else if (tref_istab(rc))
       rc = lj_ir_call(J, IRCALL_lj_tab_len, rc);
-    } else {
-      ix.tab = rc;
-      copyTV(J->L, &ix.tabv, rcv);
-      ix.key = TREF_NIL;
-      setnilV(&ix.keyv);
-      rc = rec_mm_arith(J, &ix, MM_len);
-    }
+#endif
+    else
+      rc = rec_mm_len(J, rc, rcv);
     break;
 
   /* -- Arithmetic ops ---------------------------------------------------- */

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä