root/lj_meta.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. lj_meta_init
  2. lj_meta_cache
  3. lj_meta_lookup
  4. lj_meta_tailcall
  5. mmcall
  6. lj_meta_tget
  7. lj_meta_tset
  8. str2num
  9. lj_meta_arith
  10. lj_meta_cat
  11. lj_meta_len
  12. lj_meta_equal
  13. lj_meta_equal_cd
  14. lj_meta_comp
  15. lj_meta_istype
  16. lj_meta_call
  17. lj_meta_for

   1 /*
   2 ** Metamethod handling.
   3 ** Copyright (C) 2005-2017 Mike Pall. See Copyright Notice in luajit.h
   4 **
   5 ** Portions taken verbatim or adapted from the Lua interpreter.
   6 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
   7 */
   8 
   9 #define lj_meta_c
  10 #define LUA_CORE
  11 
  12 #include "lj_obj.h"
  13 #include "lj_gc.h"
  14 #include "lj_err.h"
  15 #include "lj_buf.h"
  16 #include "lj_str.h"
  17 #include "lj_tab.h"
  18 #include "lj_meta.h"
  19 #include "lj_frame.h"
  20 #include "lj_bc.h"
  21 #include "lj_vm.h"
  22 #include "lj_strscan.h"
  23 #include "lj_strfmt.h"
  24 #include "lj_lib.h"
  25 
  26 /* -- Metamethod handling ------------------------------------------------- */
  27 
  28 /* String interning of metamethod names for fast indexing. */
  29 void lj_meta_init(lua_State *L)
  30 {
  31 #define MMNAME(name)    "__" #name
  32   const char *metanames = MMDEF(MMNAME);
  33 #undef MMNAME
  34   global_State *g = G(L);
  35   const char *p, *q;
  36   uint32_t mm;
  37   for (mm = 0, p = metanames; *p; mm++, p = q) {
  38     GCstr *s;
  39     for (q = p+2; *q && *q != '_'; q++) ;
  40     s = lj_str_new(L, p, (size_t)(q-p));
  41     /* NOBARRIER: g->gcroot[] is a GC root. */
  42     setgcref(g->gcroot[GCROOT_MMNAME+mm], obj2gco(s));
  43   }
  44 }
  45 
  46 /* Negative caching of a few fast metamethods. See the lj_meta_fast() macro. */
  47 cTValue *lj_meta_cache(GCtab *mt, MMS mm, GCstr *name)
  48 {
  49   cTValue *mo = lj_tab_getstr(mt, name);
  50   lua_assert(mm <= MM_FAST);
  51   if (!mo || tvisnil(mo)) {  /* No metamethod? */
  52     mt->nomm |= (uint8_t)(1u<<mm);  /* Set negative cache flag. */
  53     return NULL;
  54   }
  55   return mo;
  56 }
  57 
  58 /* Lookup metamethod for object. */
  59 cTValue *lj_meta_lookup(lua_State *L, cTValue *o, MMS mm)
  60 {
  61   GCtab *mt;
  62   if (tvistab(o))
  63     mt = tabref(tabV(o)->metatable);
  64   else if (tvisudata(o))
  65     mt = tabref(udataV(o)->metatable);
  66   else
  67     mt = tabref(basemt_obj(G(L), o));
  68   if (mt) {
  69     cTValue *mo = lj_tab_getstr(mt, mmname_str(G(L), mm));
  70     if (mo)
  71       return mo;
  72   }
  73   return niltv(L);
  74 }
  75 
  76 #if LJ_HASFFI
  77 /* Tailcall from C function. */
  78 int lj_meta_tailcall(lua_State *L, cTValue *tv)
  79 {
  80   TValue *base = L->base;
  81   TValue *top = L->top;
  82   const BCIns *pc = frame_pc(base-1);  /* Preserve old PC from frame. */
  83   copyTV(L, base-1-LJ_FR2, tv);  /* Replace frame with new object. */
  84   if (LJ_FR2)
  85     (top++)->u64 = LJ_CONT_TAILCALL;
  86   else
  87     top->u32.lo = LJ_CONT_TAILCALL;
  88   setframe_pc(top++, pc);
  89   if (LJ_FR2) top++;
  90   setframe_gc(top, obj2gco(L), LJ_TTHREAD);  /* Dummy frame object. */
  91   setframe_ftsz(top, ((char *)(top+1) - (char *)base) + FRAME_CONT);
  92   L->base = L->top = top+1;
  93   /*
  94   ** before:   [old_mo|PC]    [... ...]
  95   **                         ^base     ^top
  96   ** after:    [new_mo|itype] [... ...] [NULL|PC] [dummy|delta]
  97   **                                                           ^base/top
  98   ** tailcall: [new_mo|PC]    [... ...]
  99   **                         ^base     ^top
 100   */
 101   return 0;
 102 }
 103 #endif
 104 
 105 /* Setup call to metamethod to be run by Assembler VM. */
 106 static TValue *mmcall(lua_State *L, ASMFunction cont, cTValue *mo,
 107                     cTValue *a, cTValue *b)
 108 {
 109   /*
 110   **           |-- framesize -> top       top+1       top+2 top+3
 111   ** before:   [func slots ...]
 112   ** mm setup: [func slots ...] [cont|?]  [mo|tmtype] [a]   [b]
 113   ** in asm:   [func slots ...] [cont|PC] [mo|delta]  [a]   [b]
 114   **           ^-- func base                          ^-- mm base
 115   ** after mm: [func slots ...]           [result]
 116   **                ^-- copy to base[PC_RA] --/     for lj_cont_ra
 117   **                          istruecond + branch   for lj_cont_cond*
 118   **                                       ignore   for lj_cont_nop
 119   ** next PC:  [func slots ...]
 120   */
 121   TValue *top = L->top;
 122   if (curr_funcisL(L)) top = curr_topL(L);
 123   setcont(top++, cont);  /* Assembler VM stores PC in upper word or FR2. */
 124   if (LJ_FR2) setnilV(top++);
 125   copyTV(L, top++, mo);  /* Store metamethod and two arguments. */
 126   if (LJ_FR2) setnilV(top++);
 127   copyTV(L, top, a);
 128   copyTV(L, top+1, b);
 129   return top;  /* Return new base. */
 130 }
 131 
 132 /* -- C helpers for some instructions, called from assembler VM ----------- */
 133 
 134 /* Helper for TGET*. __index chain and metamethod. */
 135 cTValue *lj_meta_tget(lua_State *L, cTValue *o, cTValue *k)
 136 {
 137   int loop;
 138   for (loop = 0; loop < LJ_MAX_IDXCHAIN; loop++) {
 139     cTValue *mo;
 140     if (LJ_LIKELY(tvistab(o))) {
 141       GCtab *t = tabV(o);
 142       cTValue *tv = lj_tab_get(L, t, k);
 143       if (!tvisnil(tv) ||
 144           !(mo = lj_meta_fast(L, tabref(t->metatable), MM_index)))
 145         return tv;
 146     } else if (tvisnil(mo = lj_meta_lookup(L, o, MM_index))) {
 147       lj_err_optype(L, o, LJ_ERR_OPINDEX);
 148       return NULL;  /* unreachable */
 149     }
 150     if (tvisfunc(mo)) {
 151       L->top = mmcall(L, lj_cont_ra, mo, o, k);
 152       return NULL;  /* Trigger metamethod call. */
 153     }
 154     o = mo;
 155   }
 156   lj_err_msg(L, LJ_ERR_GETLOOP);
 157   return NULL;  /* unreachable */
 158 }
 159 
 160 /* Helper for TSET*. __newindex chain and metamethod. */
 161 TValue *lj_meta_tset(lua_State *L, cTValue *o, cTValue *k)
 162 {
 163   TValue tmp;
 164   int loop;
 165   for (loop = 0; loop < LJ_MAX_IDXCHAIN; loop++) {
 166     cTValue *mo;
 167     if (LJ_LIKELY(tvistab(o))) {
 168       GCtab *t = tabV(o);
 169       cTValue *tv = lj_tab_get(L, t, k);
 170       if (LJ_LIKELY(!tvisnil(tv))) {
 171         t->nomm = 0;  /* Invalidate negative metamethod cache. */
 172         lj_gc_anybarriert(L, t);
 173         return (TValue *)tv;
 174       } else if (!(mo = lj_meta_fast(L, tabref(t->metatable), MM_newindex))) {
 175         t->nomm = 0;  /* Invalidate negative metamethod cache. */
 176         lj_gc_anybarriert(L, t);
 177         if (tv != niltv(L))
 178           return (TValue *)tv;
 179         if (tvisnil(k)) lj_err_msg(L, LJ_ERR_NILIDX);
 180         else if (tvisint(k)) { setnumV(&tmp, (lua_Number)intV(k)); k = &tmp; }
 181         else if (tvisnum(k) && tvisnan(k)) lj_err_msg(L, LJ_ERR_NANIDX);
 182         return lj_tab_newkey(L, t, k);
 183       }
 184     } else if (tvisnil(mo = lj_meta_lookup(L, o, MM_newindex))) {
 185       lj_err_optype(L, o, LJ_ERR_OPINDEX);
 186       return NULL;  /* unreachable */
 187     }
 188     if (tvisfunc(mo)) {
 189       L->top = mmcall(L, lj_cont_nop, mo, o, k);
 190       /* L->top+2 = v filled in by caller. */
 191       return NULL;  /* Trigger metamethod call. */
 192     }
 193     copyTV(L, &tmp, mo);
 194     o = &tmp;
 195   }
 196   lj_err_msg(L, LJ_ERR_SETLOOP);
 197   return NULL;  /* unreachable */
 198 }
 199 
 200 static cTValue *str2num(cTValue *o, TValue *n)
 201 {
 202   if (tvisnum(o))
 203     return o;
 204   else if (tvisint(o))
 205     return (setnumV(n, (lua_Number)intV(o)), n);
 206   else if (tvisstr(o) && lj_strscan_num(strV(o), n))
 207     return n;
 208   else
 209     return NULL;
 210 }
 211 
 212 /* Helper for arithmetic instructions. Coercion, metamethod. */
 213 TValue *lj_meta_arith(lua_State *L, TValue *ra, cTValue *rb, cTValue *rc,
 214                       BCReg op)
 215 {
 216   MMS mm = bcmode_mm(op);
 217   TValue tempb, tempc;
 218   cTValue *b, *c;
 219   if ((b = str2num(rb, &tempb)) != NULL &&
 220       (c = str2num(rc, &tempc)) != NULL) {  /* Try coercion first. */
 221     setnumV(ra, lj_vm_foldarith(numV(b), numV(c), (int)mm-MM_add));
 222     return NULL;
 223   } else {
 224     cTValue *mo = lj_meta_lookup(L, rb, mm);
 225     if (tvisnil(mo)) {
 226       mo = lj_meta_lookup(L, rc, mm);
 227       if (tvisnil(mo)) {
 228         if (str2num(rb, &tempb) == NULL) rc = rb;
 229         lj_err_optype(L, rc, LJ_ERR_OPARITH);
 230         return NULL;  /* unreachable */
 231       }
 232     }
 233     return mmcall(L, lj_cont_ra, mo, rb, rc);
 234   }
 235 }
 236 
 237 /* Helper for CAT. Coercion, iterative concat, __concat metamethod. */
 238 TValue *lj_meta_cat(lua_State *L, TValue *top, int left)
 239 {
 240   int fromc = 0;
 241   if (left < 0) { left = -left; fromc = 1; }
 242   do {
 243     if (!(tvisstr(top) || tvisnumber(top)) ||
 244         !(tvisstr(top-1) || tvisnumber(top-1))) {
 245       cTValue *mo = lj_meta_lookup(L, top-1, MM_concat);
 246       if (tvisnil(mo)) {
 247         mo = lj_meta_lookup(L, top, MM_concat);
 248         if (tvisnil(mo)) {
 249           if (tvisstr(top-1) || tvisnumber(top-1)) top++;
 250           lj_err_optype(L, top-1, LJ_ERR_OPCAT);
 251           return NULL;  /* unreachable */
 252         }
 253       }
 254       /* One of the top two elements is not a string, call __cat metamethod:
 255       **
 256       ** before:    [...][CAT stack .........................]
 257       **                                 top-1     top         top+1 top+2
 258       ** pick two:  [...][CAT stack ...] [o1]      [o2]
 259       ** setup mm:  [...][CAT stack ...] [cont|?]  [mo|tmtype] [o1]  [o2]
 260       ** in asm:    [...][CAT stack ...] [cont|PC] [mo|delta]  [o1]  [o2]
 261       **            ^-- func base                              ^-- mm base
 262       ** after mm:  [...][CAT stack ...] <--push-- [result]
 263       ** next step: [...][CAT stack .............]
 264       */
 265       copyTV(L, top+2*LJ_FR2+2, top);  /* Carefully ordered stack copies! */
 266       copyTV(L, top+2*LJ_FR2+1, top-1);
 267       copyTV(L, top+LJ_FR2, mo);
 268       setcont(top-1, lj_cont_cat);
 269       if (LJ_FR2) { setnilV(top); setnilV(top+2); top += 2; }
 270       return top+1;  /* Trigger metamethod call. */
 271     } else {
 272       /* Pick as many strings as possible from the top and concatenate them:
 273       **
 274       ** before:    [...][CAT stack ...........................]
 275       ** pick str:  [...][CAT stack ...] [...... strings ......]
 276       ** concat:    [...][CAT stack ...] [result]
 277       ** next step: [...][CAT stack ............]
 278       */
 279       TValue *e, *o = top;
 280       uint64_t tlen = tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM;
 281       SBuf *sb;
 282       do {
 283         o--; tlen += tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM;
 284       } while (--left > 0 && (tvisstr(o-1) || tvisnumber(o-1)));
 285       if (tlen >= LJ_MAX_STR) lj_err_msg(L, LJ_ERR_STROV);
 286       sb = lj_buf_tmp_(L);
 287       lj_buf_more(sb, (MSize)tlen);
 288       for (e = top, top = o; o <= e; o++) {
 289         if (tvisstr(o)) {
 290           GCstr *s = strV(o);
 291           MSize len = s->len;
 292           lj_buf_putmem(sb, strdata(s), len);
 293         } else if (tvisint(o)) {
 294           lj_strfmt_putint(sb, intV(o));
 295         } else {
 296           lj_strfmt_putfnum(sb, STRFMT_G14, numV(o));
 297         }
 298       }
 299       setstrV(L, top, lj_buf_str(L, sb));
 300     }
 301   } while (left >= 1);
 302   if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) {
 303     if (!fromc) L->top = curr_topL(L);
 304     lj_gc_step(L);
 305   }
 306   return NULL;
 307 }
 308 
 309 /* Helper for LEN. __len metamethod. */
 310 TValue * LJ_FASTCALL lj_meta_len(lua_State *L, cTValue *o)
 311 {
 312   cTValue *mo = lj_meta_lookup(L, o, MM_len);
 313   if (tvisnil(mo)) {
 314     if (LJ_52 && tvistab(o))
 315       tabref(tabV(o)->metatable)->nomm |= (uint8_t)(1u<<MM_len);
 316     else
 317       lj_err_optype(L, o, LJ_ERR_OPLEN);
 318     return NULL;
 319   }
 320   return mmcall(L, lj_cont_ra, mo, o, LJ_52 ? o : niltv(L));
 321 }
 322 
 323 /* Helper for equality comparisons. __eq metamethod. */
 324 TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne)
 325 {
 326   /* Field metatable must be at same offset for GCtab and GCudata! */
 327   cTValue *mo = lj_meta_fast(L, tabref(o1->gch.metatable), MM_eq);
 328   if (mo) {
 329     TValue *top;
 330     uint32_t it;
 331     if (tabref(o1->gch.metatable) != tabref(o2->gch.metatable)) {
 332       cTValue *mo2 = lj_meta_fast(L, tabref(o2->gch.metatable), MM_eq);
 333       if (mo2 == NULL || !lj_obj_equal(mo, mo2))
 334         return (TValue *)(intptr_t)ne;
 335     }
 336     top = curr_top(L);
 337     setcont(top++, ne ? lj_cont_condf : lj_cont_condt);
 338     if (LJ_FR2) setnilV(top++);
 339     copyTV(L, top++, mo);
 340     if (LJ_FR2) setnilV(top++);
 341     it = ~(uint32_t)o1->gch.gct;
 342     setgcV(L, top, o1, it);
 343     setgcV(L, top+1, o2, it);
 344     return top;  /* Trigger metamethod call. */
 345   }
 346   return (TValue *)(intptr_t)ne;
 347 }
 348 
 349 #if LJ_HASFFI
 350 TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins)
 351 {
 352   ASMFunction cont = (bc_op(ins) & 1) ? lj_cont_condf : lj_cont_condt;
 353   int op = (int)bc_op(ins) & ~1;
 354   TValue tv;
 355   cTValue *mo, *o2, *o1 = &L->base[bc_a(ins)];
 356   cTValue *o1mm = o1;
 357   if (op == BC_ISEQV) {
 358     o2 = &L->base[bc_d(ins)];
 359     if (!tviscdata(o1mm)) o1mm = o2;
 360   } else if (op == BC_ISEQS) {
 361     setstrV(L, &tv, gco2str(proto_kgc(curr_proto(L), ~(ptrdiff_t)bc_d(ins))));
 362     o2 = &tv;
 363   } else if (op == BC_ISEQN) {
 364     o2 = &mref(curr_proto(L)->k, cTValue)[bc_d(ins)];
 365   } else {
 366     lua_assert(op == BC_ISEQP);
 367     setpriV(&tv, ~bc_d(ins));
 368     o2 = &tv;
 369   }
 370   mo = lj_meta_lookup(L, o1mm, MM_eq);
 371   if (LJ_LIKELY(!tvisnil(mo)))
 372     return mmcall(L, cont, mo, o1, o2);
 373   else
 374     return (TValue *)(intptr_t)(bc_op(ins) & 1);
 375 }
 376 #endif
 377 
 378 /* Helper for ordered comparisons. String compare, __lt/__le metamethods. */
 379 TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op)
 380 {
 381   if (LJ_HASFFI && (tviscdata(o1) || tviscdata(o2))) {
 382     ASMFunction cont = (op & 1) ? lj_cont_condf : lj_cont_condt;
 383     MMS mm = (op & 2) ? MM_le : MM_lt;
 384     cTValue *mo = lj_meta_lookup(L, tviscdata(o1) ? o1 : o2, mm);
 385     if (LJ_UNLIKELY(tvisnil(mo))) goto err;
 386     return mmcall(L, cont, mo, o1, o2);
 387   } else if (LJ_52 || itype(o1) == itype(o2)) {
 388     /* Never called with two numbers. */
 389     if (tvisstr(o1) && tvisstr(o2)) {
 390       int32_t res = lj_str_cmp(strV(o1), strV(o2));
 391       return (TValue *)(intptr_t)(((op&2) ? res <= 0 : res < 0) ^ (op&1));
 392     } else {
 393     trymt:
 394       while (1) {
 395         ASMFunction cont = (op & 1) ? lj_cont_condf : lj_cont_condt;
 396         MMS mm = (op & 2) ? MM_le : MM_lt;
 397         cTValue *mo = lj_meta_lookup(L, o1, mm);
 398 #if LJ_52
 399         if (tvisnil(mo) && tvisnil((mo = lj_meta_lookup(L, o2, mm))))
 400 #else
 401         cTValue *mo2 = lj_meta_lookup(L, o2, mm);
 402         if (tvisnil(mo) || !lj_obj_equal(mo, mo2))
 403 #endif
 404         {
 405           if (op & 2) {  /* MM_le not found: retry with MM_lt. */
 406             cTValue *ot = o1; o1 = o2; o2 = ot;  /* Swap operands. */
 407             op ^= 3;  /* Use LT and flip condition. */
 408             continue;
 409           }
 410           goto err;
 411         }
 412         return mmcall(L, cont, mo, o1, o2);
 413       }
 414     }
 415   } else if (tvisbool(o1) && tvisbool(o2)) {
 416     goto trymt;
 417   } else {
 418   err:
 419     lj_err_comp(L, o1, o2);
 420     return NULL;
 421   }
 422 }
 423 
 424 /* Helper for ISTYPE and ISNUM. Implicit coercion or error. */
 425 void lj_meta_istype(lua_State *L, BCReg ra, BCReg tp)
 426 {
 427   L->top = curr_topL(L);
 428   ra++; tp--;
 429   lua_assert(LJ_DUALNUM || tp != ~LJ_TNUMX);  /* ISTYPE -> ISNUM broken. */
 430   if (LJ_DUALNUM && tp == ~LJ_TNUMX) lj_lib_checkint(L, ra);
 431   else if (tp == ~LJ_TNUMX+1) lj_lib_checknum(L, ra);
 432   else if (tp == ~LJ_TSTR) lj_lib_checkstr(L, ra);
 433   else lj_err_argtype(L, ra, lj_obj_itypename[tp]);
 434 }
 435 
 436 /* Helper for calls. __call metamethod. */
 437 void lj_meta_call(lua_State *L, TValue *func, TValue *top)
 438 {
 439   cTValue *mo = lj_meta_lookup(L, func, MM_call);
 440   TValue *p;
 441   if (!tvisfunc(mo))
 442     lj_err_optype_call(L, func);
 443   for (p = top; p > func+2*LJ_FR2; p--) copyTV(L, p, p-1);
 444   if (LJ_FR2) copyTV(L, func+2, func);
 445   copyTV(L, func, mo);
 446 }
 447 
 448 /* Helper for FORI. Coercion. */
 449 void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o)
 450 {
 451   if (!lj_strscan_numberobj(o)) lj_err_msg(L, LJ_ERR_FORINIT);
 452   if (!lj_strscan_numberobj(o+1)) lj_err_msg(L, LJ_ERR_FORLIM);
 453   if (!lj_strscan_numberobj(o+2)) lj_err_msg(L, LJ_ERR_FORSTEP);
 454   if (LJ_DUALNUM) {
 455     /* Ensure all slots are integers or all slots are numbers. */
 456     int32_t k[3];
 457     int nint = 0;
 458     ptrdiff_t i;
 459     for (i = 0; i <= 2; i++) {
 460       if (tvisint(o+i)) {
 461         k[i] = intV(o+i); nint++;
 462       } else {
 463         k[i] = lj_num2int(numV(o+i)); nint += ((lua_Number)k[i] == numV(o+i));
 464       }
 465     }
 466     if (nint == 3) {  /* Narrow to integers. */
 467       setintV(o, k[0]);
 468       setintV(o+1, k[1]);
 469       setintV(o+2, k[2]);
 470     } else if (nint != 0) {  /* Widen to numbers. */
 471       if (tvisint(o)) setnumV(o, (lua_Number)intV(o));
 472       if (tvisint(o+1)) setnumV(o+1, (lua_Number)intV(o+1));
 473       if (tvisint(o+2)) setnumV(o+2, (lua_Number)intV(o+2));
 474     }
 475   }
 476 }
 477 

/* [<][>][^][v][top][bottom][index][help] */