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. */
lj_meta_init(lua_State * L)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. */
lj_meta_cache(GCtab * mt,MMS mm,GCstr * name)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. */
lj_meta_lookup(lua_State * L,cTValue * o,MMS mm)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. */
lj_meta_tailcall(lua_State * L,cTValue * tv)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. */
mmcall(lua_State * L,ASMFunction cont,cTValue * mo,cTValue * a,cTValue * b)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. */
lj_meta_tget(lua_State * L,cTValue * o,cTValue * k)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. */
lj_meta_tset(lua_State * L,cTValue * o,cTValue * k)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 
str2num(cTValue * o,TValue * n)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. */
lj_meta_arith(lua_State * L,TValue * ra,cTValue * rb,cTValue * rc,BCReg op)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. */
lj_meta_cat(lua_State * L,TValue * top,int left)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. */
lj_meta_len(lua_State * L,cTValue * o)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. */
lj_meta_equal(lua_State * L,GCobj * o1,GCobj * o2,int ne)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
lj_meta_equal_cd(lua_State * L,BCIns ins)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. */
lj_meta_comp(lua_State * L,cTValue * o1,cTValue * o2,int op)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. */
lj_meta_istype(lua_State * L,BCReg ra,BCReg tp)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. */
lj_meta_call(lua_State * L,TValue * func,TValue * top)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. */
lj_meta_for(lua_State * L,TValue * o)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 
478