2 ** Metamethod handling.
3 ** Copyright (C) 2005-2015 Mike Pall. See Copyright Notice in luajit.h
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
22 #include "lj_strscan.h"
23 #include "lj_strfmt.h"
26 /* -- Metamethod handling ------------------------------------------------- */
28 /* String interning of metamethod names for fast indexing. */
29 void lj_meta_init(lua_State
*L
)
31 #define MMNAME(name) "__" #name
32 const char *metanames
= MMDEF(MMNAME
);
34 global_State
*g
= G(L
);
37 for (mm
= 0, p
= metanames
; *p
; mm
++, p
= q
) {
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
));
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
)
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. */
58 /* Lookup metamethod for object. */
59 cTValue
*lj_meta_lookup(lua_State
*L
, cTValue
*o
, MMS mm
)
63 mt
= tabref(tabV(o
)->metatable
);
64 else if (tvisudata(o
))
65 mt
= tabref(udataV(o
)->metatable
);
67 mt
= tabref(basemt_obj(G(L
), o
));
69 cTValue
*mo
= lj_tab_getstr(mt
, mmname_str(G(L
), mm
));
77 /* Tailcall from C function. */
78 int lj_meta_tailcall(lua_State
*L
, cTValue
*tv
)
80 TValue
*base
= L
->base
;
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. */
85 (top
++)->u64
= LJ_CONT_TAILCALL
;
87 top
->u32
.lo
= LJ_CONT_TAILCALL
;
88 setframe_pc(top
++, pc
);
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;
94 ** before: [old_mo|PC] [... ...]
96 ** after: [new_mo|itype] [... ...] [NULL|PC] [dummy|delta]
98 ** tailcall: [new_mo|PC] [... ...]
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
)
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 ...]
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
++);
129 return top
; /* Return new base. */
132 /* -- C helpers for some instructions, called from assembler VM ----------- */
134 /* Helper for TGET*. __index chain and metamethod. */
135 cTValue
*lj_meta_tget(lua_State
*L
, cTValue
*o
, cTValue
*k
)
138 for (loop
= 0; loop
< LJ_MAX_IDXCHAIN
; loop
++) {
140 if (LJ_LIKELY(tvistab(o
))) {
142 cTValue
*tv
= lj_tab_get(L
, t
, k
);
144 !(mo
= lj_meta_fast(L
, tabref(t
->metatable
), MM_index
)))
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 */
151 L
->top
= mmcall(L
, lj_cont_ra
, mo
, o
, k
);
152 return NULL
; /* Trigger metamethod call. */
156 lj_err_msg(L
, LJ_ERR_GETLOOP
);
157 return NULL
; /* unreachable */
160 /* Helper for TSET*. __newindex chain and metamethod. */
161 TValue
*lj_meta_tset(lua_State
*L
, cTValue
*o
, cTValue
*k
)
165 for (loop
= 0; loop
< LJ_MAX_IDXCHAIN
; loop
++) {
167 if (LJ_LIKELY(tvistab(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
);
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
);
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
);
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 */
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. */
196 lj_err_msg(L
, LJ_ERR_SETLOOP
);
197 return NULL
; /* unreachable */
200 static cTValue
*str2num(cTValue
*o
, TValue
*n
)
205 return (setnumV(n
, (lua_Number
)intV(o
)), n
);
206 else if (tvisstr(o
) && lj_strscan_num(strV(o
), n
))
212 /* Helper for arithmetic instructions. Coercion, metamethod. */
213 TValue
*lj_meta_arith(lua_State
*L
, TValue
*ra
, cTValue
*rb
, cTValue
*rc
,
216 MMS mm
= bcmode_mm(op
);
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
));
224 cTValue
*mo
= lj_meta_lookup(L
, rb
, mm
);
226 mo
= lj_meta_lookup(L
, rc
, mm
);
228 if (str2num(rb
, &tempb
) == NULL
) rc
= rb
;
229 lj_err_optype(L
, rc
, LJ_ERR_OPARITH
);
230 return NULL
; /* unreachable */
233 return mmcall(L
, lj_cont_ra
, mo
, rb
, rc
);
237 /* Helper for CAT. Coercion, iterative concat, __concat metamethod. */
238 TValue
*lj_meta_cat(lua_State
*L
, TValue
*top
, int left
)
241 if (left
< 0) { left
= -left
; fromc
= 1; }
243 if (!(tvisstr(top
) || tvisnumber(top
)) ||
244 !(tvisstr(top
-1) || tvisnumber(top
-1))) {
245 cTValue
*mo
= lj_meta_lookup(L
, top
-1, MM_concat
);
247 mo
= lj_meta_lookup(L
, top
, MM_concat
);
249 if (tvisstr(top
-1) || tvisnumber(top
-1)) top
++;
250 lj_err_optype(L
, top
-1, LJ_ERR_OPCAT
);
251 return NULL
; /* unreachable */
254 /* One of the top two elements is not a string, call __cat metamethod:
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 .............]
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. */
272 /* Pick as many strings as possible from the top and concatenate them:
274 ** before: [...][CAT stack ...........................]
275 ** pick str: [...][CAT stack ...] [...... strings ......]
276 ** concat: [...][CAT stack ...] [result]
277 ** next step: [...][CAT stack ............]
280 uint64_t tlen
= tvisstr(o
) ? strV(o
)->len
: STRFMT_MAXBUF_NUM
;
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 p
= buf
= lj_buf_tmp(L
, (MSize
)tlen
);
287 for (e
= top
, top
= o
; o
<= e
; o
++) {
291 p
= lj_buf_wmem(p
, strdata(s
), len
);
292 } else if (tvisint(o
)) {
293 p
= lj_strfmt_wint(p
, intV(o
));
295 lua_assert(tvisnum(o
));
296 p
= lj_strfmt_wnum(p
, o
);
299 setstrV(L
, top
, lj_str_new(L
, buf
, (size_t)(p
-buf
)));
302 if (LJ_UNLIKELY(G(L
)->gc
.total
>= G(L
)->gc
.threshold
)) {
303 if (!fromc
) L
->top
= curr_topL(L
);
309 /* Helper for LEN. __len metamethod. */
310 TValue
* LJ_FASTCALL
lj_meta_len(lua_State
*L
, cTValue
*o
)
312 cTValue
*mo
= lj_meta_lookup(L
, o
, MM_len
);
314 if (LJ_52
&& tvistab(o
))
315 tabref(tabV(o
)->metatable
)->nomm
|= (uint8_t)(1u<<MM_len
);
317 lj_err_optype(L
, o
, LJ_ERR_OPLEN
);
320 return mmcall(L
, lj_cont_ra
, mo
, o
, LJ_52
? o
: niltv(L
));
323 /* Helper for equality comparisons. __eq metamethod. */
324 TValue
*lj_meta_equal(lua_State
*L
, GCobj
*o1
, GCobj
*o2
, int ne
)
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
);
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
;
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. */
346 return (TValue
*)(intptr_t)ne
;
350 TValue
* LJ_FASTCALL
lj_meta_equal_cd(lua_State
*L
, BCIns ins
)
352 ASMFunction cont
= (bc_op(ins
) & 1) ? lj_cont_condf
: lj_cont_condt
;
353 int op
= (int)bc_op(ins
) & ~1;
355 cTValue
*mo
, *o2
, *o1
= &L
->base
[bc_a(ins
)];
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
))));
363 } else if (op
== BC_ISEQN
) {
364 o2
= &mref(curr_proto(L
)->k
, cTValue
)[bc_d(ins
)];
366 lua_assert(op
== BC_ISEQP
);
367 setpriV(&tv
, ~bc_d(ins
));
370 mo
= lj_meta_lookup(L
, o1mm
, MM_eq
);
371 if (LJ_LIKELY(!tvisnil(mo
)))
372 return mmcall(L
, cont
, mo
, o1
, o2
);
374 return (TValue
*)(intptr_t)(bc_op(ins
) & 1);
378 /* Helper for ordered comparisons. String compare, __lt/__le metamethods. */
379 TValue
*lj_meta_comp(lua_State
*L
, cTValue
*o1
, cTValue
*o2
, int op
)
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));
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
);
399 if (tvisnil(mo
) && tvisnil((mo
= lj_meta_lookup(L
, o2
, mm
))))
401 cTValue
*mo2
= lj_meta_lookup(L
, o2
, mm
);
402 if (tvisnil(mo
) || !lj_obj_equal(mo
, mo2
))
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. */
412 return mmcall(L
, cont
, mo
, o1
, o2
);
415 } else if (tvisbool(o1
) && tvisbool(o2
)) {
419 lj_err_comp(L
, o1
, o2
);
424 /* Helper for ISTYPE and ISNUM. Implicit coercion or error. */
425 void lj_meta_istype(lua_State
*L
, BCReg ra
, BCReg tp
)
427 L
->top
= curr_topL(L
);
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
]);
436 /* Helper for calls. __call metamethod. */
437 void lj_meta_call(lua_State
*L
, TValue
*func
, TValue
*top
)
439 cTValue
*mo
= lj_meta_lookup(L
, func
, MM_call
);
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
);
448 /* Helper for FORI. Coercion. */
449 void LJ_FASTCALL
lj_meta_for(lua_State
*L
, TValue
*o
)
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
);
455 /* Ensure all slots are integers or all slots are numbers. */
459 for (i
= 0; i
<= 2; i
++) {
461 k
[i
] = intV(o
+i
); nint
++;
463 k
[i
] = lj_num2int(numV(o
+i
)); nint
+= ((lua_Number
)k
[i
] == numV(o
+i
));
466 if (nint
== 3) { /* Narrow to integers. */
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));