2 ** Metamethod handling.
3 ** Copyright (C) 2005-2012 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 /* -- Metamethod handling ------------------------------------------------- */
24 /* String interning of metamethod names for fast indexing. */
25 void lj_meta_init(lua_State
*L
)
27 #define MMNAME(name) "__" #name
28 const char *metanames
= MMDEF(MMNAME
);
30 global_State
*g
= G(L
);
33 for (mm
= 0, p
= metanames
; *p
; mm
++, p
= q
) {
35 for (q
= p
+2; *q
&& *q
!= '_'; q
++) ;
36 s
= lj_str_new(L
, p
, (size_t)(q
-p
));
37 /* NOBARRIER: g->gcroot[] is a GC root. */
38 setgcref(g
->gcroot
[GCROOT_MMNAME
+mm
], obj2gco(s
));
42 /* Negative caching of a few fast metamethods. See the lj_meta_fast() macro. */
43 cTValue
*lj_meta_cache(GCtab
*mt
, MMS mm
, GCstr
*name
)
45 cTValue
*mo
= lj_tab_getstr(mt
, name
);
46 lua_assert(mm
<= MM_FAST
);
47 if (!mo
|| tvisnil(mo
)) { /* No metamethod? */
48 mt
->nomm
|= (uint8_t)(1u<<mm
); /* Set negative cache flag. */
54 /* Lookup metamethod for object. */
55 cTValue
*lj_meta_lookup(lua_State
*L
, cTValue
*o
, MMS mm
)
59 mt
= tabref(tabV(o
)->metatable
);
60 else if (tvisudata(o
))
61 mt
= tabref(udataV(o
)->metatable
);
63 mt
= tabref(basemt_obj(G(L
), o
));
65 cTValue
*mo
= lj_tab_getstr(mt
, mmname_str(G(L
), mm
));
73 /* Tailcall from C function. */
74 int lj_meta_tailcall(lua_State
*L
, cTValue
*tv
)
76 TValue
*base
= L
->base
;
78 const BCIns
*pc
= frame_pc(base
-1); /* Preserve old PC from frame. */
79 copyTV(L
, base
-1, tv
); /* Replace frame with new object. */
80 top
->u32
.lo
= LJ_CONT_TAILCALL
;
82 setframe_gc(top
+1, obj2gco(L
)); /* Dummy frame object. */
83 setframe_ftsz(top
+1, (int)((char *)(top
+2) - (char *)base
) + FRAME_CONT
);
84 L
->base
= L
->top
= top
+2;
86 ** before: [old_mo|PC] [... ...]
88 ** after: [new_mo|itype] [... ...] [NULL|PC] [dummy|delta]
90 ** tailcall: [new_mo|PC] [... ...]
97 /* Setup call to metamethod to be run by Assembler VM. */
98 static TValue
*mmcall(lua_State
*L
, ASMFunction cont
, cTValue
*mo
,
99 cTValue
*a
, cTValue
*b
)
102 ** |-- framesize -> top top+1 top+2 top+3
103 ** before: [func slots ...]
104 ** mm setup: [func slots ...] [cont|?] [mo|tmtype] [a] [b]
105 ** in asm: [func slots ...] [cont|PC] [mo|delta] [a] [b]
106 ** ^-- func base ^-- mm base
107 ** after mm: [func slots ...] [result]
108 ** ^-- copy to base[PC_RA] --/ for lj_cont_ra
109 ** istruecond + branch for lj_cont_cond*
110 ** ignore for lj_cont_nop
111 ** next PC: [func slots ...]
113 TValue
*top
= L
->top
;
114 if (curr_funcisL(L
)) top
= curr_topL(L
);
115 setcont(top
, cont
); /* Assembler VM stores PC in upper word. */
116 copyTV(L
, top
+1, mo
); /* Store metamethod and two arguments. */
119 return top
+2; /* Return new base. */
122 /* -- C helpers for some instructions, called from assembler VM ----------- */
124 /* Helper for TGET*. __index chain and metamethod. */
125 cTValue
*lj_meta_tget(lua_State
*L
, cTValue
*o
, cTValue
*k
)
128 for (loop
= 0; loop
< LJ_MAX_IDXCHAIN
; loop
++) {
130 if (LJ_LIKELY(tvistab(o
))) {
132 cTValue
*tv
= lj_tab_get(L
, t
, k
);
134 !(mo
= lj_meta_fast(L
, tabref(t
->metatable
), MM_index
)))
136 } else if (tvisnil(mo
= lj_meta_lookup(L
, o
, MM_index
))) {
137 lj_err_optype(L
, o
, LJ_ERR_OPINDEX
);
138 return NULL
; /* unreachable */
141 L
->top
= mmcall(L
, lj_cont_ra
, mo
, o
, k
);
142 return NULL
; /* Trigger metamethod call. */
146 lj_err_msg(L
, LJ_ERR_GETLOOP
);
147 return NULL
; /* unreachable */
150 /* Helper for TSET*. __newindex chain and metamethod. */
151 TValue
*lj_meta_tset(lua_State
*L
, cTValue
*o
, cTValue
*k
)
155 for (loop
= 0; loop
< LJ_MAX_IDXCHAIN
; loop
++) {
157 if (LJ_LIKELY(tvistab(o
))) {
159 cTValue
*tv
= lj_tab_get(L
, t
, k
);
160 if (LJ_LIKELY(!tvisnil(tv
))) {
161 t
->nomm
= 0; /* Invalidate negative metamethod cache. */
162 lj_gc_anybarriert(L
, t
);
164 } else if (!(mo
= lj_meta_fast(L
, tabref(t
->metatable
), MM_newindex
))) {
165 t
->nomm
= 0; /* Invalidate negative metamethod cache. */
166 lj_gc_anybarriert(L
, t
);
169 if (tvisnil(k
)) lj_err_msg(L
, LJ_ERR_NILIDX
);
170 else if (tvisint(k
)) { setnumV(&tmp
, (lua_Number
)intV(k
)); k
= &tmp
; }
171 else if (tvisnum(k
) && tvisnan(k
)) lj_err_msg(L
, LJ_ERR_NANIDX
);
172 return lj_tab_newkey(L
, t
, k
);
174 } else if (tvisnil(mo
= lj_meta_lookup(L
, o
, MM_newindex
))) {
175 lj_err_optype(L
, o
, LJ_ERR_OPINDEX
);
176 return NULL
; /* unreachable */
179 L
->top
= mmcall(L
, lj_cont_nop
, mo
, o
, k
);
180 /* L->top+2 = v filled in by caller. */
181 return NULL
; /* Trigger metamethod call. */
186 lj_err_msg(L
, LJ_ERR_SETLOOP
);
187 return NULL
; /* unreachable */
190 static cTValue
*str2num(cTValue
*o
, TValue
*n
)
195 return (setnumV(n
, (lua_Number
)intV(o
)), n
);
196 else if (tvisstr(o
) && lj_str_tonum(strV(o
), n
))
202 /* Helper for arithmetic instructions. Coercion, metamethod. */
203 TValue
*lj_meta_arith(lua_State
*L
, TValue
*ra
, cTValue
*rb
, cTValue
*rc
,
206 MMS mm
= bcmode_mm(op
);
209 if ((b
= str2num(rb
, &tempb
)) != NULL
&&
210 (c
= str2num(rc
, &tempc
)) != NULL
) { /* Try coercion first. */
211 setnumV(ra
, lj_vm_foldarith(numV(b
), numV(c
), (int)mm
-MM_add
));
214 cTValue
*mo
= lj_meta_lookup(L
, rb
, mm
);
216 mo
= lj_meta_lookup(L
, rc
, mm
);
218 if (str2num(rb
, &tempb
) == NULL
) rc
= rb
;
219 lj_err_optype(L
, rc
, LJ_ERR_OPARITH
);
220 return NULL
; /* unreachable */
223 return mmcall(L
, lj_cont_ra
, mo
, rb
, rc
);
227 /* In-place coercion of a number to a string. */
228 static LJ_AINLINE
int tostring(lua_State
*L
, TValue
*o
)
232 } else if (tvisnumber(o
)) {
233 setstrV(L
, o
, lj_str_fromnumber(L
, o
));
240 /* Helper for CAT. Coercion, iterative concat, __concat metamethod. */
241 TValue
*lj_meta_cat(lua_State
*L
, TValue
*top
, int left
)
244 if (left
< 0) { left
= -left
; fromc
= 1; }
247 if (!(tvisstr(top
-1) || tvisnumber(top
-1)) || !tostring(L
, top
)) {
248 cTValue
*mo
= lj_meta_lookup(L
, top
-1, MM_concat
);
250 mo
= lj_meta_lookup(L
, top
, MM_concat
);
252 if (tvisstr(top
-1) || tvisnumber(top
-1)) top
++;
253 lj_err_optype(L
, top
-1, LJ_ERR_OPCAT
);
254 return NULL
; /* unreachable */
257 /* One of the top two elements is not a string, call __cat metamethod:
259 ** before: [...][CAT stack .........................]
260 ** top-1 top top+1 top+2
261 ** pick two: [...][CAT stack ...] [o1] [o2]
262 ** setup mm: [...][CAT stack ...] [cont|?] [mo|tmtype] [o1] [o2]
263 ** in asm: [...][CAT stack ...] [cont|PC] [mo|delta] [o1] [o2]
264 ** ^-- func base ^-- mm base
265 ** after mm: [...][CAT stack ...] <--push-- [result]
266 ** next step: [...][CAT stack .............]
268 copyTV(L
, top
+2, top
); /* Careful with the order of stack copies! */
269 copyTV(L
, top
+1, top
-1);
271 setcont(top
-1, lj_cont_cat
);
272 return top
+1; /* Trigger metamethod call. */
273 } else if (strV(top
)->len
== 0) { /* Shortcut. */
274 (void)tostring(L
, top
-1);
276 /* Pick as many strings as possible from the top and concatenate them:
278 ** before: [...][CAT stack ...........................]
279 ** pick str: [...][CAT stack ...] [...... strings ......]
280 ** concat: [...][CAT stack ...] [result]
281 ** next step: [...][CAT stack ............]
283 MSize tlen
= strV(top
)->len
;
286 for (n
= 1; n
<= left
&& tostring(L
, top
-n
); n
++) {
287 MSize len
= strV(top
-n
)->len
;
288 if (len
>= LJ_MAX_STR
- tlen
)
289 lj_err_msg(L
, LJ_ERR_STROV
);
292 buffer
= lj_str_needbuf(L
, &G(L
)->tmpbuf
, tlen
);
295 for (i
= n
; i
>= 0; i
--) {
296 MSize len
= strV(top
-i
)->len
;
297 memcpy(buffer
+ tlen
, strVdata(top
-i
), len
);
300 setstrV(L
, top
-n
, lj_str_new(L
, buffer
, tlen
));
305 if (LJ_UNLIKELY(G(L
)->gc
.total
>= G(L
)->gc
.threshold
)) {
306 if (!fromc
) L
->top
= curr_topL(L
);
312 /* Helper for LEN. __len metamethod. */
313 TValue
* LJ_FASTCALL
lj_meta_len(lua_State
*L
, cTValue
*o
)
315 cTValue
*mo
= lj_meta_lookup(L
, o
, MM_len
);
317 #ifdef LUAJIT_ENABLE_LUA52COMPAT
319 tabref(tabV(o
)->metatable
)->nomm
|= (uint8_t)(1u<<MM_len
);
322 lj_err_optype(L
, o
, LJ_ERR_OPLEN
);
325 #ifdef LUAJIT_ENABLE_LUA52COMPAT
326 return mmcall(L
, lj_cont_ra
, mo
, o
, o
);
328 return mmcall(L
, lj_cont_ra
, mo
, o
, niltv(L
));
332 /* Helper for equality comparisons. __eq metamethod. */
333 TValue
*lj_meta_equal(lua_State
*L
, GCobj
*o1
, GCobj
*o2
, int ne
)
335 /* Field metatable must be at same offset for GCtab and GCudata! */
336 cTValue
*mo
= lj_meta_fast(L
, tabref(o1
->gch
.metatable
), MM_eq
);
340 if (tabref(o1
->gch
.metatable
) != tabref(o2
->gch
.metatable
)) {
341 cTValue
*mo2
= lj_meta_fast(L
, tabref(o2
->gch
.metatable
), MM_eq
);
342 if (mo2
== NULL
|| !lj_obj_equal(mo
, mo2
))
343 return (TValue
*)(intptr_t)ne
;
346 setcont(top
, ne
? lj_cont_condf
: lj_cont_condt
);
347 copyTV(L
, top
+1, mo
);
348 it
= ~(uint32_t)o1
->gch
.gct
;
349 setgcV(L
, top
+2, o1
, it
);
350 setgcV(L
, top
+3, o2
, it
);
351 return top
+2; /* Trigger metamethod call. */
353 return (TValue
*)(intptr_t)ne
;
357 TValue
* LJ_FASTCALL
lj_meta_equal_cd(lua_State
*L
, BCIns ins
)
359 ASMFunction cont
= (bc_op(ins
) & 1) ? lj_cont_condf
: lj_cont_condt
;
360 int op
= (int)bc_op(ins
) & ~1;
362 cTValue
*mo
, *o2
, *o1
= &L
->base
[bc_a(ins
)];
364 if (op
== BC_ISEQV
) {
365 o2
= &L
->base
[bc_d(ins
)];
366 if (!tviscdata(o1mm
)) o1mm
= o2
;
367 } else if (op
== BC_ISEQS
) {
368 setstrV(L
, &tv
, gco2str(proto_kgc(curr_proto(L
), ~(ptrdiff_t)bc_d(ins
))));
370 } else if (op
== BC_ISEQN
) {
371 o2
= &mref(curr_proto(L
)->k
, cTValue
)[bc_d(ins
)];
373 lua_assert(op
== BC_ISEQP
);
374 setitype(&tv
, ~bc_d(ins
));
377 mo
= lj_meta_lookup(L
, o1mm
, MM_eq
);
378 if (LJ_LIKELY(!tvisnil(mo
)))
379 return mmcall(L
, cont
, mo
, o1
, o2
);
381 return (TValue
*)(intptr_t)(bc_op(ins
) & 1);
385 /* Helper for ordered comparisons. String compare, __lt/__le metamethods. */
386 TValue
*lj_meta_comp(lua_State
*L
, cTValue
*o1
, cTValue
*o2
, int op
)
388 if (LJ_HASFFI
&& (tviscdata(o1
) || tviscdata(o2
))) {
389 ASMFunction cont
= (op
& 1) ? lj_cont_condf
: lj_cont_condt
;
390 MMS mm
= (op
& 2) ? MM_le
: MM_lt
;
391 cTValue
*mo
= lj_meta_lookup(L
, tviscdata(o1
) ? o1
: o2
, mm
);
392 if (LJ_UNLIKELY(tvisnil(mo
))) goto err
;
393 return mmcall(L
, cont
, mo
, o1
, o2
);
394 } else if (itype(o1
) == itype(o2
)) { /* Never called with two numbers. */
395 if (tvisstr(o1
) && tvisstr(o2
)) {
396 int32_t res
= lj_str_cmp(strV(o1
), strV(o2
));
397 return (TValue
*)(intptr_t)(((op
&2) ? res
<= 0 : res
< 0) ^ (op
&1));
401 ASMFunction cont
= (op
& 1) ? lj_cont_condf
: lj_cont_condt
;
402 MMS mm
= (op
& 2) ? MM_le
: MM_lt
;
403 cTValue
*mo
= lj_meta_lookup(L
, o1
, mm
);
404 cTValue
*mo2
= lj_meta_lookup(L
, o2
, mm
);
405 if (tvisnil(mo
) || !lj_obj_equal(mo
, mo2
)) {
406 if (op
& 2) { /* MM_le not found: retry with MM_lt. */
407 cTValue
*ot
= o1
; o1
= o2
; o2
= ot
; /* Swap operands. */
408 op
^= 3; /* Use LT and flip condition. */
413 return mmcall(L
, cont
, mo
, o1
, o2
);
416 } else if (tvisbool(o1
) && tvisbool(o2
)) {
420 lj_err_comp(L
, o1
, o2
);
425 /* Helper for calls. __call metamethod. */
426 void lj_meta_call(lua_State
*L
, TValue
*func
, TValue
*top
)
428 cTValue
*mo
= lj_meta_lookup(L
, func
, MM_call
);
431 lj_err_optype_call(L
, func
);
432 for (p
= top
; p
> func
; p
--) copyTV(L
, p
, p
-1);
436 /* Helper for FORI. Coercion. */
437 void LJ_FASTCALL
lj_meta_for(lua_State
*L
, TValue
*o
)
439 if (!(tvisnumber(o
) || (tvisstr(o
) && lj_str_tonumber(strV(o
), o
))))
440 lj_err_msg(L
, LJ_ERR_FORINIT
);
441 if (!(tvisnumber(o
+1) || (tvisstr(o
+1) && lj_str_tonumber(strV(o
+1), o
+1))))
442 lj_err_msg(L
, LJ_ERR_FORLIM
);
443 if (!(tvisnumber(o
+2) || (tvisstr(o
+2) && lj_str_tonumber(strV(o
+2), o
+2))))
444 lj_err_msg(L
, LJ_ERR_FORSTEP
);
446 /* Ensure all slots are integers or all slots are numbers. */
450 for (i
= 0; i
<= 2; i
++) {
452 k
[i
] = intV(o
+i
); nint
++;
454 k
[i
] = lj_num2int(numV(o
+i
)); nint
+= ((lua_Number
)k
[i
] == numV(o
+i
));
457 if (nint
== 3) { /* Narrow to integers. */
461 } else if (nint
!= 0) { /* Widen to numbers. */
462 if (tvisint(o
)) setnumV(o
, (lua_Number
)intV(o
));
463 if (tvisint(o
+1)) setnumV(o
+1, (lua_Number
)intV(o
+1));
464 if (tvisint(o
+2)) setnumV(o
+2, (lua_Number
)intV(o
+2));