/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 | | |