summaryrefslogtreecommitdiff
path: root/src/lj_state.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lj_state.c255
1 files changed, 255 insertions, 0 deletions
diff --git a/src/lj_state.c b/src/lj_state.c
new file mode 100644
index 00000000..b4bc7a0c
--- /dev/null
+++ b/src/lj_state.c
@@ -0,0 +1,255 @@
1/*
2** State and stack handling.
3** Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h
4**
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
7*/
8
9#define lj_state_c
10#define LUA_CORE
11
12#include "lj_obj.h"
13#include "lj_gc.h"
14#include "lj_err.h"
15#include "lj_str.h"
16#include "lj_tab.h"
17#include "lj_func.h"
18#include "lj_meta.h"
19#include "lj_state.h"
20#include "lj_frame.h"
21#include "lj_trace.h"
22#include "lj_dispatch.h"
23#include "lj_vm.h"
24#include "lj_lex.h"
25#include "lj_alloc.h"
26
27/* -- Stack handling ------------------------------------------------------ */
28
29/* Stack sizes. */
30#define LJ_STACK_MIN LUA_MINSTACK /* Min. stack size. */
31#define LJ_STACK_MAX LUAI_MAXSTACK /* Max. stack size. */
32#define LJ_STACK_START (2*LJ_STACK_MIN) /* Starting stack size. */
33#define LJ_STACK_MAXEX (LJ_STACK_MAX + 1 + LJ_STACK_EXTRA)
34
35/* Explanation of LJ_STACK_EXTRA:
36**
37** Calls to metamethods store their arguments beyond the current top
38** without checking for the stack limit. This avoids stack resizes which
39** would invalidate passed TValue pointers. The stack check is performed
40** later by the call gate. This can safely resize the stack or raise an
41** error. Thus we need some extra slots beyond the current stack limit.
42**
43** Most metamethods need 4 slots above top (cont, mobj, arg1, arg2) plus
44** one extra slot if mobj is not a function. Only lj_meta_tset needs 5
45** slots above top, but then mobj is always a function. So we can get by
46** with 5 extra slots.
47*/
48
49/* Resize stack slots and adjust pointers in state. */
50static void resizestack(lua_State *L, MSize n)
51{
52 TValue *oldst = L->stack;
53 ptrdiff_t delta;
54 MSize realsize = n + 1 + LJ_STACK_EXTRA;
55 GCobj *up;
56 lua_assert((MSize)(L->maxstack-L->stack) == L->stacksize-LJ_STACK_EXTRA-1);
57 lj_mem_reallocvec(L, L->stack, L->stacksize, realsize, TValue);
58 delta = (char *)L->stack - (char *)oldst;
59 L->maxstack = L->stack + n;
60 L->stacksize = realsize;
61 L->base = (TValue *)((char *)L->base + delta);
62 L->top = (TValue *)((char *)L->top + delta);
63 for (up = gcref(L->openupval); up != NULL; up = gcnext(up))
64 gco2uv(up)->v = (TValue *)((char *)gco2uv(up)->v + delta);
65 if (obj2gco(L) == gcref(G(L)->jit_L))
66 setmref(G(L)->jit_base, mref(G(L)->jit_base, char) + delta);
67}
68
69/* Relimit stack after error, in case the limit was overdrawn. */
70void lj_state_relimitstack(lua_State *L)
71{
72 if (L->stacksize > LJ_STACK_MAXEX && L->top - L->stack < LJ_STACK_MAX-1)
73 resizestack(L, LJ_STACK_MAX);
74}
75
76/* Try to shrink the stack (called from GC). */
77void lj_state_shrinkstack(lua_State *L, MSize used)
78{
79 if (L->stacksize > LJ_STACK_MAXEX)
80 return; /* Avoid stack shrinking while handling stack overflow. */
81 if (4*used < L->stacksize &&
82 2*(LJ_STACK_START+LJ_STACK_EXTRA) < L->stacksize &&
83 obj2gco(L) != gcref(G(L)->jit_L)) /* Don't shrink stack of live trace. */
84 resizestack(L, L->stacksize >> 1);
85}
86
87/* Try to grow stack. */
88void lj_state_growstack(lua_State *L, MSize need)
89{
90 if (L->stacksize > LJ_STACK_MAXEX) /* overflow while handling overflow? */
91 lj_err_throw(L, LUA_ERRERR);
92 resizestack(L, L->stacksize + (need > L->stacksize ? need : L->stacksize));
93 if (L->stacksize > LJ_STACK_MAXEX) {
94 if (curr_funcisL(L)) { /* Clear slots of incomplete Lua frame. */
95 TValue *top = curr_topL(L);
96 while (--top >= L->top) setnilV(top);
97 }
98 lj_err_msg(L, LJ_ERR_STKOV); /* ... to allow L->top = curr_topL(L). */
99 }
100}
101
102void lj_state_growstack1(lua_State *L)
103{
104 lj_state_growstack(L, 1);
105}
106
107/* Allocate basic stack for new state. */
108static void stack_init(lua_State *L1, lua_State *L)
109{
110 L1->stack = lj_mem_newvec(L, LJ_STACK_START + LJ_STACK_EXTRA, TValue);
111 L1->stacksize = LJ_STACK_START + LJ_STACK_EXTRA;
112 L1->top = L1->stack;
113 L1->maxstack = L1->stack+(L1->stacksize - LJ_STACK_EXTRA)-1;
114 setthreadV(L1, L1->top, L1); /* needed for curr_funcisL() on empty stack */
115 setnilV(L1->top); /* but clear its type */
116 L1->base = ++L1->top;
117}
118
119/* -- State handling ------------------------------------------------------ */
120
121/* Open parts that may cause memory-allocation errors. */
122static TValue *cpluaopen(lua_State *L, lua_CFunction dummy, void *ud)
123{
124 global_State *g = G(L);
125 UNUSED(dummy);
126 UNUSED(ud);
127 stack_init(L, L);
128 /* NOBARRIER: State initialization, all objects are white. */
129 setgcref(L->env, obj2gco(lj_tab_new(L, 0, LJ_MIN_GLOBAL)));
130 settabV(L, registry(L), lj_tab_new(L, 0, LJ_MIN_REGISTRY));
131 lj_str_resize(L, LJ_MIN_STRTAB-1);
132 lj_meta_init(L);
133 lj_lex_init(L);
134 fixstring(lj_err_str(L, LJ_ERR_ERRMEM)); /* Preallocate memory error msg. */
135 g->gc.threshold = 4*g->gc.total;
136 return NULL;
137}
138
139static void close_state(lua_State *L)
140{
141 global_State *g = G(L);
142#ifndef LUAJIT_USE_SYSMALLOC
143 if (g->allocf == lj_alloc_f) {
144 lj_alloc_destroy(g->allocd);
145 } else
146#endif
147 {
148 lj_func_closeuv(L, L->stack);
149 lj_gc_freeall(g);
150 lua_assert(gcref(g->gc.root) == obj2gco(L));
151 lua_assert(g->strnum == 0);
152 lj_trace_freestate(g);
153 lj_mem_freevec(g, g->strhash, g->strmask+1, GCstr *);
154 lj_str_freebuf(g, &g->tmpbuf);
155 lj_mem_freevec(g, L->stack, L->stacksize, TValue);
156 lua_assert(g->gc.total == sizeof(GG_State));
157 g->allocf(g->allocd, G2GG(g), sizeof(GG_State), 0);
158 }
159}
160
161LUA_API lua_State *lua_newstate(lua_Alloc f, void *ud)
162{
163 GG_State *GG = cast(GG_State *, f(ud, NULL, 0, sizeof(GG_State)));
164 lua_State *L = &GG->L;
165 global_State *g = &GG->g;
166 if (GG == NULL) return NULL;
167 memset(GG, 0, sizeof(GG_State));
168 L->gct = ~LJ_TTHREAD;
169 L->marked = LJ_GC_WHITE0 | LJ_GC_FIXED | LJ_GC_SFIXED; /* Prevent free. */
170 L->dummy_ffid = FF_C;
171 setmref(L->glref, g);
172 g->gc.currentwhite = LJ_GC_WHITE0 | LJ_GC_FIXED;
173 g->allocf = f;
174 g->allocd = ud;
175 setgcref(g->mainthref, obj2gco(L));
176 setgcref(g->uvhead.prev, obj2gco(&g->uvhead));
177 setgcref(g->uvhead.next, obj2gco(&g->uvhead));
178 g->strmask = ~(MSize)0;
179 setnilV(registry(L));
180 setnilV(&g->nilnode.val);
181 setnilV(&g->nilnode.key);
182 lj_str_initbuf(L, &g->tmpbuf);
183 g->gc.state = GCSpause;
184 setgcref(g->gc.root, obj2gco(L));
185 g->gc.sweep = &g->gc.root;
186 g->gc.total = sizeof(GG_State);
187 g->gc.pause = LUAI_GCPAUSE;
188 g->gc.stepmul = LUAI_GCMUL;
189 lj_dispatch_init((GG_State *)L);
190 L->status = LUA_ERRERR+1; /* Avoid touching the stack upon memory error. */
191 if (lj_vm_cpcall(L, cpluaopen, NULL, NULL) != 0) {
192 /* Memory allocation error: free partial state. */
193 close_state(L);
194 return NULL;
195 }
196 L->status = 0;
197 return L;
198}
199
200static TValue *cpfinalize(lua_State *L, lua_CFunction dummy, void *ud)
201{
202 UNUSED(dummy);
203 UNUSED(ud);
204 lj_gc_finalizeudata(L);
205 /* Frame pop omitted. */
206 return NULL;
207}
208
209LUA_API void lua_close(lua_State *L)
210{
211 global_State *g = G(L);
212 L = mainthread(g); /* Only the main thread can be closed. */
213 lj_func_closeuv(L, L->stack);
214 lj_gc_separateudata(g, 1); /* Separate udata which have GC metamethods. */
215#if LJ_HASJIT
216 G2J(g)->flags &= ~JIT_F_ON;
217 G2J(g)->state = LJ_TRACE_IDLE;
218 lj_dispatch_update(g);
219#endif
220 do {
221 hook_enter(g);
222 L->status = 0;
223 L->cframe = NULL;
224 L->base = L->top = L->stack + 1;
225 } while (lj_vm_cpcall(L, cpfinalize, NULL, NULL) != 0);
226 close_state(L);
227}
228
229lua_State *lj_state_new(lua_State *L)
230{
231 lua_State *L1 = lj_mem_newobj(L, lua_State);
232 L1->gct = ~LJ_TTHREAD;
233 L1->dummy_ffid = FF_C;
234 L1->status = 0;
235 L1->stacksize = 0;
236 L1->stack = NULL;
237 L1->cframe = NULL;
238 /* NOBARRIER: The lua_State is new (marked white). */
239 setgcrefnull(L1->openupval);
240 setmrefr(L1->glref, L->glref);
241 setgcrefr(L1->env, L->env);
242 stack_init(L1, L); /* init stack */
243 lua_assert(iswhite(obj2gco(L1)));
244 return L1;
245}
246
247void LJ_FASTCALL lj_state_free(global_State *g, lua_State *L)
248{
249 lua_assert(L != mainthread(g));
250 lj_func_closeuv(L, L->stack);
251 lua_assert(gcref(L->openupval) == NULL);
252 lj_mem_freevec(g, L->stack, L->stacksize, TValue);
253 lj_mem_freet(g, L);
254}
255