2 ** Metamethod handling.
3 ** Copyright (C) 2005-2017 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
21 #include "lj_strscan.h"
23 /* -- Metamethod handling ------------------------------------------------- */
25 /* String interning of metamethod names for fast indexing. */
26 void lj_meta_init(lua_State
*L
)
28 #define MMNAME(name) "__" #name
29 const char *metanames
= MMDEF(MMNAME
);
31 global_State
*g
= G(L
);
34 for (mm
= 0, p
= metanames
; *p
; mm
++, p
= q
) {
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
));
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
)
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. */
55 /* Lookup metamethod for object. */
56 cTValue
*lj_meta_lookup(lua_State
*L
, cTValue
*o
, MMS mm
)
60 mt
= tabref(tabV(o
)->metatable
);
61 else if (tvisudata(o
))
62 mt
= tabref(udataV(o
)->metatable
);
64 mt
= tabref(basemt_obj(G(L
), o
));
66 cTValue
*mo
= lj_tab_getstr(mt
, mmname_str(G(L
), mm
));
74 /* Tailcall from C function. */
75 int lj_meta_tailcall(lua_State
*L
, cTValue
*tv
)
77 TValue
*base
= L
->base
;
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
;
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;
87 ** before: [old_mo|PC] [... ...]
89 ** after: [new_mo|itype] [... ...] [NULL|PC] [dummy|delta]
91 ** tailcall: [new_mo|PC] [... ...]
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
)
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 ...]
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. */
120 return top
+2; /* Return new base. */
123 /* -- C helpers for some instructions, called from assembler VM ----------- */
125 /* Helper for TGET*. __index chain and metamethod. */
126 cTValue
*lj_meta_tget(lua_State
*L
, cTValue
*o
, cTValue
*k
)
129 for (loop
= 0; loop
< LJ_MAX_IDXCHAIN
; loop
++) {
131 if (LJ_LIKELY(tvistab(o
))) {
133 cTValue
*tv
= lj_tab_get(L
, t
, k
);
135 !(mo
= lj_meta_fast(L
, tabref(t
->metatable
), MM_index
)))
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 */
142 L
->top
= mmcall(L
, lj_cont_ra
, mo
, o
, k
);
143 return NULL
; /* Trigger metamethod call. */
147 lj_err_msg(L
, LJ_ERR_GETLOOP
);
148 return NULL
; /* unreachable */
151 /* Helper for TSET*. __newindex chain and metamethod. */
152 TValue
*lj_meta_tset(lua_State
*L
, cTValue
*o
, cTValue
*k
)
156 for (loop
= 0; loop
< LJ_MAX_IDXCHAIN
; loop
++) {
158 if (LJ_LIKELY(tvistab(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
);
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
);
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
);
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 */
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. */
187 lj_err_msg(L
, LJ_ERR_SETLOOP
);
188 return NULL
; /* unreachable */
191 static cTValue
*str2num(cTValue
*o
, TValue
*n
)
196 return (setnumV(n
, (lua_Number
)intV(o
)), n
);
197 else if (tvisstr(o
) && lj_strscan_num(strV(o
), n
))
203 /* Helper for arithmetic instructions. Coercion, metamethod. */
204 TValue
*lj_meta_arith(lua_State
*L
, TValue
*ra
, cTValue
*rb
, cTValue
*rc
,
207 MMS mm
= bcmode_mm(op
);
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
));
215 cTValue
*mo
= lj_meta_lookup(L
, rb
, mm
);
217 mo
= lj_meta_lookup(L
, rc
, mm
);
219 if (str2num(rb
, &tempb
) == NULL
) rc
= rb
;
220 lj_err_optype(L
, rc
, LJ_ERR_OPARITH
);
221 return NULL
; /* unreachable */
224 return mmcall(L
, lj_cont_ra
, mo
, rb
, rc
);
228 /* In-place coercion of a number to a string. */
229 static LJ_AINLINE
int tostring(lua_State
*L
, TValue
*o
)
233 } else if (tvisnumber(o
)) {
234 setstrV(L
, o
, lj_str_fromnumber(L
, o
));
241 /* Helper for CAT. Coercion, iterative concat, __concat metamethod. */
242 TValue
*lj_meta_cat(lua_State
*L
, TValue
*top
, int left
)
245 if (left
< 0) { left
= -left
; fromc
= 1; }
248 if (!(tvisstr(top
-1) || tvisnumber(top
-1)) || !tostring(L
, top
)) {
249 cTValue
*mo
= lj_meta_lookup(L
, top
-1, MM_concat
);
251 mo
= lj_meta_lookup(L
, top
, MM_concat
);
253 if (tvisstr(top
-1) || tvisnumber(top
-1)) top
++;
254 lj_err_optype(L
, top
-1, LJ_ERR_OPCAT
);
255 return NULL
; /* unreachable */
258 /* One of the top two elements is not a string, call __cat metamethod:
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 .............]
269 copyTV(L
, top
+2, top
); /* Careful with the order of stack copies! */
270 copyTV(L
, top
+1, top
-1);
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);
277 /* Pick as many strings as possible from the top and concatenate them:
279 ** before: [...][CAT stack ...........................]
280 ** pick str: [...][CAT stack ...] [...... strings ......]
281 ** concat: [...][CAT stack ...] [result]
282 ** next step: [...][CAT stack ............]
284 MSize tlen
= strV(top
)->len
;
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
);
293 buffer
= lj_str_needbuf(L
, &G(L
)->tmpbuf
, tlen
);
296 for (i
= n
; i
>= 0; i
--) {
297 MSize len
= strV(top
-i
)->len
;
298 memcpy(buffer
+ tlen
, strVdata(top
-i
), len
);
301 setstrV(L
, top
-n
, lj_str_new(L
, buffer
, tlen
));
306 if (LJ_UNLIKELY(G(L
)->gc
.total
>= G(L
)->gc
.threshold
)) {
307 if (!fromc
) L
->top
= curr_topL(L
);
313 /* Helper for LEN. __len metamethod. */
314 TValue
* LJ_FASTCALL
lj_meta_len(lua_State
*L
, cTValue
*o
)
316 cTValue
*mo
= lj_meta_lookup(L
, o
, MM_len
);
318 if (LJ_52
&& tvistab(o
))
319 tabref(tabV(o
)->metatable
)->nomm
|= (uint8_t)(1u<<MM_len
);
321 lj_err_optype(L
, o
, LJ_ERR_OPLEN
);
324 return mmcall(L
, lj_cont_ra
, mo
, o
, LJ_52
? o
: niltv(L
));
327 /* Helper for equality comparisons. __eq metamethod. */
328 TValue
*lj_meta_equal(lua_State
*L
, GCobj
*o1
, GCobj
*o2
, int ne
)
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
);
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
;
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. */
348 return (TValue
*)(intptr_t)ne
;
352 TValue
* LJ_FASTCALL
lj_meta_equal_cd(lua_State
*L
, BCIns ins
)
354 ASMFunction cont
= (bc_op(ins
) & 1) ? lj_cont_condf
: lj_cont_condt
;
355 int op
= (int)bc_op(ins
) & ~1;
357 cTValue
*mo
, *o2
, *o1
= &L
->base
[bc_a(ins
)];
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
))));
365 } else if (op
== BC_ISEQN
) {
366 o2
= &mref(curr_proto(L
)->k
, cTValue
)[bc_d(ins
)];
368 lua_assert(op
== BC_ISEQP
);
369 setitype(&tv
, ~bc_d(ins
));
372 mo
= lj_meta_lookup(L
, o1mm
, MM_eq
);
373 if (LJ_LIKELY(!tvisnil(mo
)))
374 return mmcall(L
, cont
, mo
, o1
, o2
);
376 return (TValue
*)(intptr_t)(bc_op(ins
) & 1);
380 /* Helper for ordered comparisons. String compare, __lt/__le metamethods. */
381 TValue
*lj_meta_comp(lua_State
*L
, cTValue
*o1
, cTValue
*o2
, int op
)
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));
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
);
401 if (tvisnil(mo
) && tvisnil((mo
= lj_meta_lookup(L
, o2
, mm
))))
403 cTValue
*mo2
= lj_meta_lookup(L
, o2
, mm
);
404 if (tvisnil(mo
) || !lj_obj_equal(mo
, mo2
))
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. */
414 return mmcall(L
, cont
, mo
, o1
, o2
);
417 } else if (tvisbool(o1
) && tvisbool(o2
)) {
421 lj_err_comp(L
, o1
, o2
);
426 /* Helper for calls. __call metamethod. */
427 void lj_meta_call(lua_State
*L
, TValue
*func
, TValue
*top
)
429 cTValue
*mo
= lj_meta_lookup(L
, func
, MM_call
);
432 lj_err_optype_call(L
, func
);
433 for (p
= top
; p
> func
; p
--) copyTV(L
, p
, p
-1);
437 /* Helper for FORI. Coercion. */
438 void LJ_FASTCALL
lj_meta_for(lua_State
*L
, TValue
*o
)
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
);
444 /* Ensure all slots are integers or all slots are numbers. */
448 for (i
= 0; i
<= 2; i
++) {
450 k
[i
] = intV(o
+i
); nint
++;
452 k
[i
] = lj_num2int(numV(o
+i
)); nint
+= ((lua_Number
)k
[i
] == numV(o
+i
));
455 if (nint
== 3) { /* Narrow to integers. */
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));