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

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