1 | /* |
2 | ** Metamethod handling. |
3 | ** Copyright (C) 2005-2014 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 | |
467 | |