Coverage Report

Created: 2026-01-25 07:04

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
147k
#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
43.0k
#define luai_userstateopen(L)   ((void)L)
41
#endif
42
43
#if !defined(luai_userstateclose)
44
43.0k
#define luai_userstateclose(L)    ((void)L)
45
#endif
46
47
#if !defined(luai_userstatethread)
48
147k
#define luai_userstatethread(L,L1)  ((void)L)
49
#endif
50
51
#if !defined(luai_userstatefree)
52
147k
#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
2.62M
void luaE_setdebt (global_State *g, l_mem debt) {
62
2.62M
  l_mem tb = gettotalbytes(g);
63
2.62M
  lua_assert(tb > 0);
64
2.62M
  if (debt > MAX_LMEM - tb)
65
0
    debt = MAX_LMEM - tb;  /* will make GCtotalbytes == MAX_LMEM */
66
2.62M
  g->GCtotalbytes = tb + debt;
67
2.62M
  g->GCdebt = debt;
68
2.62M
}
69
70
71
13.3M
CallInfo *luaE_extendCI (lua_State *L, int err) {
72
13.3M
  CallInfo *ci;
73
13.3M
  ci = luaM_reallocvector(L, NULL, 0, 1, CallInfo);
74
13.3M
  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.3M
  ci->next = L->ci->next;
80
13.3M
  ci->previous = L->ci;
81
13.3M
  L->ci->next = ci;
82
13.3M
  if (ci->next)
83
301k
    ci->next->previous = ci;
84
13.3M
  ci->u.l.trap = 0;
85
13.3M
  L->nci++;
86
13.3M
  return ci;
87
13.3M
}
88
89
90
/*
91
** free all CallInfo structures not in use by a thread
92
*/
93
190k
static void freeCI (lua_State *L) {
94
190k
  CallInfo *ci = L->ci;
95
190k
  CallInfo *next = ci->next;
96
190k
  ci->next = NULL;
97
4.20M
  while ((ci = next) != NULL) {
98
4.01M
    next = ci->next;
99
4.01M
    luaM_free(L, ci);
100
4.01M
    L->nci--;
101
4.01M
  }
102
190k
}
103
104
105
/*
106
** free half of the CallInfo structures not in use by a thread,
107
** keeping the first one.
108
*/
109
23.9M
void luaE_shrinkCI (lua_State *L) {
110
23.9M
  CallInfo *ci = L->ci->next;  /* first free CallInfo */
111
23.9M
  CallInfo *next;
112
23.9M
  if (ci == NULL)
113
10.2M
    return;  /* no extra elements */
114
21.9M
  while ((next = ci->next) != NULL) {  /* two extra elements? */
115
9.30M
    CallInfo *next2 = next->next;  /* next's next */
116
9.30M
    ci->next = next2;  /* remove next from the list */
117
9.30M
    L->nci--;
118
9.30M
    luaM_free(L, next);  /* free next */
119
9.30M
    if (next2 == NULL)
120
1.02M
      break;  /* no more elements */
121
8.27M
    else {
122
8.27M
      next2->previous = ci;
123
8.27M
      ci = next2;  /* continue */
124
8.27M
    }
125
9.30M
  }
126
13.6M
}
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.67M
void luaE_checkcstack (lua_State *L) {
137
1.67M
  if (getCcalls(L) == LUAI_MAXCCALLS)
138
18.2k
    luaG_runerror(L, "C stack overflow");
139
1.66M
  else if (getCcalls(L) >= (LUAI_MAXCCALLS / 10 * 11))
140
91.4k
    luaD_errerr(L);  /* error while handling stack error */
141
1.67M
}
142
143
144
206M
LUAI_FUNC void luaE_incCstack (lua_State *L) {
145
206M
  L->nCcalls++;
146
206M
  if (l_unlikely(getCcalls(L) >= LUAI_MAXCCALLS))
147
1.38M
    luaE_checkcstack(L);
148
206M
}
149
150
151
251k
static void resetCI (lua_State *L) {
152
251k
  CallInfo *ci = L->ci = &L->base_ci;
153
251k
  ci->func.p = L->stack.p;
154
251k
  setnilvalue(s2v(ci->func.p));  /* 'function' entry for basic 'ci' */
155
251k
  ci->top.p = ci->func.p + 1 + LUA_MINSTACK;  /* +1 for 'function' entry */
156
251k
  ci->u.c.k = NULL;
157
251k
  ci->callstatus = CIST_C;
158
251k
  L->status = LUA_OK;
159
251k
  L->errfunc = 0;  /* stack unwind can "throw away" the error function */
160
251k
}
161
162
163
190k
static void stack_init (lua_State *L1, lua_State *L) {
164
190k
  int i;
165
  /* initialize stack array */
166
190k
  L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue);
167
190k
  L1->tbclist.p = L1->stack.p;
168
8.77M
  for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++)
169
8.58M
    setnilvalue(s2v(L1->stack.p + i));  /* erase new stack */
170
190k
  L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE;
171
  /* initialize first ci */
172
190k
  resetCI(L1);
173
190k
  L1->top.p = L1->stack.p + 1;  /* +1 for 'function' entry */
174
190k
}
175
176
177
190k
static void freestack (lua_State *L) {
178
190k
  if (L->stack.p == NULL)
179
0
    return;  /* stack not completely built yet */
180
190k
  L->ci = &L->base_ci;  /* free the entire 'ci' list */
181
190k
  freeCI(L);
182
190k
  lua_assert(L->nci == 0);
183
  /* free stack */
184
190k
  luaM_freearray(L, L->stack.p, cast_sizet(stacksize(L) + EXTRA_STACK));
185
190k
}
186
187
188
/*
189
** Create registry table and its predefined values
190
*/
191
43.0k
static void init_registry (lua_State *L, global_State *g) {
192
  /* create registry */
193
43.0k
  TValue aux;
194
43.0k
  Table *registry = luaH_new(L);
195
43.0k
  sethvalue(L, &g->l_registry, registry);
196
43.0k
  luaH_resize(L, registry, LUA_RIDX_LAST, 0);
197
  /* registry[1] = false */
198
43.0k
  setbfvalue(&aux);
199
43.0k
  luaH_setint(L, registry, 1, &aux);
200
  /* registry[LUA_RIDX_MAINTHREAD] = L */
201
43.0k
  setthvalue(L, &aux, L);
202
43.0k
  luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &aux);
203
  /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */
204
43.0k
  sethvalue(L, &aux, luaH_new(L));
205
43.0k
  luaH_setint(L, registry, LUA_RIDX_GLOBALS, &aux);
206
43.0k
}
207
208
209
/*
210
** open parts of the state that may cause memory-allocation errors.
211
*/
212
43.0k
static void f_luaopen (lua_State *L, void *ud) {
213
43.0k
  global_State *g = G(L);
214
43.0k
  UNUSED(ud);
215
43.0k
  stack_init(L, L);  /* init stack */
216
43.0k
  init_registry(L, g);
217
43.0k
  luaS_init(L);
218
43.0k
  luaT_init(L);
219
43.0k
  luaX_init(L);
220
43.0k
  g->gcstp = 0;  /* allow gc */
221
43.0k
  setnilvalue(&g->nilvalue);  /* now state is complete */
222
43.0k
  luai_userstateopen(L);
223
43.0k
}
224
225
226
/*
227
** preinitialize a thread with consistent values without allocating
228
** any memory (to avoid errors)
229
*/
230
190k
static void preinit_thread (lua_State *L, global_State *g) {
231
190k
  G(L) = g;
232
190k
  L->stack.p = NULL;
233
190k
  L->ci = NULL;
234
190k
  L->nci = 0;
235
190k
  L->twups = L;  /* thread has no upvalues */
236
190k
  L->nCcalls = 0;
237
190k
  L->errorJmp = NULL;
238
190k
  L->hook = NULL;
239
190k
  L->hookmask = 0;
240
190k
  L->basehookcount = 0;
241
190k
  L->allowhook = 1;
242
190k
  resethookcount(L);
243
190k
  L->openupval = NULL;
244
190k
  L->status = LUA_OK;
245
190k
  L->errfunc = 0;
246
190k
  L->oldpc = 0;
247
190k
  L->base_ci.previous = L->base_ci.next = NULL;
248
190k
}
249
250
251
15.7M
lu_mem luaE_threadsize (lua_State *L) {
252
15.7M
  lu_mem sz = cast(lu_mem, sizeof(LX))
253
15.7M
            + cast_uint(L->nci) * sizeof(CallInfo);
254
15.7M
  if (L->stack.p != NULL)
255
15.7M
    sz += cast_uint(stacksize(L) + EXTRA_STACK) * sizeof(StackValue);
256
15.7M
  return sz;
257
15.7M
}
258
259
260
43.0k
static void close_state (lua_State *L) {
261
43.0k
  global_State *g = G(L);
262
43.0k
  if (!completestate(g))  /* closing a partially built state? */
263
0
    luaC_freeallobjects(L);  /* just collect its objects */
264
43.0k
  else {  /* closing a fully built state */
265
43.0k
    resetCI(L);
266
43.0k
    luaD_closeprotected(L, 1, LUA_OK);  /* close all upvalues */
267
43.0k
    L->top.p = L->stack.p + 1;  /* empty the stack to run finalizers */
268
43.0k
    luaC_freeallobjects(L);  /* collect all objects */
269
43.0k
    luai_userstateclose(L);
270
43.0k
  }
271
43.0k
  luaM_freearray(L, G(L)->strt.hash, cast_sizet(G(L)->strt.size));
272
43.0k
  freestack(L);
273
43.0k
  lua_assert(gettotalbytes(g) == sizeof(global_State));
274
43.0k
  (*g->frealloc)(g->ud, g, sizeof(global_State), 0);  /* free main block */
275
43.0k
}
276
277
278
147k
LUA_API lua_State *lua_newthread (lua_State *L) {
279
147k
  global_State *g = G(L);
280
147k
  GCObject *o;
281
147k
  lua_State *L1;
282
147k
  lua_lock(L);
283
147k
  luaC_checkGC(L);
284
  /* create new thread */
285
147k
  o = luaC_newobjdt(L, LUA_TTHREAD, sizeof(LX), offsetof(LX, l));
286
147k
  L1 = gco2th(o);
287
  /* anchor it on L stack */
288
147k
  setthvalue2s(L, L->top.p, L1);
289
147k
  api_incr_top(L);
290
147k
  preinit_thread(L1, g);
291
147k
  L1->hookmask = L->hookmask;
292
147k
  L1->basehookcount = L->basehookcount;
293
147k
  L1->hook = L->hook;
294
147k
  resethookcount(L1);
295
  /* initialize L1 extra space */
296
147k
  memcpy(lua_getextraspace(L1), lua_getextraspace(mainthread(g)),
297
147k
         LUA_EXTRASPACE);
298
147k
  luai_userstatethread(L, L1);
299
147k
  stack_init(L1, L);  /* init stack */
300
147k
  lua_unlock(L);
301
147k
  return L1;
302
147k
}
303
304
305
147k
void luaE_freethread (lua_State *L, lua_State *L1) {
306
147k
  LX *l = fromstate(L1);
307
147k
  luaF_closeupval(L1, L1->stack.p);  /* close all upvalues */
308
147k
  lua_assert(L1->openupval == NULL);
309
147k
  luai_userstatefree(L, L1);
310
147k
  freestack(L1);
311
147k
  luaM_free(L, l);
312
147k
}
313
314
315
18.0k
TStatus luaE_resetthread (lua_State *L, TStatus status) {
316
18.0k
  resetCI(L);
317
18.0k
  if (status == LUA_YIELD)
318
0
    status = LUA_OK;
319
18.0k
  status = luaD_closeprotected(L, 1, status);
320
18.0k
  if (status != LUA_OK)  /* errors? */
321
18.0k
    luaD_seterrorobj(L, status, L->stack.p + 1);
322
0
  else
323
0
    L->top.p = L->stack.p + 1;
324
18.0k
  luaD_reallocstack(L, cast_int(L->ci->top.p - L->stack.p), 0);
325
18.0k
  return status;
326
18.0k
}
327
328
329
18.0k
LUA_API int lua_closethread (lua_State *L, lua_State *from) {
330
18.0k
  TStatus status;
331
18.0k
  lua_lock(L);
332
18.0k
  L->nCcalls = (from) ? getCcalls(from) : 0;
333
18.0k
  status = luaE_resetthread(L, L->status);
334
18.0k
  if (L == from)  /* closing itself? */
335
0
    luaD_throwbaselevel(L, status);
336
18.0k
  lua_unlock(L);
337
18.0k
  return APIstatus(status);
338
18.0k
}
339
340
341
43.0k
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) {
342
43.0k
  int i;
343
43.0k
  lua_State *L;
344
43.0k
  global_State *g = cast(global_State*,
345
43.0k
                       (*f)(ud, NULL, LUA_TTHREAD, sizeof(global_State)));
346
43.0k
  if (g == NULL) return NULL;
347
43.0k
  L = &g->mainth.l;
348
43.0k
  L->tt = LUA_VTHREAD;
349
43.0k
  g->currentwhite = bitmask(WHITE0BIT);
350
43.0k
  L->marked = luaC_white(g);
351
43.0k
  preinit_thread(L, g);
352
43.0k
  g->allgc = obj2gco(L);  /* by now, only object is the main thread */
353
43.0k
  L->next = NULL;
354
43.0k
  incnny(L);  /* main thread is always non yieldable */
355
43.0k
  g->frealloc = f;
356
43.0k
  g->ud = ud;
357
43.0k
  g->warnf = NULL;
358
43.0k
  g->ud_warn = NULL;
359
43.0k
  g->seed = seed;
360
43.0k
  g->gcstp = GCSTPGC;  /* no GC while building state */
361
43.0k
  g->strt.size = g->strt.nuse = 0;
362
43.0k
  g->strt.hash = NULL;
363
43.0k
  setnilvalue(&g->l_registry);
364
43.0k
  g->panic = NULL;
365
43.0k
  g->gcstate = GCSpause;
366
43.0k
  g->gckind = KGC_INC;
367
43.0k
  g->gcstopem = 0;
368
43.0k
  g->gcemergency = 0;
369
43.0k
  g->finobj = g->tobefnz = g->fixedgc = NULL;
370
43.0k
  g->firstold1 = g->survival = g->old1 = g->reallyold = NULL;
371
43.0k
  g->finobjsur = g->finobjold1 = g->finobjrold = NULL;
372
43.0k
  g->sweepgc = NULL;
373
43.0k
  g->gray = g->grayagain = NULL;
374
43.0k
  g->weak = g->ephemeron = g->allweak = NULL;
375
43.0k
  g->twups = NULL;
376
43.0k
  g->GCtotalbytes = sizeof(global_State);
377
43.0k
  g->GCmarked = 0;
378
43.0k
  g->GCdebt = 0;
379
43.0k
  setivalue(&g->nilvalue, 0);  /* to signal that state is not yet built */
380
43.0k
  setgcparam(g, PAUSE, LUAI_GCPAUSE);
381
43.0k
  setgcparam(g, STEPMUL, LUAI_GCMUL);
382
43.0k
  setgcparam(g, STEPSIZE, LUAI_GCSTEPSIZE);
383
43.0k
  setgcparam(g, MINORMUL, LUAI_GENMINORMUL);
384
43.0k
  setgcparam(g, MINORMAJOR, LUAI_MINORMAJOR);
385
43.0k
  setgcparam(g, MAJORMINOR, LUAI_MAJORMINOR);
386
430k
  for (i=0; i < LUA_NUMTYPES; i++) g->mt[i] = NULL;
387
43.0k
  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
43.0k
  return L;
393
43.0k
}
394
395
396
43.0k
LUA_API void lua_close (lua_State *L) {
397
43.0k
  lua_lock(L);
398
43.0k
  L = mainthread(G(L));  /* only the main thread can be closed */
399
43.0k
  close_state(L);
400
43.0k
}
401
402
403
58.9k
void luaE_warning (lua_State *L, const char *msg, int tocont) {
404
58.9k
  lua_WarnFunction wf = G(L)->warnf;
405
58.9k
  if (wf != NULL)
406
58.9k
    wf(G(L)->ud_warn, msg, tocont);
407
58.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