aboutsummaryrefslogtreecommitdiff
path: root/src/lj_meta.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_meta.c')
-rw-r--r--src/lj_meta.c134
1 files changed, 75 insertions, 59 deletions
diff --git a/src/lj_meta.c b/src/lj_meta.c
index 1d4d2234..5324c666 100644
--- a/src/lj_meta.c
+++ b/src/lj_meta.c
@@ -12,6 +12,7 @@
12#include "lj_obj.h" 12#include "lj_obj.h"
13#include "lj_gc.h" 13#include "lj_gc.h"
14#include "lj_err.h" 14#include "lj_err.h"
15#include "lj_buf.h"
15#include "lj_str.h" 16#include "lj_str.h"
16#include "lj_tab.h" 17#include "lj_tab.h"
17#include "lj_meta.h" 18#include "lj_meta.h"
@@ -19,6 +20,8 @@
19#include "lj_bc.h" 20#include "lj_bc.h"
20#include "lj_vm.h" 21#include "lj_vm.h"
21#include "lj_strscan.h" 22#include "lj_strscan.h"
23#include "lj_strfmt.h"
24#include "lj_lib.h"
22 25
23/* -- Metamethod handling ------------------------------------------------- */ 26/* -- Metamethod handling ------------------------------------------------- */
24 27
@@ -44,7 +47,7 @@ void lj_meta_init(lua_State *L)
44cTValue *lj_meta_cache(GCtab *mt, MMS mm, GCstr *name) 47cTValue *lj_meta_cache(GCtab *mt, MMS mm, GCstr *name)
45{ 48{
46 cTValue *mo = lj_tab_getstr(mt, name); 49 cTValue *mo = lj_tab_getstr(mt, name);
47 lua_assert(mm <= MM_FAST); 50 lj_assertX(mm <= MM_FAST, "bad metamethod %d", mm);
48 if (!mo || tvisnil(mo)) { /* No metamethod? */ 51 if (!mo || tvisnil(mo)) { /* No metamethod? */
49 mt->nomm |= (uint8_t)(1u<<mm); /* Set negative cache flag. */ 52 mt->nomm |= (uint8_t)(1u<<mm); /* Set negative cache flag. */
50 return NULL; 53 return NULL;
@@ -77,12 +80,16 @@ int lj_meta_tailcall(lua_State *L, cTValue *tv)
77 TValue *base = L->base; 80 TValue *base = L->base;
78 TValue *top = L->top; 81 TValue *top = L->top;
79 const BCIns *pc = frame_pc(base-1); /* Preserve old PC from frame. */ 82 const BCIns *pc = frame_pc(base-1); /* Preserve old PC from frame. */
80 copyTV(L, base-1, tv); /* Replace frame with new object. */ 83 copyTV(L, base-1-LJ_FR2, tv); /* Replace frame with new object. */
81 top->u32.lo = LJ_CONT_TAILCALL; 84 if (LJ_FR2)
82 setframe_pc(top, pc); 85 (top++)->u64 = LJ_CONT_TAILCALL;
83 setframe_gc(top+1, obj2gco(L)); /* Dummy frame object. */ 86 else
84 setframe_ftsz(top+1, (int)((char *)(top+2) - (char *)base) + FRAME_CONT); 87 top->u32.lo = LJ_CONT_TAILCALL;
85 L->base = L->top = top+2; 88 setframe_pc(top++, pc);
89 setframe_gc(top, obj2gco(L), LJ_TTHREAD); /* Dummy frame object. */
90 if (LJ_FR2) top++;
91 setframe_ftsz(top, ((char *)(top+1) - (char *)base) + FRAME_CONT);
92 L->base = L->top = top+1;
86 /* 93 /*
87 ** before: [old_mo|PC] [... ...] 94 ** before: [old_mo|PC] [... ...]
88 ** ^base ^top 95 ** ^base ^top
@@ -113,11 +120,13 @@ static TValue *mmcall(lua_State *L, ASMFunction cont, cTValue *mo,
113 */ 120 */
114 TValue *top = L->top; 121 TValue *top = L->top;
115 if (curr_funcisL(L)) top = curr_topL(L); 122 if (curr_funcisL(L)) top = curr_topL(L);
116 setcont(top, cont); /* Assembler VM stores PC in upper word. */ 123 setcont(top++, cont); /* Assembler VM stores PC in upper word or FR2. */
117 copyTV(L, top+1, mo); /* Store metamethod and two arguments. */ 124 if (LJ_FR2) setnilV(top++);
118 copyTV(L, top+2, a); 125 copyTV(L, top++, mo); /* Store metamethod and two arguments. */
119 copyTV(L, top+3, b); 126 if (LJ_FR2) setnilV(top++);
120 return top+2; /* Return new base. */ 127 copyTV(L, top, a);
128 copyTV(L, top+1, b);
129 return top; /* Return new base. */
121} 130}
122 131
123/* -- C helpers for some instructions, called from assembler VM ----------- */ 132/* -- C helpers for some instructions, called from assembler VM ----------- */
@@ -225,27 +234,14 @@ TValue *lj_meta_arith(lua_State *L, TValue *ra, cTValue *rb, cTValue *rc,
225 } 234 }
226} 235}
227 236
228/* In-place coercion of a number to a string. */
229static 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. */ 237/* Helper for CAT. Coercion, iterative concat, __concat metamethod. */
242TValue *lj_meta_cat(lua_State *L, TValue *top, int left) 238TValue *lj_meta_cat(lua_State *L, TValue *top, int left)
243{ 239{
244 int fromc = 0; 240 int fromc = 0;
245 if (left < 0) { left = -left; fromc = 1; } 241 if (left < 0) { left = -left; fromc = 1; }
246 do { 242 do {
247 int n = 1; 243 if (!(tvisstr(top) || tvisnumber(top) || tvisbuf(top)) ||
248 if (!(tvisstr(top-1) || tvisnumber(top-1)) || !tostring(L, top)) { 244 !(tvisstr(top-1) || tvisnumber(top-1) || tvisbuf(top-1))) {
249 cTValue *mo = lj_meta_lookup(L, top-1, MM_concat); 245 cTValue *mo = lj_meta_lookup(L, top-1, MM_concat);
250 if (tvisnil(mo)) { 246 if (tvisnil(mo)) {
251 mo = lj_meta_lookup(L, top, MM_concat); 247 mo = lj_meta_lookup(L, top, MM_concat);
@@ -266,13 +262,12 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left)
266 ** after mm: [...][CAT stack ...] <--push-- [result] 262 ** after mm: [...][CAT stack ...] <--push-- [result]
267 ** next step: [...][CAT stack .............] 263 ** next step: [...][CAT stack .............]
268 */ 264 */
269 copyTV(L, top+2, top); /* Careful with the order of stack copies! */ 265 copyTV(L, top+2*LJ_FR2+2, top); /* Carefully ordered stack copies! */
270 copyTV(L, top+1, top-1); 266 copyTV(L, top+2*LJ_FR2+1, top-1);
271 copyTV(L, top, mo); 267 copyTV(L, top+LJ_FR2, mo);
272 setcont(top-1, lj_cont_cat); 268 setcont(top-1, lj_cont_cat);
269 if (LJ_FR2) { setnilV(top); setnilV(top+2); top += 2; }
273 return top+1; /* Trigger metamethod call. */ 270 return top+1; /* Trigger metamethod call. */
274 } else if (strV(top)->len == 0) { /* Shortcut. */
275 (void)tostring(L, top-1);
276 } else { 271 } else {
277 /* Pick as many strings as possible from the top and concatenate them: 272 /* Pick as many strings as possible from the top and concatenate them:
278 ** 273 **
@@ -281,27 +276,33 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left)
281 ** concat: [...][CAT stack ...] [result] 276 ** concat: [...][CAT stack ...] [result]
282 ** next step: [...][CAT stack ............] 277 ** next step: [...][CAT stack ............]
283 */ 278 */
284 MSize tlen = strV(top)->len; 279 TValue *e, *o = top;
285 char *buffer; 280 uint64_t tlen = tvisstr(o) ? strV(o)->len :
286 int i; 281 tvisbuf(o) ? sbufxlen(bufV(o)) : STRFMT_MAXBUF_NUM;
287 for (n = 1; n <= left && tostring(L, top-n); n++) { 282 SBuf *sb;
288 MSize len = strV(top-n)->len; 283 do {
289 if (len >= LJ_MAX_STR - tlen) 284 o--; tlen += tvisstr(o) ? strV(o)->len :
290 lj_err_msg(L, LJ_ERR_STROV); 285 tvisbuf(o) ? sbufxlen(bufV(o)) : STRFMT_MAXBUF_NUM;
291 tlen += len; 286 } while (--left > 0 && (tvisstr(o-1) || tvisnumber(o-1)));
292 } 287 if (tlen >= LJ_MAX_STR) lj_err_msg(L, LJ_ERR_STROV);
293 buffer = lj_str_needbuf(L, &G(L)->tmpbuf, tlen); 288 sb = lj_buf_tmp_(L);
294 n--; 289 lj_buf_more(sb, (MSize)tlen);
295 tlen = 0; 290 for (e = top, top = o; o <= e; o++) {
296 for (i = n; i >= 0; i--) { 291 if (tvisstr(o)) {
297 MSize len = strV(top-i)->len; 292 GCstr *s = strV(o);
298 memcpy(buffer + tlen, strVdata(top-i), len); 293 MSize len = s->len;
299 tlen += len; 294 lj_buf_putmem(sb, strdata(s), len);
295 } else if (tvisbuf(o)) {
296 SBufExt *sbx = bufV(o);
297 lj_buf_putmem(sb, sbx->r, sbufxlen(sbx));
298 } else if (tvisint(o)) {
299 lj_strfmt_putint(sb, intV(o));
300 } else {
301 lj_strfmt_putfnum(sb, STRFMT_G14, numV(o));
302 }
300 } 303 }
301 setstrV(L, top-n, lj_str_new(L, buffer, tlen)); 304 setstrV(L, top, lj_buf_str(L, sb));
302 } 305 }
303 left -= n;
304 top -= n;
305 } while (left >= 1); 306 } while (left >= 1);
306 if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) { 307 if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) {
307 if (!fromc) L->top = curr_topL(L); 308 if (!fromc) L->top = curr_topL(L);
@@ -338,12 +339,14 @@ TValue *lj_meta_equal(lua_State *L, GCobj *o1, GCobj *o2, int ne)
338 return (TValue *)(intptr_t)ne; 339 return (TValue *)(intptr_t)ne;
339 } 340 }
340 top = curr_top(L); 341 top = curr_top(L);
341 setcont(top, ne ? lj_cont_condf : lj_cont_condt); 342 setcont(top++, ne ? lj_cont_condf : lj_cont_condt);
342 copyTV(L, top+1, mo); 343 if (LJ_FR2) setnilV(top++);
344 copyTV(L, top++, mo);
345 if (LJ_FR2) setnilV(top++);
343 it = ~(uint32_t)o1->gch.gct; 346 it = ~(uint32_t)o1->gch.gct;
344 setgcV(L, top+2, o1, it); 347 setgcV(L, top, o1, it);
345 setgcV(L, top+3, o2, it); 348 setgcV(L, top+1, o2, it);
346 return top+2; /* Trigger metamethod call. */ 349 return top; /* Trigger metamethod call. */
347 } 350 }
348 return (TValue *)(intptr_t)ne; 351 return (TValue *)(intptr_t)ne;
349} 352}
@@ -365,8 +368,8 @@ TValue * LJ_FASTCALL lj_meta_equal_cd(lua_State *L, BCIns ins)
365 } else if (op == BC_ISEQN) { 368 } else if (op == BC_ISEQN) {
366 o2 = &mref(curr_proto(L)->k, cTValue)[bc_d(ins)]; 369 o2 = &mref(curr_proto(L)->k, cTValue)[bc_d(ins)];
367 } else { 370 } else {
368 lua_assert(op == BC_ISEQP); 371 lj_assertL(op == BC_ISEQP, "bad bytecode op %d", op);
369 setitype(&tv, ~bc_d(ins)); 372 setpriV(&tv, ~bc_d(ins));
370 o2 = &tv; 373 o2 = &tv;
371 } 374 }
372 mo = lj_meta_lookup(L, o1mm, MM_eq); 375 mo = lj_meta_lookup(L, o1mm, MM_eq);
@@ -423,6 +426,18 @@ TValue *lj_meta_comp(lua_State *L, cTValue *o1, cTValue *o2, int op)
423 } 426 }
424} 427}
425 428
429/* Helper for ISTYPE and ISNUM. Implicit coercion or error. */
430void lj_meta_istype(lua_State *L, BCReg ra, BCReg tp)
431{
432 L->top = curr_topL(L);
433 ra++; tp--;
434 lj_assertL(LJ_DUALNUM || tp != ~LJ_TNUMX, "bad type for ISTYPE");
435 if (LJ_DUALNUM && tp == ~LJ_TNUMX) lj_lib_checkint(L, ra);
436 else if (tp == ~LJ_TNUMX+1) lj_lib_checknum(L, ra);
437 else if (tp == ~LJ_TSTR) lj_lib_checkstr(L, ra);
438 else lj_err_argtype(L, ra, lj_obj_itypename[tp]);
439}
440
426/* Helper for calls. __call metamethod. */ 441/* Helper for calls. __call metamethod. */
427void lj_meta_call(lua_State *L, TValue *func, TValue *top) 442void lj_meta_call(lua_State *L, TValue *func, TValue *top)
428{ 443{
@@ -430,7 +445,8 @@ void lj_meta_call(lua_State *L, TValue *func, TValue *top)
430 TValue *p; 445 TValue *p;
431 if (!tvisfunc(mo)) 446 if (!tvisfunc(mo))
432 lj_err_optype_call(L, func); 447 lj_err_optype_call(L, func);
433 for (p = top; p > func; p--) copyTV(L, p, p-1); 448 for (p = top; p > func+2*LJ_FR2; p--) copyTV(L, p, p-1);
449 if (LJ_FR2) copyTV(L, func+2, func);
434 copyTV(L, func, mo); 450 copyTV(L, func, mo);
435} 451}
436 452