ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

lj_meta.c (15381B)


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