comparison third_party/luajit/src/lib_debug.c @ 178:94705b5986b3

[ThirdParty] Added WRK and luajit for load testing.
author MrJuneJune <me@mrjunejune.com>
date Thu, 22 Jan 2026 20:10:30 -0800
parents
children
comparison
equal deleted inserted replaced
177:24fe8ff94056 178:94705b5986b3
1 /*
2 ** Debug library.
3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
4 **
5 ** Major portions taken verbatim or adapted from the Lua interpreter.
6 ** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
7 */
8
9 #define lib_debug_c
10 #define LUA_LIB
11
12 #include "lua.h"
13 #include "lauxlib.h"
14 #include "lualib.h"
15
16 #include "lj_obj.h"
17 #include "lj_gc.h"
18 #include "lj_err.h"
19 #include "lj_debug.h"
20 #include "lj_lib.h"
21
22 /* ------------------------------------------------------------------------ */
23
24 #define LJLIB_MODULE_debug
25
26 LJLIB_CF(debug_getregistry)
27 {
28 copyTV(L, L->top++, registry(L));
29 return 1;
30 }
31
32 LJLIB_CF(debug_getmetatable) LJLIB_REC(.)
33 {
34 lj_lib_checkany(L, 1);
35 if (!lua_getmetatable(L, 1)) {
36 setnilV(L->top-1);
37 }
38 return 1;
39 }
40
41 LJLIB_CF(debug_setmetatable)
42 {
43 lj_lib_checktabornil(L, 2);
44 L->top = L->base+2;
45 lua_setmetatable(L, 1);
46 #if !LJ_52
47 setboolV(L->top-1, 1);
48 #endif
49 return 1;
50 }
51
52 LJLIB_CF(debug_getfenv)
53 {
54 lj_lib_checkany(L, 1);
55 lua_getfenv(L, 1);
56 return 1;
57 }
58
59 LJLIB_CF(debug_setfenv)
60 {
61 lj_lib_checktab(L, 2);
62 L->top = L->base+2;
63 if (!lua_setfenv(L, 1))
64 lj_err_caller(L, LJ_ERR_SETFENV);
65 return 1;
66 }
67
68 /* ------------------------------------------------------------------------ */
69
70 static void settabss(lua_State *L, const char *i, const char *v)
71 {
72 lua_pushstring(L, v);
73 lua_setfield(L, -2, i);
74 }
75
76 static void settabsi(lua_State *L, const char *i, int v)
77 {
78 lua_pushinteger(L, v);
79 lua_setfield(L, -2, i);
80 }
81
82 static void settabsb(lua_State *L, const char *i, int v)
83 {
84 lua_pushboolean(L, v);
85 lua_setfield(L, -2, i);
86 }
87
88 static lua_State *getthread(lua_State *L, int *arg)
89 {
90 if (L->base < L->top && tvisthread(L->base)) {
91 *arg = 1;
92 return threadV(L->base);
93 } else {
94 *arg = 0;
95 return L;
96 }
97 }
98
99 static void treatstackoption(lua_State *L, lua_State *L1, const char *fname)
100 {
101 if (L == L1) {
102 lua_pushvalue(L, -2);
103 lua_remove(L, -3);
104 }
105 else
106 lua_xmove(L1, L, 1);
107 lua_setfield(L, -2, fname);
108 }
109
110 LJLIB_CF(debug_getinfo)
111 {
112 lj_Debug ar;
113 int arg, opt_f = 0, opt_L = 0;
114 lua_State *L1 = getthread(L, &arg);
115 const char *options = luaL_optstring(L, arg+2, "flnSu");
116 if (lua_isnumber(L, arg+1)) {
117 if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), (lua_Debug *)&ar)) {
118 setnilV(L->top-1);
119 return 1;
120 }
121 } else if (L->base+arg < L->top && tvisfunc(L->base+arg)) {
122 options = lua_pushfstring(L, ">%s", options);
123 setfuncV(L1, L1->top++, funcV(L->base+arg));
124 } else {
125 lj_err_arg(L, arg+1, LJ_ERR_NOFUNCL);
126 }
127 if (!lj_debug_getinfo(L1, options, &ar, 1))
128 lj_err_arg(L, arg+2, LJ_ERR_INVOPT);
129 lua_createtable(L, 0, 16); /* Create result table. */
130 for (; *options; options++) {
131 switch (*options) {
132 case 'S':
133 settabss(L, "source", ar.source);
134 settabss(L, "short_src", ar.short_src);
135 settabsi(L, "linedefined", ar.linedefined);
136 settabsi(L, "lastlinedefined", ar.lastlinedefined);
137 settabss(L, "what", ar.what);
138 break;
139 case 'l':
140 settabsi(L, "currentline", ar.currentline);
141 break;
142 case 'u':
143 settabsi(L, "nups", ar.nups);
144 settabsi(L, "nparams", ar.nparams);
145 settabsb(L, "isvararg", ar.isvararg);
146 break;
147 case 'n':
148 settabss(L, "name", ar.name);
149 settabss(L, "namewhat", ar.namewhat);
150 break;
151 case 'f': opt_f = 1; break;
152 case 'L': opt_L = 1; break;
153 default: break;
154 }
155 }
156 if (opt_L) treatstackoption(L, L1, "activelines");
157 if (opt_f) treatstackoption(L, L1, "func");
158 return 1; /* Return result table. */
159 }
160
161 LJLIB_CF(debug_getlocal)
162 {
163 int arg;
164 lua_State *L1 = getthread(L, &arg);
165 lua_Debug ar;
166 const char *name;
167 int slot = lj_lib_checkint(L, arg+2);
168 if (tvisfunc(L->base+arg)) {
169 L->top = L->base+arg+1;
170 lua_pushstring(L, lua_getlocal(L, NULL, slot));
171 return 1;
172 }
173 if (!lua_getstack(L1, lj_lib_checkint(L, arg+1), &ar))
174 lj_err_arg(L, arg+1, LJ_ERR_LVLRNG);
175 name = lua_getlocal(L1, &ar, slot);
176 if (name) {
177 lua_xmove(L1, L, 1);
178 lua_pushstring(L, name);
179 lua_pushvalue(L, -2);
180 return 2;
181 } else {
182 setnilV(L->top-1);
183 return 1;
184 }
185 }
186
187 LJLIB_CF(debug_setlocal)
188 {
189 int arg;
190 lua_State *L1 = getthread(L, &arg);
191 lua_Debug ar;
192 TValue *tv;
193 if (!lua_getstack(L1, lj_lib_checkint(L, arg+1), &ar))
194 lj_err_arg(L, arg+1, LJ_ERR_LVLRNG);
195 tv = lj_lib_checkany(L, arg+3);
196 copyTV(L1, L1->top++, tv);
197 lua_pushstring(L, lua_setlocal(L1, &ar, lj_lib_checkint(L, arg+2)));
198 return 1;
199 }
200
201 static int debug_getupvalue(lua_State *L, int get)
202 {
203 int32_t n = lj_lib_checkint(L, 2);
204 const char *name;
205 lj_lib_checkfunc(L, 1);
206 name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n);
207 if (name) {
208 lua_pushstring(L, name);
209 if (!get) return 1;
210 copyTV(L, L->top, L->top-2);
211 L->top++;
212 return 2;
213 }
214 return 0;
215 }
216
217 LJLIB_CF(debug_getupvalue)
218 {
219 return debug_getupvalue(L, 1);
220 }
221
222 LJLIB_CF(debug_setupvalue)
223 {
224 lj_lib_checkany(L, 3);
225 return debug_getupvalue(L, 0);
226 }
227
228 LJLIB_CF(debug_upvalueid)
229 {
230 GCfunc *fn = lj_lib_checkfunc(L, 1);
231 int32_t n = lj_lib_checkint(L, 2) - 1;
232 if ((uint32_t)n >= fn->l.nupvalues)
233 lj_err_arg(L, 2, LJ_ERR_IDXRNG);
234 lua_pushlightuserdata(L, isluafunc(fn) ? (void *)gcref(fn->l.uvptr[n]) :
235 (void *)&fn->c.upvalue[n]);
236 return 1;
237 }
238
239 LJLIB_CF(debug_upvaluejoin)
240 {
241 GCfunc *fn[2];
242 GCRef *p[2];
243 int i;
244 for (i = 0; i < 2; i++) {
245 int32_t n;
246 fn[i] = lj_lib_checkfunc(L, 2*i+1);
247 if (!isluafunc(fn[i]))
248 lj_err_arg(L, 2*i+1, LJ_ERR_NOLFUNC);
249 n = lj_lib_checkint(L, 2*i+2) - 1;
250 if ((uint32_t)n >= fn[i]->l.nupvalues)
251 lj_err_arg(L, 2*i+2, LJ_ERR_IDXRNG);
252 p[i] = &fn[i]->l.uvptr[n];
253 }
254 setgcrefr(*p[0], *p[1]);
255 lj_gc_objbarrier(L, fn[0], gcref(*p[1]));
256 return 0;
257 }
258
259 #if LJ_52
260 LJLIB_CF(debug_getuservalue)
261 {
262 TValue *o = L->base;
263 if (o < L->top && tvisudata(o))
264 settabV(L, o, tabref(udataV(o)->env));
265 else
266 setnilV(o);
267 L->top = o+1;
268 return 1;
269 }
270
271 LJLIB_CF(debug_setuservalue)
272 {
273 TValue *o = L->base;
274 if (!(o < L->top && tvisudata(o)))
275 lj_err_argt(L, 1, LUA_TUSERDATA);
276 if (!(o+1 < L->top && tvistab(o+1)))
277 lj_err_argt(L, 2, LUA_TTABLE);
278 L->top = o+2;
279 lua_setfenv(L, 1);
280 return 1;
281 }
282 #endif
283
284 /* ------------------------------------------------------------------------ */
285
286 #define KEY_HOOK (U64x(80000000,00000000)|'h')
287
288 static void hookf(lua_State *L, lua_Debug *ar)
289 {
290 static const char *const hooknames[] =
291 {"call", "return", "line", "count", "tail return"};
292 (L->top++)->u64 = KEY_HOOK;
293 lua_rawget(L, LUA_REGISTRYINDEX);
294 if (lua_isfunction(L, -1)) {
295 lua_pushstring(L, hooknames[(int)ar->event]);
296 if (ar->currentline >= 0)
297 lua_pushinteger(L, ar->currentline);
298 else lua_pushnil(L);
299 lua_call(L, 2, 0);
300 }
301 }
302
303 static int makemask(const char *smask, int count)
304 {
305 int mask = 0;
306 if (strchr(smask, 'c')) mask |= LUA_MASKCALL;
307 if (strchr(smask, 'r')) mask |= LUA_MASKRET;
308 if (strchr(smask, 'l')) mask |= LUA_MASKLINE;
309 if (count > 0) mask |= LUA_MASKCOUNT;
310 return mask;
311 }
312
313 static char *unmakemask(int mask, char *smask)
314 {
315 int i = 0;
316 if (mask & LUA_MASKCALL) smask[i++] = 'c';
317 if (mask & LUA_MASKRET) smask[i++] = 'r';
318 if (mask & LUA_MASKLINE) smask[i++] = 'l';
319 smask[i] = '\0';
320 return smask;
321 }
322
323 LJLIB_CF(debug_sethook)
324 {
325 int arg, mask, count;
326 lua_Hook func;
327 (void)getthread(L, &arg);
328 if (lua_isnoneornil(L, arg+1)) {
329 lua_settop(L, arg+1);
330 func = NULL; mask = 0; count = 0; /* turn off hooks */
331 } else {
332 const char *smask = luaL_checkstring(L, arg+2);
333 luaL_checktype(L, arg+1, LUA_TFUNCTION);
334 count = luaL_optint(L, arg+3, 0);
335 func = hookf; mask = makemask(smask, count);
336 }
337 (L->top++)->u64 = KEY_HOOK;
338 lua_pushvalue(L, arg+1);
339 lua_rawset(L, LUA_REGISTRYINDEX);
340 lua_sethook(L, func, mask, count);
341 return 0;
342 }
343
344 LJLIB_CF(debug_gethook)
345 {
346 char buff[5];
347 int mask = lua_gethookmask(L);
348 lua_Hook hook = lua_gethook(L);
349 if (hook != NULL && hook != hookf) { /* external hook? */
350 lua_pushliteral(L, "external hook");
351 } else {
352 (L->top++)->u64 = KEY_HOOK;
353 lua_rawget(L, LUA_REGISTRYINDEX); /* get hook */
354 }
355 lua_pushstring(L, unmakemask(mask, buff));
356 lua_pushinteger(L, lua_gethookcount(L));
357 return 3;
358 }
359
360 /* ------------------------------------------------------------------------ */
361
362 LJLIB_CF(debug_debug)
363 {
364 for (;;) {
365 char buffer[250];
366 fputs("lua_debug> ", stderr);
367 if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
368 strcmp(buffer, "cont\n") == 0)
369 return 0;
370 if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") ||
371 lua_pcall(L, 0, 0, 0)) {
372 const char *s = lua_tostring(L, -1);
373 fputs(s ? s : "(error object is not a string)", stderr);
374 fputs("\n", stderr);
375 }
376 lua_settop(L, 0); /* remove eventual returns */
377 }
378 }
379
380 /* ------------------------------------------------------------------------ */
381
382 #define LEVELS1 12 /* size of the first part of the stack */
383 #define LEVELS2 10 /* size of the second part of the stack */
384
385 LJLIB_CF(debug_traceback)
386 {
387 int arg;
388 lua_State *L1 = getthread(L, &arg);
389 const char *msg = lua_tostring(L, arg+1);
390 if (msg == NULL && L->top > L->base+arg)
391 L->top = L->base+arg+1;
392 else
393 luaL_traceback(L, L1, msg, lj_lib_optint(L, arg+2, (L == L1)));
394 return 1;
395 }
396
397 /* ------------------------------------------------------------------------ */
398
399 #include "lj_libdef.h"
400
401 LUALIB_API int luaopen_debug(lua_State *L)
402 {
403 LJ_LIB_REG(L, LUA_DBLIBNAME, debug);
404 return 1;
405 }
406