diff options
-rw-r--r-- | lstate.c | 105 |
1 files changed, 53 insertions, 52 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 1.124 2003/07/16 20:49:02 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 1.125 2003/07/16 20:51:47 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -34,10 +34,19 @@ union UEXTRASPACE {L_Umaxalign a; LUA_USERSTATE b;}; | |||
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | 36 | ||
37 | /* | ||
38 | ** Main thread combines a thread state and the global state | ||
39 | */ | ||
40 | typedef struct LG { | ||
41 | lua_State l; | ||
42 | global_State g; | ||
43 | } LG; | ||
44 | |||
45 | |||
37 | 46 | ||
38 | 47 | ||
39 | static lua_State *mallocstate (lua_State *L) { | 48 | static lua_State *mallocstate (lua_State *L, size_t size) { |
40 | lu_byte *block = (lu_byte *)luaM_malloc(L, sizeof(lua_State) + EXTRASPACE); | 49 | lu_byte *block = (lu_byte *)luaM_malloc(L, size + EXTRASPACE); |
41 | if (block == NULL) return NULL; | 50 | if (block == NULL) return NULL; |
42 | else { | 51 | else { |
43 | block += EXTRASPACE; | 52 | block += EXTRASPACE; |
@@ -46,9 +55,9 @@ static lua_State *mallocstate (lua_State *L) { | |||
46 | } | 55 | } |
47 | 56 | ||
48 | 57 | ||
49 | static void freestate (lua_State *L, lua_State *L1) { | 58 | static void freestate (lua_State *L, lua_State *L1, size_t size) { |
50 | luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE, | 59 | luaM_free(L, cast(lu_byte *, L1) - EXTRASPACE, |
51 | sizeof(lua_State) + EXTRASPACE); | 60 | size + EXTRASPACE); |
52 | } | 61 | } |
53 | 62 | ||
54 | 63 | ||
@@ -77,27 +86,7 @@ static void freestack (lua_State *L, lua_State *L1) { | |||
77 | ** open parts that may cause memory-allocation errors | 86 | ** open parts that may cause memory-allocation errors |
78 | */ | 87 | */ |
79 | static void f_luaopen (lua_State *L, void *ud) { | 88 | static void f_luaopen (lua_State *L, void *ud) { |
80 | /* create a new global state */ | ||
81 | global_State *g = luaM_new(NULL, global_State); | ||
82 | UNUSED(ud); | 89 | UNUSED(ud); |
83 | if (g == NULL) luaD_throw(L, LUA_ERRMEM); | ||
84 | L->l_G = g; | ||
85 | g->mainthread = L; | ||
86 | g->GCthreshold = 0; /* mark it as unfinished state */ | ||
87 | g->strt.size = 0; | ||
88 | g->strt.nuse = 0; | ||
89 | g->strt.hash = NULL; | ||
90 | setnilvalue(defaultmeta(L)); | ||
91 | setnilvalue(registry(L)); | ||
92 | luaZ_initbuffer(L, &g->buff); | ||
93 | g->panic = NULL; | ||
94 | g->rootgc = NULL; | ||
95 | g->rootudata = NULL; | ||
96 | g->tmudata = NULL; | ||
97 | setnilvalue(gkey(g->dummynode)); | ||
98 | setnilvalue(gval(g->dummynode)); | ||
99 | g->dummynode->next = NULL; | ||
100 | g->nblocks = sizeof(lua_State) + sizeof(global_State); | ||
101 | stack_init(L, L); /* init stack */ | 90 | stack_init(L, L); /* init stack */ |
102 | /* create default meta table with a dummy table, and then close the loop */ | 91 | /* create default meta table with a dummy table, and then close the loop */ |
103 | defaultmeta(L)->tt = LUA_TTABLE; | 92 | defaultmeta(L)->tt = LUA_TTABLE; |
@@ -109,7 +98,7 @@ static void f_luaopen (lua_State *L, void *ud) { | |||
109 | luaT_init(L); | 98 | luaT_init(L); |
110 | luaX_init(L); | 99 | luaX_init(L); |
111 | luaS_fix(luaS_newliteral(L, MEMERRMSG)); | 100 | luaS_fix(luaS_newliteral(L, MEMERRMSG)); |
112 | g->GCthreshold = 4*G(L)->nblocks; | 101 | G(L)->GCthreshold = 4*G(L)->nblocks; |
113 | } | 102 | } |
114 | 103 | ||
115 | 104 | ||
@@ -134,24 +123,19 @@ static void preinit_state (lua_State *L) { | |||
134 | 123 | ||
135 | static void close_state (lua_State *L) { | 124 | static void close_state (lua_State *L) { |
136 | luaF_close(L, L->stack); /* close all upvalues for this thread */ | 125 | luaF_close(L, L->stack); /* close all upvalues for this thread */ |
137 | if (G(L)) { /* close global state */ | 126 | luaC_sweep(L, 1); /* collect all elements */ |
138 | luaC_sweep(L, 1); /* collect all elements */ | 127 | lua_assert(G(L)->rootgc == NULL); |
139 | lua_assert(G(L)->rootgc == NULL); | 128 | lua_assert(G(L)->rootudata == NULL); |
140 | lua_assert(G(L)->rootudata == NULL); | 129 | luaS_freeall(L); |
141 | luaS_freeall(L); | 130 | luaZ_freebuffer(L, &G(L)->buff); |
142 | luaZ_freebuffer(L, &G(L)->buff); | ||
143 | } | ||
144 | freestack(L, L); | 131 | freestack(L, L); |
145 | if (G(L)) { | 132 | lua_assert(G(L)->nblocks == sizeof(LG)); |
146 | lua_assert(G(L)->nblocks == sizeof(lua_State) + sizeof(global_State)); | 133 | freestate(NULL, L, sizeof(LG)); |
147 | luaM_freelem(NULL, G(L)); | ||
148 | } | ||
149 | freestate(NULL, L); | ||
150 | } | 134 | } |
151 | 135 | ||
152 | 136 | ||
153 | lua_State *luaE_newthread (lua_State *L) { | 137 | lua_State *luaE_newthread (lua_State *L) { |
154 | lua_State *L1 = mallocstate(L); | 138 | lua_State *L1 = mallocstate(L, sizeof(lua_State)); |
155 | luaC_link(L, valtogco(L1), LUA_TTHREAD); | 139 | luaC_link(L, valtogco(L1), LUA_TTHREAD); |
156 | preinit_state(L1); | 140 | preinit_state(L1); |
157 | L1->l_G = L->l_G; | 141 | L1->l_G = L->l_G; |
@@ -165,23 +149,40 @@ void luaE_freethread (lua_State *L, lua_State *L1) { | |||
165 | luaF_close(L1, L1->stack); /* close all upvalues for this thread */ | 149 | luaF_close(L1, L1->stack); /* close all upvalues for this thread */ |
166 | lua_assert(L1->openupval == NULL); | 150 | lua_assert(L1->openupval == NULL); |
167 | freestack(L, L1); | 151 | freestack(L, L1); |
168 | freestate(L, L1); | 152 | freestate(L, L1, sizeof(lua_State)); |
169 | } | 153 | } |
170 | 154 | ||
171 | 155 | ||
172 | LUA_API lua_State *lua_open (void) { | 156 | LUA_API lua_State *lua_open (void) { |
173 | lua_State *L = mallocstate(NULL); | 157 | lua_State *L = mallocstate(NULL, sizeof(LG)); |
174 | if (L) { /* allocation OK? */ | 158 | global_State *g; |
175 | L->tt = LUA_TTHREAD; | 159 | if (L == NULL) return NULL; |
176 | L->marked = 0; | 160 | g = &((LG *)L)->g; |
177 | L->next = L->gclist = NULL; | 161 | L->tt = LUA_TTHREAD; |
178 | preinit_state(L); | 162 | L->marked = 0; |
179 | L->l_G = NULL; | 163 | L->next = L->gclist = NULL; |
180 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { | 164 | preinit_state(L); |
181 | /* memory allocation error: free partial state */ | 165 | L->l_G = g; |
182 | close_state(L); | 166 | g->mainthread = L; |
183 | L = NULL; | 167 | g->GCthreshold = 0; /* mark it as unfinished state */ |
184 | } | 168 | g->strt.size = 0; |
169 | g->strt.nuse = 0; | ||
170 | g->strt.hash = NULL; | ||
171 | setnilvalue(defaultmeta(L)); | ||
172 | setnilvalue(registry(L)); | ||
173 | luaZ_initbuffer(L, &g->buff); | ||
174 | g->panic = NULL; | ||
175 | g->rootgc = NULL; | ||
176 | g->rootudata = NULL; | ||
177 | g->tmudata = NULL; | ||
178 | setnilvalue(gkey(g->dummynode)); | ||
179 | setnilvalue(gval(g->dummynode)); | ||
180 | g->dummynode->next = NULL; | ||
181 | g->nblocks = sizeof(LG); | ||
182 | if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { | ||
183 | /* memory allocation error: free partial state */ | ||
184 | close_state(L); | ||
185 | L = NULL; | ||
185 | } | 186 | } |
186 | lua_userstateopen(L); | 187 | lua_userstateopen(L); |
187 | return L; | 188 | return L; |