Coverage Report

Created: 2026-02-26 07:19

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