2 ** Metamethod handling.
3 ** Copyright (C) 2005-2014 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, tv
); /* Replace frame with new object. */
84 top
->u32
.lo
= LJ_CONT_TAILCALL
;
86 setframe_gc(top
+1, obj2gco(L
)); /* Dummy frame object. */
87 setframe_ftsz(top
+1, (int)((char *)(top
+2) - (char *)base
) + FRAME_CONT
);
88 L
->base
= L
->top
= top
+2;
90 ** before: [old_mo|PC] [... ...]
92 ** after: [new_mo|itype] [... ...] [NULL|PC] [dummy|delta]
94 ** tailcall: [new_mo|PC] [... ...]
101 /* Setup call to metamethod to be run by Assembler VM. */
102 static TValue
*mmcall(lua_State
*L
, ASMFunction cont
, cTValue
*mo
,
103 cTValue
*a
, cTValue
*b
)
106 ** |-- framesize -> top top+1 top+2 top+3
107 ** before: [func slots ...]
108 ** mm setup: [func slots ...] [cont|?] [mo|tmtype] [a] [b]
109 ** in asm: [func slots ...] [cont|PC] [mo|delta] [a] [b]
110 ** ^-- func base ^-- mm base
111 ** after mm: [func slots ...] [result]
112 ** ^-- copy to base[PC_RA] --/ for lj_cont_ra
113 ** istruecond + branch for lj_cont_cond*
114 ** ignore for lj_cont_nop
115 ** next PC: [func slots ...]
117 TValue
*top
= L
->top
;
118 if (curr_funcisL(L
)) top
= curr_topL(L
);
119 setcont(top
, cont
); /* Assembler VM stores PC in upper word. */
120 copyTV(L
, top
+1, mo
); /* Store metamethod and two arguments. */
123 return top
+2; /* Return new base. */
126 /* -- C helpers for some instructions, called from assembler VM ----------- */
128 /* Helper for TGET*. __index chain and metamethod. */
129 cTValue
*lj_meta_tget(lua_State
*L
, cTValue
*o
, cTValue
*k
)
132 for (loop
= 0; loop
< LJ_MAX_IDXCHAIN
; loop
++) {
134 if (LJ_LIKELY(tvistab(o
))) {
136 cTValue
*tv
= lj_tab_get(L
, t
, k
);
138 !(mo
= lj_meta_fast(L
, tabref(t
->metatable
), MM_index
)))
140 } else if (tvisnil(mo
= lj_meta_lookup(L
, o
, MM_index
))) {
141 lj_err_optype(L
, o
, LJ_ERR_OPINDEX
);
142 return NULL
; /* unreachable */
145 L
->top
= mmcall(L
, lj_cont_ra
, mo
, o
, k
);
146 return NULL
; /* Trigger metamethod call. */
150 lj_err_msg(L
, LJ_ERR_GETLOOP
);
151 return NULL
; /* unreachable */
154 /* Helper for TSET*. __newindex chain and metamethod. */
155 TValue
*lj_meta_tset(lua_State
*L
, cTValue
*o
, cTValue
*k
)
159 for (loop
= 0; loop
< LJ_MAX_IDXCHAIN
; loop
++) {
161 if (LJ_LIKELY(tvistab(o
))) {
163 cTValue
*tv
= lj_tab_get(L
, t
, k
);
164 if (LJ_LIKELY(!tvisnil(tv
))) {
165 t
->nomm
= 0; /* Invalidate negative metamethod cache. */
166 lj_gc_anybarriert(L
, t
);
168 } else if (!(mo
= lj_meta_fast(L
, tabref(t
->metatable
), MM_newindex
))) {
169 t
->nomm
= 0; /* Invalidate negative metamethod cache. */
170 lj_gc_anybarriert(L
, t
);
173 if (tvisnil(k
)) lj_err_msg(L
, LJ_ERR_NILIDX
);
174 else if (tvisint(k
)) { setnumV(&tmp
, (lua_Number
)intV(k
)); k
= &tmp
; }
175 else if (tvisnum(k
) && tvisnan(k
)) lj_err_msg(L
, LJ_ERR_NANIDX
);
176 return lj_tab_newkey(L
, t
, k
);
178 } else if (tvisnil(mo
= lj_meta_lookup(L
, o
, MM_newindex
))) {
179 lj_err_optype(L
, o
, LJ_ERR_OPINDEX
);
180 return NULL
; /* unreachable */
183 L
->top
= mmcall(L
, lj_cont_nop
, mo
, o
, k
);
184 /* L->top+2 = v filled in by caller. */
185 return NULL
; /* Trigger metamethod call. */
190 lj_err_msg(L
, LJ_ERR_SETLOOP
);
191 return NULL
; /* unreachable */
194 static cTValue
*str2num(cTValue
*o
, TValue
*n
)
199 return (setnumV(n
, (lua_Number
)intV(o
)), n
);
200 else if (tvisstr(o
) && lj_strscan_num(strV(o
), n
))
206 /* Helper for arithmetic instructions. Coercion, metamethod. */
207 TValue
*lj_meta_arith(lua_State
*L
, TValue
*ra
, cTValue
*rb
, cTValue
*rc
,
210 MMS mm
= bcmode_mm(op
);
213 if ((b
= str2num(rb
, &tempb
)) != NULL
&&
214 (c
= str2num(rc
, &tempc
)) != NULL
) { /* Try coercion first. */
215 setnumV(ra
, lj_vm_foldarith(numV(b
), numV(c
), (int)mm
-MM_add
));
218 cTValue
*mo
= lj_meta_lookup(L
, rb
, mm
);
220 mo
= lj_meta_lookup(L
, rc
, mm
);
222 if (str2num(rb
, &tempb
) == NULL
) rc
= rb
;
223 lj_err_optype(L
, rc
, LJ_ERR_OPARITH
);
224 return NULL
; /* unreachable */
227 return mmcall(L
, lj_cont_ra
, mo
, rb
, rc
);
231 /* Helper for CAT. Coercion, iterative concat, __concat metamethod. */
232 TValue
*lj_meta_cat(lua_State
*L
, TValue
*top
, int left
)
235 if (left
< 0) { left
= -left
; fromc
= 1; }
237 if (!(tvisstr(top
) || tvisnumber(top
)) ||
238 !(tvisstr(top
-1) || tvisnumber(top
-1))) {
239 cTValue
*mo
= lj_meta_lookup(L
, top
-1, MM_concat
);
241 mo
= lj_meta_lookup(L
, top
, MM_concat
);
243 if (tvisstr(top
-1) || tvisnumber(top
-1)) top
++;
244 lj_err_optype(L
, top
-1, LJ_ERR_OPCAT
);
245 return NULL
; /* unreachable */
248 /* One of the top two elements is not a string, call __cat metamethod:
250 ** before: [...][CAT stack .........................]
251 ** top-1 top top+1 top+2
252 ** pick two: [...][CAT stack ...] [o1] [o2]
253 ** setup mm: [...][CAT stack ...] [cont|?] [mo|tmtype] [o1] [o2]
254 ** in asm: [...][CAT stack ...] [cont|PC] [mo|delta] [o1] [o2]
255 ** ^-- func base ^-- mm base
256 ** after mm: [...][CAT stack ...] <--push-- [result]
257 ** next step: [...][CAT stack .............]
259 copyTV(L
, top
+2, top
); /* Careful with the order of stack copies! */
260 copyTV(L
, top
+1, top
-1);
262 setcont(top
-1, lj_cont_cat
);
263 return top
+1; /* Trigger metamethod call. */
265 /* Pick as many strings as possible from the top and concatenate them:
267 ** before: [...][CAT stack ...........................]
268 ** pick str: [...][CAT stack ...] [...... strings ......]
269 ** concat: [...][CAT stack ...] [result]
270 ** next step: [...][CAT stack ............]
273 uint64_t tlen
= tvisstr(o
) ? strV(o
)->len
: STRFMT_MAXBUF_NUM
;
276 o
--; tlen
+= tvisstr(o
) ? strV(o
)->len
: STRFMT_MAXBUF_NUM
;
277 } while (--left
> 0 && (tvisstr(o
-1) || tvisnumber(o
-1)));
278 if (tlen
>= LJ_MAX_STR
) lj_err_msg(L
, LJ_ERR_STROV
);
279 p
= buf
= lj_buf_tmp(L
, (MSize
)tlen
);
280 for (e
= top
, top
= o
; o
<= e
; o
++) {
284 p
= lj_buf_wmem(p
, strdata(s
), len
);
285 } else if (tvisint(o
)) {
286 p
= lj_strfmt_wint(p
, intV(o
));
288 lua_assert(tvisnum(o
));
289 p
= lj_strfmt_wnum(p
, o
);
292 setstrV(L
, top
, lj_str_new(L
, buf
, (size_t)(p
-buf
)));
295 if (LJ_UNLIKELY(G(L
)->gc
.total
>= G(L
)->gc
.threshold
)) {
296 if (!fromc
) L
->top
= curr_topL(L
);
302 /* Helper for LEN. __len metamethod. */
303 TValue
* LJ_FASTCALL
lj_meta_len(lua_State
*L
, cTValue
*o
)
305 cTValue
*mo
= lj_meta_lookup(L
, o
, MM_len
);
307 if (LJ_52
&& tvistab(o
))
308 tabref(tabV(o
)->metatable
)->nomm
|= (uint8_t)(1u<<MM_len
);
310 lj_err_optype(L
, o
, LJ_ERR_OPLEN
);
313 return mmcall(L
, lj_cont_ra
, mo
, o
, LJ_52
? o
: niltv(L
));
316 /* Helper for equality comparisons. __eq metamethod. */
317 TValue
*lj_meta_equal(lua_State
*L
, GCobj
*o1
, GCobj
*o2
, int ne
)
319 /* Field metatable must be at same offset for GCtab and GCudata! */
320 cTValue
*mo
= lj_meta_fast(L
, tabref(o1
->gch
.metatable
), MM_eq
);
324 if (tabref(o1
->gch
.metatable
) != tabref(o2
->gch
.metatable
)) {
325 cTValue
*mo2
= lj_meta_fast(L
, tabref(o2
->gch
.metatable
), MM_eq
);
326 if (mo2
== NULL
|| !lj_obj_equal(mo
, mo2
))
327 return (TValue
*)(intptr_t)ne
;
330 setcont(top
, ne
? lj_cont_condf
: lj_cont_condt
);
331 copyTV(L
, top
+1, mo
);
332 it
= ~(uint32_t)o1
->gch
.gct
;
333 setgcV(L
, top
+2, o1
, it
);
334 setgcV(L
, top
+3, o2
, it
);
335 return top
+2; /* Trigger metamethod call. */
337 return (TValue
*)(intptr_t)ne
;
341 TValue
* LJ_FASTCALL
lj_meta_equal_cd(lua_State
*L
, BCIns ins
)
343 ASMFunction cont
= (bc_op(ins
) & 1) ? lj_cont_condf
: lj_cont_condt
;
344 int op
= (int)bc_op(ins
) & ~1;
346 cTValue
*mo
, *o2
, *o1
= &L
->base
[bc_a(ins
)];
348 if (op
== BC_ISEQV
) {
349 o2
= &L
->base
[bc_d(ins
)];
350 if (!tviscdata(o1mm
)) o1mm
= o2
;
351 } else if (op
== BC_ISEQS
) {
352 setstrV(L
, &tv
, gco2str(proto_kgc(curr_proto(L
), ~(ptrdiff_t)bc_d(ins
))));
354 } else if (op
== BC_ISEQN
) {
355 o2
= &mref(curr_proto(L
)->k
, cTValue
)[bc_d(ins
)];
357 lua_assert(op
== BC_ISEQP
);
358 setitype(&tv
, ~bc_d(ins
));
361 mo
= lj_meta_lookup(L
, o1mm
, MM_eq
);
362 if (LJ_LIKELY(!tvisnil(mo
)))
363 return mmcall(L
, cont
, mo
, o1
, o2
);
365 return (TValue
*)(intptr_t)(bc_op(ins
) & 1);
369 /* Helper for ordered comparisons. String compare, __lt/__le metamethods. */
370 TValue
*lj_meta_comp(lua_State
*L
, cTValue
*o1
, cTValue
*o2
, int op
)
372 if (LJ_HASFFI
&& (tviscdata(o1
) || tviscdata(o2
))) {
373 ASMFunction cont
= (op
& 1) ? lj_cont_condf
: lj_cont_condt
;
374 MMS mm
= (op
& 2) ? MM_le
: MM_lt
;
375 cTValue
*mo
= lj_meta_lookup(L
, tviscdata(o1
) ? o1
: o2
, mm
);
376 if (LJ_UNLIKELY(tvisnil(mo
))) goto err
;
377 return mmcall(L
, cont
, mo
, o1
, o2
);
378 } else if (LJ_52
|| itype(o1
) == itype(o2
)) {
379 /* Never called with two numbers. */
380 if (tvisstr(o1
) && tvisstr(o2
)) {
381 int32_t res
= lj_str_cmp(strV(o1
), strV(o2
));
382 return (TValue
*)(intptr_t)(((op
&2) ? res
<= 0 : res
< 0) ^ (op
&1));
386 ASMFunction cont
= (op
& 1) ? lj_cont_condf
: lj_cont_condt
;
387 MMS mm
= (op
& 2) ? MM_le
: MM_lt
;
388 cTValue
*mo
= lj_meta_lookup(L
, o1
, mm
);
390 if (tvisnil(mo
) && tvisnil((mo
= lj_meta_lookup(L
, o2
, mm
))))
392 cTValue
*mo2
= lj_meta_lookup(L
, o2
, mm
);
393 if (tvisnil(mo
) || !lj_obj_equal(mo
, mo2
))
396 if (op
& 2) { /* MM_le not found: retry with MM_lt. */
397 cTValue
*ot
= o1
; o1
= o2
; o2
= ot
; /* Swap operands. */
398 op
^= 3; /* Use LT and flip condition. */
403 return mmcall(L
, cont
, mo
, o1
, o2
);
406 } else if (tvisbool(o1
) && tvisbool(o2
)) {
410 lj_err_comp(L
, o1
, o2
);
415 /* Helper for ISTYPE and ISNUM. Implicit coercion or error. */
416 void lj_meta_istype(lua_State
*L
, BCReg ra
, BCReg tp
)
418 L
->top
= curr_topL(L
);
420 lua_assert(LJ_DUALNUM
|| tp
!= ~LJ_TNUMX
); /* ISTYPE -> ISNUM broken. */
421 if (LJ_DUALNUM
&& tp
== ~LJ_TNUMX
) lj_lib_checkint(L
, ra
);
422 else if (tp
== ~LJ_TNUMX
+1) lj_lib_checknum(L
, ra
);
423 else if (tp
== ~LJ_TSTR
) lj_lib_checkstr(L
, ra
);
424 else lj_err_argtype(L
, ra
, lj_obj_itypename
[tp
]);
427 /* Helper for calls. __call metamethod. */
428 void lj_meta_call(lua_State
*L
, TValue
*func
, TValue
*top
)
430 cTValue
*mo
= lj_meta_lookup(L
, func
, MM_call
);
433 lj_err_optype_call(L
, func
);
434 for (p
= top
; p
> func
; p
--) copyTV(L
, p
, p
-1);
438 /* Helper for FORI. Coercion. */
439 void LJ_FASTCALL
lj_meta_for(lua_State
*L
, TValue
*o
)
441 if (!lj_strscan_numberobj(o
)) lj_err_msg(L
, LJ_ERR_FORINIT
);
442 if (!lj_strscan_numberobj(o
+1)) lj_err_msg(L
, LJ_ERR_FORLIM
);
443 if (!lj_strscan_numberobj(o
+2)) lj_err_msg(L
, LJ_ERR_FORSTEP
);
445 /* Ensure all slots are integers or all slots are numbers. */
449 for (i
= 0; i
<= 2; i
++) {
451 k
[i
] = intV(o
+i
); nint
++;
453 k
[i
] = lj_num2int(numV(o
+i
)); nint
+= ((lua_Number
)k
[i
] == numV(o
+i
));
456 if (nint
== 3) { /* Narrow to integers. */
460 } else if (nint
!= 0) { /* Widen to numbers. */
461 if (tvisint(o
)) setnumV(o
, (lua_Number
)intV(o
));
462 if (tvisint(o
+1)) setnumV(o
+1, (lua_Number
)intV(o
+1));
463 if (tvisint(o
+2)) setnumV(o
+2, (lua_Number
)intV(o
+2));