diff options
Diffstat (limited to 'src/lj_meta.c')
-rw-r--r-- | src/lj_meta.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/src/lj_meta.c b/src/lj_meta.c index cd6fa8d3..58c6c73a 100644 --- a/src/lj_meta.c +++ b/src/lj_meta.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "lj_str.h" | 15 | #include "lj_str.h" |
16 | #include "lj_tab.h" | 16 | #include "lj_tab.h" |
17 | #include "lj_meta.h" | 17 | #include "lj_meta.h" |
18 | #include "lj_frame.h" | ||
18 | #include "lj_bc.h" | 19 | #include "lj_bc.h" |
19 | #include "lj_vm.h" | 20 | #include "lj_vm.h" |
20 | 21 | ||
@@ -68,6 +69,29 @@ cTValue *lj_meta_lookup(lua_State *L, cTValue *o, MMS mm) | |||
68 | return niltv(L); | 69 | return niltv(L); |
69 | } | 70 | } |
70 | 71 | ||
72 | /* Tailcall from C function. */ | ||
73 | int lj_meta_tailcall(lua_State *L, cTValue *tv) | ||
74 | { | ||
75 | TValue *base = L->base; | ||
76 | TValue *top = L->top; | ||
77 | const BCIns *pc = frame_pc(base-1); /* Preserve old PC from frame. */ | ||
78 | copyTV(L, base-1, tv); /* Replace frame with new object. */ | ||
79 | top->u64 = 0; | ||
80 | setframe_pc(top, pc); | ||
81 | setframe_gc(top+1, obj2gco(L)); /* Dummy frame object. */ | ||
82 | setframe_ftsz(top+1, (int)((char *)(top+2) - (char *)base) + FRAME_CONT); | ||
83 | L->base = L->top = top+2; | ||
84 | /* | ||
85 | ** before: [old_mo|PC] [... ...] | ||
86 | ** ^base ^top | ||
87 | ** after: [new_mo|itype] [... ...] [NULL|PC] [dummy|delta] | ||
88 | ** ^base/top | ||
89 | ** tailcall: [new_mo|PC] [... ...] | ||
90 | ** ^base ^top | ||
91 | */ | ||
92 | return 0; | ||
93 | } | ||
94 | |||
71 | /* Setup call to metamethod to be run by Assembler VM. */ | 95 | /* Setup call to metamethod to be run by Assembler VM. */ |
72 | static TValue *mmcall(lua_State *L, ASMFunction cont, cTValue *mo, | 96 | static TValue *mmcall(lua_State *L, ASMFunction cont, cTValue *mo, |
73 | cTValue *a, cTValue *b) | 97 | cTValue *a, cTValue *b) |