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; |
