/src/tarantool/third_party/luajit/src/lj_meta.c
Line  | Count  | Source (jump to first uncovered line)  | 
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  | 4.20k  | { | 
31  | 8.41k  | #define MMNAME(name)  "__" #name  | 
32  | 8.41k  |   const char *metanames = MMDEF(MMNAME);  | 
33  | 4.20k  | #undef MMNAME  | 
34  | 4.20k  |   global_State *g = G(L);  | 
35  | 4.20k  |   const char *p, *q;  | 
36  | 4.20k  |   uint32_t mm;  | 
37  | 96.8k  |   for (mm = 0, p = metanames; *p; mm++, p = q) { | 
38  | 92.5k  |     GCstr *s;  | 
39  | 471k  |     for (q = p+2; *q && *q != '_'; q++) ;  | 
40  | 92.5k  |     s = lj_str_new(L, p, (size_t)(q-p));  | 
41  |  |     /* NOBARRIER: g->gcroot[] is a GC root. */  | 
42  | 92.5k  |     setgcref(g->gcroot[GCROOT_MMNAME+mm], obj2gco(s));  | 
43  | 92.5k  |   }  | 
44  | 4.20k  | }  | 
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  | 145k  | { | 
49  | 145k  |   cTValue *mo = lj_tab_getstr(mt, name);  | 
50  | 145k  |   lj_assertX(mm <= MM_FAST, "bad metamethod %d", mm);  | 
51  | 145k  |   if (!mo || tvisnil(mo)) {  /* No metamethod? */ | 
52  | 1.57k  |     mt->nomm |= (uint8_t)(1u<<mm);  /* Set negative cache flag. */  | 
53  | 1.57k  |     return NULL;  | 
54  | 1.57k  |   }  | 
55  | 143k  |   return mo;  | 
56  | 145k  | }  | 
57  |  |  | 
58  |  | /* Lookup metamethod for object. */  | 
59  |  | cTValue *lj_meta_lookup(lua_State *L, cTValue *o, MMS mm)  | 
60  | 1.30M  | { | 
61  | 1.30M  |   GCtab *mt;  | 
62  | 1.30M  |   if (tvistab(o))  | 
63  | 568k  |     mt = tabref(tabV(o)->metatable);  | 
64  | 733k  |   else if (tvisudata(o))  | 
65  | 0  |     mt = tabref(udataV(o)->metatable);  | 
66  | 733k  |   else  | 
67  | 733k  |     mt = tabref(basemt_obj(G(L), o));  | 
68  | 1.30M  |   if (mt) { | 
69  | 1.30M  |     cTValue *mo = lj_tab_getstr(mt, mmname_str(G(L), mm));  | 
70  | 1.30M  |     if (mo)  | 
71  | 1.15M  |       return mo;  | 
72  | 1.30M  |   }  | 
73  | 145k  |   return niltv(L);  | 
74  | 145k  | }  | 
75  |  |  | 
76  |  | #if LJ_HASFFI  | 
77  |  | /* Tailcall from C function. */  | 
78  |  | int lj_meta_tailcall(lua_State *L, cTValue *tv)  | 
79  | 0  | { | 
80  | 0  |   TValue *base = L->base;  | 
81  | 0  |   TValue *top = L->top;  | 
82  | 0  |   const BCIns *pc = frame_pc(base-1);  /* Preserve old PC from frame. */  | 
83  | 0  |   copyTV(L, base-1-LJ_FR2, tv);  /* Replace frame with new object. */  | 
84  | 0  |   if (LJ_FR2)  | 
85  | 0  |     (top++)->u64 = LJ_CONT_TAILCALL;  | 
86  | 0  |   else  | 
87  | 0  |     top->u32.lo = LJ_CONT_TAILCALL;  | 
88  | 0  |   setframe_pc(top++, pc);  | 
89  | 0  |   setframe_gc(top, obj2gco(L), LJ_TTHREAD);  /* Dummy frame object. */  | 
90  | 0  |   if (LJ_FR2) top++;  | 
91  | 0  |   setframe_ftsz(top, ((char *)(top+1) - (char *)base) + FRAME_CONT);  | 
92  | 0  |   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  | 0  |   return 0;  | 
102  | 0  | }  | 
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  | 395k  | { | 
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  | 395k  |   TValue *top = L->top;  | 
122  | 395k  |   if (curr_funcisL(L)) top = curr_topL(L);  | 
123  | 395k  |   setcont(top++, cont);  /* Assembler VM stores PC in upper word or FR2. */  | 
124  | 395k  |   if (LJ_FR2) setnilV(top++);  | 
125  | 395k  |   copyTV(L, top++, mo);  /* Store metamethod and two arguments. */  | 
126  | 395k  |   if (LJ_FR2) setnilV(top++);  | 
127  | 395k  |   copyTV(L, top, a);  | 
128  | 395k  |   copyTV(L, top+1, b);  | 
129  | 395k  |   return top;  /* Return new base. */  | 
130  | 395k  | }  | 
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  | 144k  | { | 
137  | 144k  |   int loop;  | 
138  | 144k  |   for (loop = 0; loop < LJ_MAX_IDXCHAIN; loop++) { | 
139  | 144k  |     cTValue *mo;  | 
140  | 144k  |     if (LJ_LIKELY(tvistab(o))) { | 
141  | 75.1k  |       GCtab *t = tabV(o);  | 
142  | 0  |       cTValue *tv = lj_tab_get(L, t, k);  | 
143  | 75.1k  |       if (!tvisnil(tv) ||  | 
144  | 75.1k  |     !(mo = lj_meta_fast(L, tabref(t->metatable), MM_index)))  | 
145  | 75.1k  |   return tv;  | 
146  | 75.1k  |     } else if (tvisnil(mo = lj_meta_lookup(L, o, MM_index))) { | 
147  | 0  |       lj_err_optype(L, o, LJ_ERR_OPINDEX);  | 
148  | 0  |       return NULL;  /* unreachable */  | 
149  | 0  |     }  | 
150  | 68.9k  |     if (tvisfunc(mo)) { | 
151  | 68.9k  |       L->top = mmcall(L, lj_cont_ra, mo, o, k);  | 
152  | 68.9k  |       return NULL;  /* Trigger metamethod call. */  | 
153  | 68.9k  |     }  | 
154  | 0  |     o = mo;  | 
155  | 0  |   }  | 
156  | 0  |   lj_err_msg(L, LJ_ERR_GETLOOP);  | 
157  | 0  |   return NULL;  /* unreachable */  | 
158  | 144k  | }  | 
159  |  |  | 
160  |  | /* Helper for TSET*. __newindex chain and metamethod. */  | 
161  |  | TValue *lj_meta_tset(lua_State *L, cTValue *o, cTValue *k)  | 
162  | 544k  | { | 
163  | 544k  |   TValue tmp;  | 
164  | 544k  |   int loop;  | 
165  | 544k  |   for (loop = 0; loop < LJ_MAX_IDXCHAIN; loop++) { | 
166  | 544k  |     cTValue *mo;  | 
167  | 544k  |     if (LJ_LIKELY(tvistab(o))) { | 
168  | 460k  |       GCtab *t = tabV(o);  | 
169  | 0  |       cTValue *tv = lj_tab_get(L, t, k);  | 
170  | 460k  |       if (LJ_LIKELY(!tvisnil(tv))) { | 
171  | 7.40k  |   t->nomm = 0;  /* Invalidate negative metamethod cache. */  | 
172  | 7.40k  |   lj_gc_anybarriert(L, t);  | 
173  | 7.40k  |   return (TValue *)tv;  | 
174  | 453k  |       } else if (!(mo = lj_meta_fast(L, tabref(t->metatable), MM_newindex))) { | 
175  | 367k  |   t->nomm = 0;  /* Invalidate negative metamethod cache. */  | 
176  | 367k  |   lj_gc_anybarriert(L, t);  | 
177  | 367k  |   if (tv != niltv(L))  | 
178  | 1.10k  |     return (TValue *)tv;  | 
179  | 365k  |   if (tvisnil(k)) lj_err_msg(L, LJ_ERR_NILIDX);  | 
180  | 365k  |   else if (tvisint(k)) { setnumV(&tmp, (lua_Number)intV(k)); k = &tmp; } | 
181  | 365k  |   else if (tvisnum(k) && tvisnan(k)) lj_err_msg(L, LJ_ERR_NANIDX);  | 
182  | 365k  |   return lj_tab_newkey(L, t, k);  | 
183  | 365k  |       }  | 
184  | 460k  |     } else if (tvisnil(mo = lj_meta_lookup(L, o, MM_newindex))) { | 
185  | 0  |       lj_err_optype(L, o, LJ_ERR_OPINDEX);  | 
186  | 0  |       return NULL;  /* unreachable */  | 
187  | 0  |     }  | 
188  | 170k  |     if (tvisfunc(mo)) { | 
189  | 170k  |       L->top = mmcall(L, lj_cont_nop, mo, o, k);  | 
190  |  |       /* L->top+2 = v filled in by caller. */  | 
191  | 170k  |       return NULL;  /* Trigger metamethod call. */  | 
192  | 170k  |     }  | 
193  | 0  |     copyTV(L, &tmp, mo);  | 
194  | 0  |     o = &tmp;  | 
195  | 0  |   }  | 
196  | 0  |   lj_err_msg(L, LJ_ERR_SETLOOP);  | 
197  | 0  |   return NULL;  /* unreachable */  | 
198  | 544k  | }  | 
199  |  |  | 
200  |  | static cTValue *str2num(cTValue *o, TValue *n)  | 
201  | 254k  | { | 
202  | 254k  |   if (tvisnum(o))  | 
203  | 81.6k  |     return o;  | 
204  | 172k  |   else if (tvisint(o))  | 
205  | 0  |     return (setnumV(n, (lua_Number)intV(o)), n);  | 
206  | 172k  |   else if (tvisstr(o) && lj_strscan_num(strV(o), n))  | 
207  | 25.1k  |     return n;  | 
208  | 147k  |   else  | 
209  | 147k  |     return NULL;  | 
210  | 254k  | }  | 
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  | 156k  | { | 
216  | 156k  |   MMS mm = bcmode_mm(op);  | 
217  | 156k  |   TValue tempb, tempc;  | 
218  | 156k  |   cTValue *b, *c;  | 
219  | 156k  |   if ((b = str2num(rb, &tempb)) != NULL &&  | 
220  | 156k  |       (c = str2num(rc, &tempc)) != NULL) {  /* Try coercion first. */ | 
221  | 8.80k  |     setnumV(ra, lj_vm_foldarith(numV(b), numV(c), (int)mm-MM_add));  | 
222  | 0  |     return NULL;  | 
223  | 147k  |   } else { | 
224  | 147k  |     cTValue *mo = lj_meta_lookup(L, rb, mm);  | 
225  | 147k  |     if (tvisnil(mo)) { | 
226  | 19.2k  |       mo = lj_meta_lookup(L, rc, mm);  | 
227  | 19.2k  |       if (tvisnil(mo)) { | 
228  | 3  |   if (str2num(rb, &tempb) == NULL) rc = rb;  | 
229  | 3  |   lj_err_optype(L, rc, LJ_ERR_OPARITH);  | 
230  | 0  |   return NULL;  /* unreachable */  | 
231  | 3  |       }  | 
232  | 19.2k  |     }  | 
233  | 147k  |     return mmcall(L, lj_cont_ra, mo, rb, rc);  | 
234  | 147k  |   }  | 
235  | 156k  | }  | 
236  |  |  | 
237  |  | /* Helper for CAT. Coercion, iterative concat, __concat metamethod. */  | 
238  |  | TValue *lj_meta_cat(lua_State *L, TValue *top, int left)  | 
239  | 125k  | { | 
240  | 125k  |   int fromc = 0;  | 
241  | 125k  |   if (left < 0) { left = -left; fromc = 1; } | 
242  | 127k  |   do { | 
243  | 127k  |     if (!(tvisstr(top) || tvisnumber(top)) ||  | 
244  | 127k  |   !(tvisstr(top-1) || tvisnumber(top-1))) { | 
245  | 49.4k  |       cTValue *mo = lj_meta_lookup(L, top-1, MM_concat);  | 
246  | 49.4k  |       if (tvisnil(mo)) { | 
247  | 4.54k  |   mo = lj_meta_lookup(L, top, MM_concat);  | 
248  | 4.54k  |   if (tvisnil(mo)) { | 
249  | 13  |     if (tvisstr(top-1) || tvisnumber(top-1)) top++;  | 
250  | 13  |     lj_err_optype(L, top-1, LJ_ERR_OPCAT);  | 
251  | 0  |     return NULL;  /* unreachable */  | 
252  | 13  |   }  | 
253  | 4.54k  |       }  | 
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  | 49.4k  |       copyTV(L, top+2*LJ_FR2+2, top);  /* Carefully ordered stack copies! */  | 
266  | 49.4k  |       copyTV(L, top+2*LJ_FR2+1, top-1);  | 
267  | 49.4k  |       copyTV(L, top+LJ_FR2, mo);  | 
268  | 49.4k  |       setcont(top-1, lj_cont_cat);  | 
269  | 49.4k  |       if (LJ_FR2) { setnilV(top); setnilV(top+2); top += 2; } | 
270  | 49.4k  |       return top+1;  /* Trigger metamethod call. */  | 
271  | 78.4k  |     } 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  | 78.4k  |       TValue *e, *o = top;  | 
280  | 137k  |       uint64_t tlen = tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM;  | 
281  | 78.4k  |       SBuf *sb;  | 
282  | 90.8k  |       do { | 
283  | 152k  |   o--; tlen += tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM;  | 
284  | 90.8k  |       } while (--left > 0 && (tvisstr(o-1) || tvisnumber(o-1)));  | 
285  | 78.4k  |       if (tlen >= LJ_MAX_STR) lj_err_msg(L, LJ_ERR_STROV);  | 
286  | 78.4k  |       sb = lj_buf_tmp_(L);  | 
287  | 78.4k  |       lj_buf_more(sb, (MSize)tlen);  | 
288  | 247k  |       for (e = top, top = o; o <= e; o++) { | 
289  | 169k  |   if (tvisstr(o)) { | 
290  | 144k  |     GCstr *s = strV(o);  | 
291  | 0  |     MSize len = s->len;  | 
292  | 144k  |     lj_buf_putmem(sb, strdata(s), len);  | 
293  | 144k  |   } else if (tvisint(o)) { | 
294  | 0  |     lj_strfmt_putint(sb, intV(o));  | 
295  | 24.5k  |   } else { | 
296  | 24.5k  |     lj_strfmt_putfnum(sb, STRFMT_G14, numV(o));  | 
297  | 24.5k  |   }  | 
298  | 169k  |       }  | 
299  | 78.4k  |       setstrV(L, top, lj_buf_str(L, sb));  | 
300  | 78.4k  |     }  | 
301  | 127k  |   } while (left >= 1);  | 
302  | 75.6k  |   if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) { | 
303  | 18.3k  |     if (!fromc) L->top = curr_topL(L);  | 
304  | 18.3k  |     lj_gc_step(L);  | 
305  | 18.3k  |   }  | 
306  | 75.6k  |   return NULL;  | 
307  | 75.6k  | }  | 
308  |  |  | 
309  |  | /* Helper for LEN. __len metamethod. */  | 
310  |  | TValue * LJ_FASTCALL lj_meta_len(lua_State *L, cTValue *o)  | 
311  | 7.69k  | { | 
312  | 7.69k  |   cTValue *mo = lj_meta_lookup(L, o, MM_len);  | 
313  | 7.69k  |   if (tvisnil(mo)) { | 
314  | 0  |     if (LJ_52 && tvistab(o))  | 
315  | 0  |       tabref(tabV(o)->metatable)->nomm |= (uint8_t)(1u<<MM_len);  | 
316  | 0  |     else  | 
317  | 0  |       lj_err_optype(L, o, LJ_ERR_OPLEN);  | 
318  | 0  |     return NULL;  | 
319  | 0  |   }  | 
320  | 7.69k  |   return mmcall(L, lj_cont_ra, mo, o, LJ_52 ? o : niltv(L));  | 
321  | 7.69k  | }  | 
322  |  |  | 
323  |  | /* Helper for equality comparisons. __eq metamethod. */  | 
324  |  | TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne)  | 
325  | 62  | { | 
326  |  |   /* Field metatable must be at same offset for GCtab and GCudata! */  | 
327  | 62  |   cTValue *mo = lj_meta_fast(L, tabref(o1->gch.metatable), MM_eq);  | 
328  | 62  |   if (mo) { | 
329  | 0  |     TValue *top;  | 
330  | 0  |     uint32_t it;  | 
331  | 0  |     if (tabref(o1->gch.metatable) != tabref(o2->gch.metatable)) { | 
332  | 0  |       cTValue *mo2 = lj_meta_fast(L, tabref(o2->gch.metatable), MM_eq);  | 
333  | 0  |       if (mo2 == NULL || !lj_obj_equal(mo, mo2))  | 
334  | 0  |   return (TValue *)(intptr_t)ne;  | 
335  | 0  |     }  | 
336  | 0  |     top = curr_top(L);  | 
337  | 0  |     setcont(top++, ne ? lj_cont_condf : lj_cont_condt);  | 
338  | 0  |     if (LJ_FR2) setnilV(top++);  | 
339  | 0  |     copyTV(L, top++, mo);  | 
340  | 0  |     if (LJ_FR2) setnilV(top++);  | 
341  | 0  |     it = ~(uint32_t)o1->gch.gct;  | 
342  | 0  |     setgcV(L, top, o1, it);  | 
343  | 0  |     setgcV(L, top+1, o2, it);  | 
344  | 0  |     return top;  /* Trigger metamethod call. */  | 
345  | 0  |   }  | 
346  | 62  |   return (TValue *)(intptr_t)ne;  | 
347  | 62  | }  | 
348  |  |  | 
349  |  | #if LJ_HASFFI  | 
350  |  | TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins)  | 
351  | 0  | { | 
352  | 0  |   ASMFunction cont = (bc_op(ins) & 1) ? lj_cont_condf : lj_cont_condt;  | 
353  | 0  |   int op = (int)bc_op(ins) & ~1;  | 
354  | 0  |   TValue tv;  | 
355  | 0  |   cTValue *mo, *o2, *o1 = &L->base[bc_a(ins)];  | 
356  | 0  |   cTValue *o1mm = o1;  | 
357  | 0  |   if (op == BC_ISEQV) { | 
358  | 0  |     o2 = &L->base[bc_d(ins)];  | 
359  | 0  |     if (!tviscdata(o1mm)) o1mm = o2;  | 
360  | 0  |   } else if (op == BC_ISEQS) { | 
361  | 0  |     setstrV(L, &tv, gco2str(proto_kgc(curr_proto(L), ~(ptrdiff_t)bc_d(ins))));  | 
362  | 0  |     o2 = &tv;  | 
363  | 0  |   } else if (op == BC_ISEQN) { | 
364  | 0  |     o2 = &mref(curr_proto(L)->k, cTValue)[bc_d(ins)];  | 
365  | 0  |   } else { | 
366  | 0  |     lj_assertL(op == BC_ISEQP, "bad bytecode op %d", op);  | 
367  | 0  |     setpriV(&tv, ~bc_d(ins));  | 
368  | 0  |     o2 = &tv;  | 
369  | 0  |   }  | 
370  | 0  |   mo = lj_meta_lookup(L, o1mm, MM_eq);  | 
371  | 0  |   if (LJ_LIKELY(!tvisnil(mo)))  | 
372  | 0  |     return mmcall(L, cont, mo, o1, o2);  | 
373  | 0  |   else  | 
374  | 0  |     return (TValue *)(intptr_t)(bc_op(ins) & 1);  | 
375  | 0  | }  | 
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  | 3.15k  | { | 
381  | 3.15k  |   if (LJ_HASFFI && (tviscdata(o1) || tviscdata(o2))) { | 
382  | 0  |     ASMFunction cont = (op & 1) ? lj_cont_condf : lj_cont_condt;  | 
383  | 0  |     MMS mm = (op & 2) ? MM_le : MM_lt;  | 
384  | 0  |     cTValue *mo = lj_meta_lookup(L, tviscdata(o1) ? o1 : o2, mm);  | 
385  | 0  |     if (LJ_UNLIKELY(tvisnil(mo))) goto err;  | 
386  | 0  |     return mmcall(L, cont, mo, o1, o2);  | 
387  | 3.15k  |   } else if (LJ_52 || itype(o1) == itype(o2)) { | 
388  |  |     /* Never called with two numbers. */  | 
389  | 3.13k  |     if (tvisstr(o1) && tvisstr(o2)) { | 
390  | 2.21k  |       int32_t res = lj_str_cmp(strV(o1), strV(o2));  | 
391  | 2.21k  |       return (TValue *)(intptr_t)(((op&2) ? res <= 0 : res < 0) ^ (op&1));  | 
392  | 2.21k  |     } else { | 
393  | 917  |     trymt:  | 
394  | 917  |       while (1) { | 
395  | 917  |   ASMFunction cont = (op & 1) ? lj_cont_condf : lj_cont_condt;  | 
396  | 917  |   MMS mm = (op & 2) ? MM_le : MM_lt;  | 
397  | 917  |   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  | 917  |   cTValue *mo2 = lj_meta_lookup(L, o2, mm);  | 
402  | 917  |   if (tvisnil(mo) || !lj_obj_equal(mo, mo2))  | 
403  | 0  | #endif  | 
404  | 0  |   { | 
405  | 0  |     if (op & 2) {  /* MM_le not found: retry with MM_lt. */ | 
406  | 0  |       cTValue *ot = o1; o1 = o2; o2 = ot;  /* Swap operands. */  | 
407  | 0  |       op ^= 3;  /* Use LT and flip condition. */  | 
408  | 0  |       continue;  | 
409  | 0  |     }  | 
410  | 0  |     goto err;  | 
411  | 0  |   }  | 
412  | 917  |   return mmcall(L, cont, mo, o1, o2);  | 
413  | 917  |       }  | 
414  | 917  |     }  | 
415  | 3.13k  |   } else if (tvisbool(o1) && tvisbool(o2)) { | 
416  | 0  |     goto trymt;  | 
417  | 18  |   } else { | 
418  | 18  |   err:  | 
419  | 18  |     lj_err_comp(L, o1, o2);  | 
420  | 0  |     return NULL;  | 
421  | 18  |   }  | 
422  | 3.15k  | }  | 
423  |  |  | 
424  |  | /* Helper for ISTYPE and ISNUM. Implicit coercion or error. */  | 
425  |  | void lj_meta_istype(lua_State *L, BCReg ra, BCReg tp)  | 
426  | 0  | { | 
427  | 0  |   L->top = curr_topL(L);  | 
428  | 0  |   ra++; tp--;  | 
429  | 0  |   lj_assertL(LJ_DUALNUM || tp != ~LJ_TNUMX, "bad type for ISTYPE");  | 
430  | 0  |   if (LJ_DUALNUM && tp == ~LJ_TNUMX) lj_lib_checkint(L, ra);  | 
431  | 0  |   else if (tp == ~LJ_TNUMX+1) lj_lib_checknum(L, ra);  | 
432  | 0  |   else if (tp == ~LJ_TSTR) lj_lib_checkstr(L, ra);  | 
433  | 0  |   else lj_err_argtype(L, ra, lj_obj_itypename[tp]);  | 
434  | 0  | }  | 
435  |  |  | 
436  |  | /* Helper for calls. __call metamethod. */  | 
437  |  | void lj_meta_call(lua_State *L, TValue *func, TValue *top)  | 
438  | 797k  | { | 
439  | 797k  |   cTValue *mo = lj_meta_lookup(L, func, MM_call);  | 
440  | 797k  |   TValue *p;  | 
441  | 797k  |   if (!tvisfunc(mo))  | 
442  | 4  |     lj_err_optype_call(L, func);  | 
443  | 1.21M  |   for (p = top; p > func+2*LJ_FR2; p--) copyTV(L, p, p-1);  | 
444  | 797k  |   if (LJ_FR2) copyTV(L, func+2, func);  | 
445  | 797k  |   copyTV(L, func, mo);  | 
446  | 797k  | }  | 
447  |  |  | 
448  |  | /* Helper for FORI. Coercion. */  | 
449  |  | void LJ_FASTCALL lj_meta_for(lua_State *L, TValue *o)  | 
450  | 60.7k  | { | 
451  | 60.7k  |   if (!lj_strscan_numberobj(o)) lj_err_msg(L, LJ_ERR_FORINIT);  | 
452  | 60.7k  |   if (!lj_strscan_numberobj(o+1)) lj_err_msg(L, LJ_ERR_FORLIM);  | 
453  | 60.7k  |   if (!lj_strscan_numberobj(o+2)) lj_err_msg(L, LJ_ERR_FORSTEP);  | 
454  | 60.7k  |   if (LJ_DUALNUM) { | 
455  |  |     /* Ensure all slots are integers or all slots are numbers. */  | 
456  | 0  |     int32_t k[3];  | 
457  | 0  |     int nint = 0;  | 
458  | 0  |     ptrdiff_t i;  | 
459  | 0  |     for (i = 0; i <= 2; i++) { | 
460  | 0  |       if (tvisint(o+i)) { | 
461  | 0  |   k[i] = intV(o+i); nint++;  | 
462  | 0  |       } else { | 
463  | 0  |   k[i] = lj_num2int(numV(o+i)); nint += ((lua_Number)k[i] == numV(o+i));  | 
464  | 0  |       }  | 
465  | 0  |     }  | 
466  | 0  |     if (nint == 3) {  /* Narrow to integers. */ | 
467  | 0  |       setintV(o, k[0]);  | 
468  | 0  |       setintV(o+1, k[1]);  | 
469  | 0  |       setintV(o+2, k[2]);  | 
470  | 0  |     } else if (nint != 0) {  /* Widen to numbers. */ | 
471  | 0  |       if (tvisint(o)) setnumV(o, (lua_Number)intV(o));  | 
472  | 0  |       if (tvisint(o+1)) setnumV(o+1, (lua_Number)intV(o+1));  | 
473  | 0  |       if (tvisint(o+2)) setnumV(o+2, (lua_Number)intV(o+2));  | 
474  | 0  |     }  | 
475  | 0  |   }  | 
476  | 60.7k  | }  | 
477  |  |  |