Coverage Report

Created: 2026-04-11 06:45

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/testdir/build/lua-master/source/lstate.c
Line
Count
Source
1
/*
2
** $Id: lstate.c $
3
** Global State
4
** See Copyright Notice in lua.h
5
*/
6
7
#define lstate_c
8
#define LUA_CORE
9
10
#include "lprefix.h"
11
12
13
#include <stddef.h>
14
#include <string.h>
15
16
#include "lua.h"
17
18
#include "lapi.h"
19
#include "ldebug.h"
20
#include "ldo.h"
21
#include "lfunc.h"
22
#include "lgc.h"
23
#include "llex.h"
24
#include "lmem.h"
25
#include "lstate.h"
26
#include "lstring.h"
27
#include "ltable.h"
28
#include "ltm.h"
29
30
31
32
215k
#define fromstate(L)  (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l)))
33
34
35
/*
36
** these macros allow user-specific actions when a thread is
37
** created/deleted
38
*/
39
#if !defined(luai_userstateopen)
40
44.6k
#define luai_userstateopen(L)   ((void)L)
41
#endif
42
43
#if !defined(luai_userstateclose)
44
44.6k
#define luai_userstateclose(L)    ((void)L)
45
#endif
46
47
#if !defined(luai_userstatethread)
48
215k
#define luai_userstatethread(L,L1)  ((void)L)
49
#endif
50
51
#if !defined(luai_userstatefree)
52
215k
#define luai_userstatefree(L,L1)  ((void)L)
53
#endif
54
55
56
/*
57
** set GCdebt to a new value keeping the real number of allocated
58
** objects (GCtotalobjs - GCdebt) invariant and avoiding overflows in
59
** 'GCtotalobjs'.
60
*/
61
3.02M
void luaE_setdebt (global_State *g, l_mem debt) {
62
3.02M
  l_mem tb = gettotalbytes(g);
63
3.02M
  lua_assert(tb > 0);
64
3.02M
  if (debt > MAX_LMEM - tb)
65
0
    debt = MAX_LMEM - tb;  /* will make GCtotalbytes == MAX_LMEM */
66
3.02M
  g->GCtotalbytes = tb + debt;
67
3.02M
  g->GCdebt = debt;
68
3.02M
}
69
70
71
13.7M
CallInfo *luaE_extendCI (lua_State *L, int err) {
72
13.7M
  CallInfo *ci;
73
13.7M
  ci = luaM_reallocvector(L, NULL, 0, 1, CallInfo);
74
13.7M
  if (l_unlikely(ci == NULL)) {  /* allocation failed? */
75
0
    if (err)
76
0
      luaM_error(L);  /* raise the error */
77
0
    return NULL;  /* else only report it */
78
0
  }
79
13.7M
  ci->next = L->ci->next;
80
13.7M
  ci->previous = L->ci;
81
13.7M
  L->ci->next = ci;
82
13.7M
  if (ci->next)
83
357k
    ci->next->previous = ci;
84
13.7M
  ci->u.l.trap = 0;
85
13.7M
  L->nci++;
86
13.7M
  return ci;
87
13.7M
}
88
89
90
/*
91
** free all CallInfo structures not in use by a thread
92
*/
93
260k
static void freeCI (lua_State *L) {
94
260k
  CallInfo *ci = L->ci;
95
260k
  CallInfo *next = ci->next;
96
260k
  ci->next = NULL;
97
5.01M
  while ((ci = next) != NULL) {
98
4.75M
    next = ci->next;
99
4.75M
    luaM_free(L, ci);
100
4.75M
    L->nci--;
101
4.75M
  }
102
260k
}
103
104
105
/*
106
** free half of the CallInfo structures not in use by a thread,
107
** keeping the first one.
108
*/
109
28.2M
void luaE_shrinkCI (lua_State *L) {
110
28.2M
  CallInfo *ci = L->ci->next;  /* first free CallInfo */
111
28.2M
  CallInfo *next;
112
28.2M
  if (ci == NULL)
113
11.2M
    return;  /* no extra elements */
114
24.7M
  while ((next = ci->next) != NULL) {  /* two extra elements? */
115
8.98M
    CallInfo *next2 = next->next;  /* next's next */
116
8.98M
    ci->next = next2;  /* remove next from the list */
117
8.98M
    L->nci--;
118
8.98M
    luaM_free(L, next);  /* free next */
119
8.98M
    if (next2 == NULL)
120
1.24M
      break;  /* no more elements */
121
7.74M
    else {
122
7.74M
      next2->previous = ci;
123
7.74M
      ci = next2;  /* continue */
124
7.74M
    }
125
8.98M
  }
126
17.0M
}
127
128
129
/*
130
** Called when 'getCcalls(L)' larger or equal to LUAI_MAXCCALLS.
131
** If equal, raises an overflow error. If value is larger than
132
** LUAI_MAXCCALLS (which means it is handling an overflow) but
133
** not much larger, does not report an error (to allow overflow
134
** handling to work).
135
*/
136
1.23M
void luaE_checkcstack (lua_State *L) {
137
1.23M
  if (getCcalls(L) == LUAI_MAXCCALLS)
138
19.8k
    luaG_runerror(L, "C stack overflow");
139
1.21M
  else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11))
140
71.8k
    luaD_errerr(L);  /* error while handling stack error */
141
1.23M
}
142
143
144
221M
LUAI_FUNC void luaE_incCstack (lua_State *L) {
145
221M
  L->nCcalls++;
146
221M
  if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
147
944k
    luaE_checkcstack(L);
148
221M
}
149
150
151
343k
static void resetCI (lua_State *L) {
152
343k
  CallInfo *ci = L->ci = &L->base_ci;
153
343k
  ci->func.p = L->stack.p;
154
343k
  setnilvalue(s2v(ci->func.p));  /* 'function' entry for basic 'ci' */
155
343k
  ci->top.p = ci->func.p + 1 + LUA_MINSTACK;  /* +1 for 'function' entry */
156
343k
  ci->u.c.k = NULL;
157
343k
  ci->callstatus = CIST_C;
158
343k
  L->status = LUA_OK;
159
343k
  L->errfunc = 0;  /* stack unwind can "throw away" the error function */
160
343k
}
161
162
163
260k
static void stack_init (lua_State *L1, lua_State *L) {
164
260k
  int i;
165
  /* initialize stack array */
166
260k
  L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
167
260k
  L1->tbclist.p = L1->stack.p;
168
11.9M
  for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
169
11.7M
    setnilvalue(s2v(L1->stack.p + i));  /* erase new stack */
170
260k
  L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE;
171
  /* initialize first ci */
172
260k
  resetCI(L1);
173
260k
  L1->top.p = L1->stack.p + 1;  /* +1 for 'function' entry */
174
260k
}
175
176
177
260k
static void freestack (lua_State *L) {
178
260k
  if (L->stack.p == NULL)
179
0
    return;  /* stack not completely built yet */
180
260k
  L->ci = &L->base_ci;  /* free the entire 'ci' list */
181
260k
  freeCI(L);
182
260k
  lua_assert(L->nci == 0);
183
  /* free stack */
184
260k
  luaM_freearray(L, L->stack.p, cast_sizet(stacksize(L) + EXTRA_STACK));
185
260k
}
186
187
188
/*
189
** Create registry table and its predefined values
190
*/
191
44.6k
static void init_registry (lua_State *L, global_State *g) {
192
  /* create registry */
193
44.6k
  TValue aux;
194
44.6k
  Table *registry = luaH_new(L);
195
44.6k
  sethvalue(L, &g->l_registry, registry);
196
44.6k
  luaH_resize(L, registry, LUA_RIDX_LAST, 0);
197
  /* registry[1] = false */
198
44.6k
  setbfvalue(&aux);
199
44.6k
  luaH_setint(L, registry, 1, &aux);
200
  /* registry[LUA_RIDX_MAINTHREAD] = L */
201
44.6k
  setthvalue(L, &aux, L);
202
44.6k
  luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &aux);
203
  /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */
204
44.6k
  sethvalue(L, &aux, luaH_new(L));
205
44.6k
  luaH_setint(L, registry, LUA_RIDX_GLOBALS, &aux);
206
44.6k
}
207
208
209
/*
210
** open parts of the state that may cause memory-allocation errors.
211
*/
212
44.6k
static void f_luaopen (lua_State *L, void *ud) {
213
44.6k
  global_State *g = G(L);
214
44.6k
  UNUSED(ud);
215
44.6k
  stack_init(L, L);  /* init stack */
216
44.6k
  init_registry(L, g);
217
44.6k
  luaS_init(L);
218
44.6k
  luaT_init(L);
219
44.6k
  luaX_init(L);
220
44.6k
  g->gcstp = 0;  /* allow gc */
221
44.6k
  setnilvalue(&g->nilvalue);  /* now state is complete */
222
44.6k
  luai_userstateopen(L);
223
44.6k
}
224
225
226
/*
227
** preinitialize a thread with consistent values without allocating
228
** any memory (to avoid errors)
229
*/
230
260k
static void preinit_thread (lua_State *L, global_State *g) {
231
260k
  G(L) = g;
232
260k
  L->stack.p = NULL;
233
260k
  L->ci = NULL;
234
260k
  L->nci = 0;
235
260k
  L->twups = L;  /* thread has no upvalues */
236
260k
  L->nCcalls = 0;
237
260k
  L->errorJmp = NULL;
238
260k
  L->hook = NULL;
239
260k
  L->hookmask = 0;
240
260k
  L->basehookcount = 0;
241
260k
  L->allowhook = 1;
242
260k
  resethookcount(L);
243
260k
  L->openupval = NULL;
244
260k
  L->status = LUA_OK;
245
260k
  L->errfunc = 0;
246
260k
  L->oldpc = 0;
247
260k
  L->base_ci.previous = L->base_ci.next = NULL;
248
260k
}
249
250
251
19.9M
lu_mem luaE_threadsize (lua_State *L) {
252
19.9M
  lu_mem sz = cast(lu_mem, sizeof(LX))
253
19.9M
            + cast_uint(L->nci) * sizeof(CallInfo);
254
19.9M
  if (L->stack.p != NULL)
255
19.9M
    sz += cast_uint(stacksize(L) + EXTRA_STACK) * sizeof(StackValue);
256
19.9M
  return sz;
257
19.9M
}
258
259
260
44.6k
static void close_state (lua_State *L) {
261
44.6k
  global_State *g = G(L);
262
44.6k
  if (!completestate(g))  /* closing a partially built state? */
263
0
    luaC_freeallobjects(L);  /* just collect its objects */
264
44.6k
  else {  /* closing a fully built state */
265
44.6k
    resetCI(L);
266
44.6k
    luaD_closeprotected(L, 1, LUA_OK);  /* close all upvalues */
267
44.6k
    L->top.p = L->stack.p + 1;  /* empty the stack to run finalizers */
268
44.6k
    luaC_freeallobjects(L);  /* collect all objects */
269
44.6k
    luai_userstateclose(L);
270
44.6k
  }
271
44.6k
  luaM_freearray(L, G(L)->strt.hash, cast_sizet(G(L)->strt.size));
272
44.6k
  freestack(L);
273
44.6k
  lua_assert(gettotalbytes(g) == sizeof(global_State));
274
44.6k
  (*g->frealloc)(g->ud, g, sizeof(global_State), 0);  /* free main block */
275
44.6k
}
276
277
278
215k
LUA_API lua_State *lua_newthread (lua_State *L) {
279
215k
  global_State *g = G(L);
280
215k
  GCObject *o;
281
215k
  lua_State *L1;
282
215k
  lua_lock(L);
283
215k
  luaC_checkGC(L);
284
  /* create new thread */
285
215k
  o = luaC_newobjdt(L, LUA_TTHREAD, sizeof(LX), offsetof(LX, l));
286
215k
  L1 = gco2th(o);
287
  /* anchor it on L stack */
288
215k
  setthvalue2s(L, L->top.p, L1);
289
215k
  api_incr_top(L);
290
215k
  preinit_thread(L1, g);
291
215k
  L1->hookmask = L->hookmask;
292
215k
  L1->basehookcount = L->basehookcount;
293
215k
  L1->hook = L->hook;
294
215k
  resethookcount(L1);
295
  /* initialize L1 extra space */
296
215k
  memcpy(lua_getextraspace(L1), lua_getextraspace(mainthread(g)),
297
215k
         LUA_EXTRASPACE);
298
215k
  luai_userstatethread(L, L1);
299
215k
  stack_init(L1, L);  /* init stack */
300
215k
  lua_unlock(L);
301
215k
  return L1;
302
215k
}
303
304
305
215k
void luaE_freethread (lua_State *L, lua_State *L1) {
306
215k
  LX *l = fromstate(L1);
307
215k
  luaF_closeupval(L1, L1->stack.p);  /* close all upvalues */
308
215k
  lua_assert(L1->openupval == NULL);
309
215k
  luai_userstatefree(L, L1);
310
215k
  freestack(L1);
311
215k
  luaM_free(L, l);
312
215k
}
313
314
315
38.0k
TStatus luaE_resetthread (lua_State *L, TStatus status) {
316
38.0k
  resetCI(L);
317
38.0k
  if (status == LUA_YIELD)
318
0
    status = LUA_OK;
319
38.0k
  status = luaD_closeprotected(L, 1, status);
320
38.0k
  if (status != LUA_OK)  /* errors? */
321
38.0k
    luaD_seterrorobj(L, status, L->stack.p + 1);
322
0
  else
323
0
    L->top.p = L->stack.p + 1;
324
38.0k
  luaD_reallocstack(L, cast_int(L->ci->top.p - L->stack.p), 0);
325
38.0k
  return status;
326
38.0k
}
327
328
329
38.0k
LUA_API int lua_closethread (lua_State *L, lua_State *from) {
330
38.0k
  TStatus status;
331
38.0k
  lua_lock(L);
332
38.0k
  L->nCcalls = (from) ? getCcalls(from) : 0;
333
38.0k
  status = luaE_resetthread(L, L->status);
334
38.0k
  if (L == from)  /* closing itself? */
335
0
    luaD_throwbaselevel(L, status);
336
38.0k
  lua_unlock(L);
337
38.0k
  return APIstatus(status);
338
38.0k
}
339
340
341
44.6k
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) {
342
44.6k
  int i;
343
44.6k
  lua_State *L;
344
44.6k
  global_State *g = cast(global_State*,
345
44.6k
                       (*f)(ud, NULL, LUA_TTHREAD, sizeof(global_State)));
346
44.6k
  if (g == NULL) return NULL;
347
44.6k
  L = &g->mainth.l;
348
44.6k
  L->tt = LUA_VTHREAD;
349
44.6k
  g->currentwhite = bitmask(WHITE0BIT);
350
44.6k
  L->marked = luaC_white(g);
351
44.6k
  preinit_thread(L, g);
352
44.6k
  g->allgc = obj2gco(L);  /* by now, only object is the main thread */
353
44.6k
  L->next = NULL;
354
44.6k
  incnny(L);  /* main thread is always non yieldable */
355
44.6k
  g->frealloc = f;
356
44.6k
  g->ud = ud;
357
44.6k
  g->warnf = NULL;
358
44.6k
  g->ud_warn = NULL;
359
44.6k
  g->seed = seed;
360
44.6k
  g->gcstp = GCSTPGC;  /* no GC while building state */
361
44.6k
  g->strt.size = g->strt.nuse = 0;
362
44.6k
  g->strt.hash = NULL;
363
44.6k
  setnilvalue(&g->l_registry);
364
44.6k
  g->panic = NULL;
365
44.6k
  g->gcstate = GCSpause;
366
44.6k
  g->gckind = KGC_INC;
367
44.6k
  g->gcstopem = 0;
368
44.6k
  g->gcemergency = 0;
369
44.6k
  g->finobj = g->tobefnz = g->fixedgc = NULL;
370
44.6k
  g->firstold1 = g->survival = g->old1 = g->reallyold = NULL;
371
44.6k
  g->finobjsur = g->finobjold1 = g->finobjrold = NULL;
372
44.6k
  g->sweepgc = NULL;
373
44.6k
  g->gray = g->grayagain = NULL;
374
44.6k
  g->weak = g->ephemeron = g->allweak = NULL;
375
44.6k
  g->twups = NULL;
376
44.6k
  g->GCtotalbytes = sizeof(global_State);
377
44.6k
  g->GCmarked = 0;
378
44.6k
  g->GCdebt = 0;
379
44.6k
  setivalue(&g->nilvalue, 0);  /* to signal that state is not yet built */
380
44.6k
  setgcparam(g, PAUSE, LUAI_GCPAUSE);
381
44.6k
  setgcparam(g, STEPMUL, LUAI_GCMUL);
382
44.6k
  setgcparam(g, STEPSIZE, LUAI_GCSTEPSIZE);
383
44.6k
  setgcparam(g, MINORMUL, LUAI_GENMINORMUL);
384
44.6k
  setgcparam(g, MINORMAJOR, LUAI_MINORMAJOR);
385
44.6k
  setgcparam(g, MAJORMINOR, LUAI_MAJORMINOR);
386
446k
  for (i=0; i < LUA_NUMTYPES; i++) g->mt[i] = NULL;
387
44.6k
  if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) {
388
    /* memory allocation error: free partial state */
389
0
    close_state(L);
390
0
    L = NULL;
391
0
  }
392
44.6k
  return L;
393
44.6k
}
394
395
396
44.6k
LUA_API void lua_close (lua_State *L) {
397
44.6k
  lua_lock(L);
398
44.6k
  L = mainthread(G(L));  /* only the main thread can be closed */
399
44.6k
  close_state(L);
400
44.6k
}
401
402
403
91.9k
void luaE_warning (lua_State *L, const char *msg, int tocont) {
404
91.9k
  lua_WarnFunction wf = G(L)->warnf;
405
91.9k
  if (wf != NULL)
406
91.9k
    wf(G(L)->ud_warn, msg, tocont);
407
91.9k
}
408
409
410
/*
411
** Generate a warning from an error message
412
*/
413
0
void luaE_warnerror (lua_State *L, const char *where) {
414
0
  TValue *errobj = s2v(L->top.p - 1);  /* error object */
415
0
  const char *msg = (ttisstring(errobj))
416
0
                  ? getstr(tsvalue(errobj))
417
0
                  : "error object is not a string";
418
  /* produce warning "error in %s (%s)" (where, msg) */
419
0
  luaE_warning(L, "error in ", 1);
420
0
  luaE_warning(L, where, 1);
421
0
  luaE_warning(L, " (", 1);
422
0
  luaE_warning(L, msg, 1);
423
0
  luaE_warning(L, ")", 0);
424
0
}
425