Explorar o código

Add support for __pairs and __ipairs metamethods (from Lua 5.2).

Mike Pall %!s(int64=15) %!d(string=hai) anos
pai
achega
ba602c9578
Modificáronse 9 ficheiros con 1561 adicións e 1498 borrados
  1. 6 0
      src/buildvm_ppc.dasc
  2. 204 192
      src/buildvm_ppcspe.h
  3. 415 413
      src/buildvm_x64.h
  4. 397 395
      src/buildvm_x64win.h
  5. 6 2
      src/buildvm_x86.dasc
  6. 466 464
      src/buildvm_x86.h
  7. 30 4
      src/lib_base.c
  8. 1 1
      src/lj_obj.h
  9. 36 27
      src/lj_record.c

+ 6 - 0
src/buildvm_ppc.dasc

@@ -1098,8 +1098,11 @@ static void build_subroutines(BuildCtx *ctx)
   |  checktab TAB:CARG1
   |   lwz PC, FRAME_PC(BASE)
   |  checkfail ->fff_fallback
+  |  lwz TAB:TMP2, TAB:CARG1->metatable
   |  evldd CFUNC:TMP0, CFUNC:RB->upvalue[0]
+  |  cmplwi TAB:TMP2, 0
   |  la RA, -8(BASE)
+  |  bne ->fff_fallback
   |   evstdd TAB:CARG1, 0(BASE)
   |   evstdd TISNIL, 8(BASE)
   |  li RD, (3+1)*8
@@ -1150,8 +1153,11 @@ static void build_subroutines(BuildCtx *ctx)
   |  checktab TAB:CARG1
   |   lwz PC, FRAME_PC(BASE)
   |  checkfail ->fff_fallback
+  |  lwz TAB:TMP2, TAB:CARG1->metatable
   |  evldd CFUNC:TMP0, CFUNC:RB->upvalue[0]
+  |  cmplwi TAB:TMP2, 0
   |  la RA, -8(BASE)
+  |  bne ->fff_fallback
   |    evsplati TMP1, 0
   |   evstdd TAB:CARG1, 0(BASE)
   |    evstdd TMP1, 8(BASE)

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 204 - 192
src/buildvm_ppcspe.h


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 415 - 413
src/buildvm_x64.h


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 397 - 395
src/buildvm_x64win.h


+ 6 - 2
src/buildvm_x86.dasc

@@ -1509,8 +1509,10 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
   |  jmp ->fff_res1
   |
   |.ffunc_1 pairs
-  |  mov CFUNC:RB, [BASE-8]
+  |  mov TAB:RB, [BASE]
   |  cmp dword [BASE+4], LJ_TTAB;  jne ->fff_fallback
+  |  cmp dword TAB:RB->metatable, 0; jne ->fff_fallback
+  |  mov CFUNC:RB, [BASE-8]
   |  mov CFUNC:RD, CFUNC:RB->upvalue[0]
   |  mov PC, [BASE-4]
   |  mov dword [BASE-4], LJ_TFUNC
@@ -1571,8 +1573,10 @@ static void build_subroutines(BuildCtx *ctx, int cmov, int sse)
   |  jmp ->fff_res
   |
   |.ffunc_1 ipairs
-  |  mov CFUNC:RB, [BASE-8]
+  |  mov TAB:RB, [BASE]
   |  cmp dword [BASE+4], LJ_TTAB;  jne ->fff_fallback
+  |  cmp dword TAB:RB->metatable, 0; jne ->fff_fallback
+  |  mov CFUNC:RB, [BASE-8]
   |  mov CFUNC:RD, CFUNC:RB->upvalue[0]
   |  mov PC, [BASE-4]
   |  mov dword [BASE-4], LJ_TFUNC

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 466 - 464
src/buildvm_x86.h


+ 30 - 4
src/lib_base.c

@@ -246,17 +246,43 @@ LJ_STATIC_ASSERT((int)FF_next == FF_next_N);
 LJLIB_ASM(next)
 {
   lj_lib_checktab(L, 1);
-  lj_lib_checknum(L, 2);  /* For ipairs_aux. */
   return FFH_UNREACHABLE;
 }
 
+static int ffh_pairs(lua_State *L, MMS mm)
+{
+  TValue *o = lj_lib_checkany(L, 1);
+  cTValue *mo = lj_meta_lookup(L, o, mm);
+  if (!tvisnil(mo)) {
+    L->top = o+1;  /* Only keep one argument. */
+    copyTV(L, L->base-1, mo);  /* Replace callable. */
+    return FFH_TAILCALL;
+  } else {
+    if (!tvistab(o)) lj_err_argt(L, 1, LUA_TTABLE);
+    setfuncV(L, o-1, funcV(lj_lib_upvalue(L, 1)));
+    if (mm == MM_pairs) setnilV(o+1); else setintV(o+1, 0);
+    return FFH_RES(3);
+  }
+}
+
 LJLIB_PUSH(lastcl)
-LJLIB_ASM_(pairs)
+LJLIB_ASM(pairs)
+{
+  return ffh_pairs(L, MM_pairs);
+}
 
-LJLIB_NOREGUV LJLIB_ASM_(ipairs_aux)	LJLIB_REC(.)
+LJLIB_NOREGUV LJLIB_ASM(ipairs_aux)	LJLIB_REC(.)
+{
+  lj_lib_checktab(L, 1);
+  lj_lib_checknum(L, 2);
+  return FFH_UNREACHABLE;
+}
 
 LJLIB_PUSH(lastcl)
-LJLIB_ASM_(ipairs)		LJLIB_REC(.)
+LJLIB_ASM(ipairs)		LJLIB_REC(.)
+{
+  return ffh_pairs(L, MM_ipairs);
+}
 
 /* -- Base library: throw and catch errors -------------------------------- */
 

+ 1 - 1
src/lj_obj.h

@@ -417,7 +417,7 @@ enum {
   /* The following must be in ORDER ARITH. */ \
   _(add) _(sub) _(mul) _(div) _(mod) _(pow) _(unm) \
   /* The following are used in the standard libraries. */ \
-  _(metatable) _(tostring)
+  _(metatable) _(tostring) _(pairs) _(ipairs)
 
 typedef enum {
 #define MMENUM(name)	MM_##name,

+ 36 - 27
src/lj_record.c

@@ -1358,7 +1358,7 @@ static void LJ_FASTCALL recff_tonumber(jit_State *J, RecordFFData *rd)
   UNUSED(rd);
 }
 
-static TValue *recff_tostring_cp(lua_State *L, lua_CFunction dummy, void *ud)
+static TValue *recff_metacall_cp(lua_State *L, lua_CFunction dummy, void *ud)
 {
   jit_State *J = (jit_State *)ud;
   rec_tailcall(J, 0, 1);
@@ -1366,31 +1366,38 @@ static TValue *recff_tostring_cp(lua_State *L, lua_CFunction dummy, void *ud)
   return NULL;
 }
 
+static int recff_metacall(jit_State *J, RecordFFData *rd, MMS mm)
+{
+  RecordIndex ix;
+  ix.tab = J->base[0];
+  copyTV(J->L, &ix.tabv, &rd->argv[0]);
+  if (rec_mm_lookup(J, &ix, mm)) {  /* Has metamethod? */
+    int errcode;
+    /* Temporarily insert metamethod below object. */
+    J->base[1] = J->base[0];
+    J->base[0] = ix.mobj;
+    copyTV(J->L, &rd->argv[1], &rd->argv[0]);
+    copyTV(J->L, &rd->argv[0], &ix.mobjv);
+    /* Need to protect rec_tailcall because it may throw. */
+    errcode = lj_vm_cpcall(J->L, NULL, J, recff_metacall_cp);
+    /* Always undo Lua stack changes to avoid confusing the interpreter. */
+    copyTV(J->L, &rd->argv[0], &rd->argv[1]);
+    if (errcode)
+      lj_err_throw(J->L, errcode);  /* Propagate errors. */
+    rd->nres = -1;  /* Pending call. */
+    return 1;  /* Tailcalled to metamethod. */
+  }
+  return 0;
+}
+
 static void LJ_FASTCALL recff_tostring(jit_State *J, RecordFFData *rd)
 {
   TRef tr = J->base[0];
   if (tref_isstr(tr)) {
     /* Ignore __tostring in the string base metatable. */
     /* Pass on result in J->base[0]. */
-  } else {
-    RecordIndex ix;
-    ix.tab = tr;
-    copyTV(J->L, &ix.tabv, &rd->argv[0]);
-    if (rec_mm_lookup(J, &ix, MM_tostring)) {  /* Has __tostring metamethod? */
-      int errcode;
-      /* Temporarily insert metamethod below object. */
-      J->base[1] = tr;
-      J->base[0] = ix.mobj;
-      copyTV(J->L, &rd->argv[1], &rd->argv[0]);
-      copyTV(J->L, &rd->argv[0], &ix.mobjv);
-      /* Need to protect rec_tailcall because it may throw. */
-      errcode = lj_vm_cpcall(J->L, NULL, J, recff_tostring_cp);
-      /* Always undo Lua stack changes to avoid confusing the interpreter. */
-      copyTV(J->L, &rd->argv[0], &rd->argv[1]);
-      if (errcode)
-	lj_err_throw(J->L, errcode);  /* Propagate errors. */
-      rd->nres = -1;  /* Pending call. */
-    } else if (tref_isnumber(tr)) {
+  } else if (!recff_metacall(J, rd, MM_tostring)) {
+    if (tref_isnumber(tr)) {
       J->base[0] = emitir(IRT(IR_TOSTR, IRT_STR), tr, 0);
     } else if (tref_ispri(tr)) {
       J->base[0] = lj_ir_kstr(J, strV(&J->fn->c.upvalue[tref_type(tr)]));
@@ -1419,13 +1426,15 @@ static void LJ_FASTCALL recff_ipairs_aux(jit_State *J, RecordFFData *rd)
 
 static void LJ_FASTCALL recff_ipairs(jit_State *J, RecordFFData *rd)
 {
-  TRef tab = J->base[0];
-  if (tref_istab(tab)) {
-    J->base[0] = lj_ir_kfunc(J, funcV(&J->fn->c.upvalue[0]));
-    J->base[1] = tab;
-    J->base[2] = lj_ir_kint(J, 0);
-    rd->nres = 3;
-  }  /* else: Interpreter will throw. */
+  if (!recff_metacall(J, rd, MM_ipairs)) {
+    TRef tab = J->base[0];
+    if (tref_istab(tab)) {
+      J->base[0] = lj_ir_kfunc(J, funcV(&J->fn->c.upvalue[0]));
+      J->base[1] = tab;
+      J->base[2] = lj_ir_kint(J, 0);
+      rd->nres = 3;
+    }  /* else: Interpreter will throw. */
+  }
 }
 
 static void LJ_FASTCALL recff_pcall(jit_State *J, RecordFFData *rd)

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio