diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-11-07 17:25:46 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-11-07 17:25:46 -0300 |
commit | 9e99f3071d07767f9e882c4abf3537f75ce2d161 (patch) | |
tree | a547cbf1772bae35b9c0d842799db0dbf2d27012 | |
parent | 14e416355f83cf0a1b871eedec2c92b86dbe76d6 (diff) | |
parent | 7923dbbf72da303ca1cca17efd24725668992f15 (diff) | |
download | lua-9e99f3071d07767f9e882c4abf3537f75ce2d161.tar.gz lua-9e99f3071d07767f9e882c4abf3537f75ce2d161.tar.bz2 lua-9e99f3071d07767f9e882c4abf3537f75ce2d161.zip |
Merge branch 'master' into nextversion
Diffstat (limited to '')
-rw-r--r-- | ldebug.c | 153 | ||||
-rw-r--r-- | lmathlib.c | 31 | ||||
-rw-r--r-- | ltable.c | 36 | ||||
-rw-r--r-- | lundump.c | 2 | ||||
-rw-r--r-- | testes/calls.lua | 14 | ||||
-rw-r--r-- | testes/errors.lua | 3 |
6 files changed, 137 insertions, 102 deletions
@@ -416,40 +416,6 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { | |||
416 | ** ======================================================= | 416 | ** ======================================================= |
417 | */ | 417 | */ |
418 | 418 | ||
419 | static const char *getobjname (const Proto *p, int lastpc, int reg, | ||
420 | const char **name); | ||
421 | |||
422 | |||
423 | /* | ||
424 | ** Find a "name" for the constant 'c'. | ||
425 | */ | ||
426 | static void kname (const Proto *p, int c, const char **name) { | ||
427 | TValue *kvalue = &p->k[c]; | ||
428 | *name = (ttisstring(kvalue)) ? getstr(tsvalue(kvalue)) : "?"; | ||
429 | } | ||
430 | |||
431 | |||
432 | /* | ||
433 | ** Find a "name" for the register 'c'. | ||
434 | */ | ||
435 | static void rname (const Proto *p, int pc, int c, const char **name) { | ||
436 | const char *what = getobjname(p, pc, c, name); /* search for 'c' */ | ||
437 | if (!(what && *what == 'c')) /* did not find a constant name? */ | ||
438 | *name = "?"; | ||
439 | } | ||
440 | |||
441 | |||
442 | /* | ||
443 | ** Find a "name" for a 'C' value in an RK instruction. | ||
444 | */ | ||
445 | static void rkname (const Proto *p, int pc, Instruction i, const char **name) { | ||
446 | int c = GETARG_C(i); /* key index */ | ||
447 | if (GETARG_k(i)) /* is 'c' a constant? */ | ||
448 | kname(p, c, name); | ||
449 | else /* 'c' is a register */ | ||
450 | rname(p, pc, c, name); | ||
451 | } | ||
452 | |||
453 | 419 | ||
454 | static int filterpc (int pc, int jmptarget) { | 420 | static int filterpc (int pc, int jmptarget) { |
455 | if (pc < jmptarget) /* is code conditional (inside a jump)? */ | 421 | if (pc < jmptarget) /* is code conditional (inside a jump)? */ |
@@ -508,28 +474,29 @@ static int findsetreg (const Proto *p, int lastpc, int reg) { | |||
508 | 474 | ||
509 | 475 | ||
510 | /* | 476 | /* |
511 | ** Check whether table being indexed by instruction 'i' is the | 477 | ** Find a "name" for the constant 'c'. |
512 | ** environment '_ENV' | ||
513 | */ | 478 | */ |
514 | static const char *gxf (const Proto *p, int pc, Instruction i, int isup) { | 479 | static const char *kname (const Proto *p, int index, const char **name) { |
515 | int t = GETARG_B(i); /* table index */ | 480 | TValue *kvalue = &p->k[index]; |
516 | const char *name; /* name of indexed variable */ | 481 | if (ttisstring(kvalue)) { |
517 | if (isup) /* is an upvalue? */ | 482 | *name = getstr(tsvalue(kvalue)); |
518 | name = upvalname(p, t); | 483 | return "constant"; |
519 | else | 484 | } |
520 | getobjname(p, pc, t, &name); | 485 | else { |
521 | return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field"; | 486 | *name = "?"; |
487 | return NULL; | ||
488 | } | ||
522 | } | 489 | } |
523 | 490 | ||
524 | 491 | ||
525 | static const char *getobjname (const Proto *p, int lastpc, int reg, | 492 | static const char *basicgetobjname (const Proto *p, int *ppc, int reg, |
526 | const char **name) { | 493 | const char **name) { |
527 | int pc; | 494 | int pc = *ppc; |
528 | *name = luaF_getlocalname(p, reg + 1, lastpc); | 495 | *name = luaF_getlocalname(p, reg + 1, pc); |
529 | if (*name) /* is a local? */ | 496 | if (*name) /* is a local? */ |
530 | return "local"; | 497 | return "local"; |
531 | /* else try symbolic execution */ | 498 | /* else try symbolic execution */ |
532 | pc = findsetreg(p, lastpc, reg); | 499 | *ppc = pc = findsetreg(p, pc, reg); |
533 | if (pc != -1) { /* could find instruction? */ | 500 | if (pc != -1) { /* could find instruction? */ |
534 | Instruction i = p->code[pc]; | 501 | Instruction i = p->code[pc]; |
535 | OpCode op = GET_OPCODE(i); | 502 | OpCode op = GET_OPCODE(i); |
@@ -537,18 +504,80 @@ static const char *getobjname (const Proto *p, int lastpc, int reg, | |||
537 | case OP_MOVE: { | 504 | case OP_MOVE: { |
538 | int b = GETARG_B(i); /* move from 'b' to 'a' */ | 505 | int b = GETARG_B(i); /* move from 'b' to 'a' */ |
539 | if (b < GETARG_A(i)) | 506 | if (b < GETARG_A(i)) |
540 | return getobjname(p, pc, b, name); /* get name for 'b' */ | 507 | return basicgetobjname(p, ppc, b, name); /* get name for 'b' */ |
541 | break; | 508 | break; |
542 | } | 509 | } |
510 | case OP_GETUPVAL: { | ||
511 | *name = upvalname(p, GETARG_B(i)); | ||
512 | return "upvalue"; | ||
513 | } | ||
514 | case OP_LOADK: return kname(p, GETARG_Bx(i), name); | ||
515 | case OP_LOADKX: return kname(p, GETARG_Ax(p->code[pc + 1]), name); | ||
516 | default: break; | ||
517 | } | ||
518 | } | ||
519 | return NULL; /* could not find reasonable name */ | ||
520 | } | ||
521 | |||
522 | |||
523 | /* | ||
524 | ** Find a "name" for the register 'c'. | ||
525 | */ | ||
526 | static void rname (const Proto *p, int pc, int c, const char **name) { | ||
527 | const char *what = basicgetobjname(p, &pc, c, name); /* search for 'c' */ | ||
528 | if (!(what && *what == 'c')) /* did not find a constant name? */ | ||
529 | *name = "?"; | ||
530 | } | ||
531 | |||
532 | |||
533 | /* | ||
534 | ** Find a "name" for a 'C' value in an RK instruction. | ||
535 | */ | ||
536 | static void rkname (const Proto *p, int pc, Instruction i, const char **name) { | ||
537 | int c = GETARG_C(i); /* key index */ | ||
538 | if (GETARG_k(i)) /* is 'c' a constant? */ | ||
539 | kname(p, c, name); | ||
540 | else /* 'c' is a register */ | ||
541 | rname(p, pc, c, name); | ||
542 | } | ||
543 | |||
544 | |||
545 | /* | ||
546 | ** Check whether table being indexed by instruction 'i' is the | ||
547 | ** environment '_ENV' | ||
548 | */ | ||
549 | static const char *isEnv (const Proto *p, int pc, Instruction i, int isup) { | ||
550 | int t = GETARG_B(i); /* table index */ | ||
551 | const char *name; /* name of indexed variable */ | ||
552 | if (isup) /* is 't' an upvalue? */ | ||
553 | name = upvalname(p, t); | ||
554 | else /* 't' is a register */ | ||
555 | basicgetobjname(p, &pc, t, &name); | ||
556 | return (name && strcmp(name, LUA_ENV) == 0) ? "global" : "field"; | ||
557 | } | ||
558 | |||
559 | |||
560 | /* | ||
561 | ** Extend 'basicgetobjname' to handle table accesses | ||
562 | */ | ||
563 | static const char *getobjname (const Proto *p, int lastpc, int reg, | ||
564 | const char **name) { | ||
565 | const char *kind = basicgetobjname(p, &lastpc, reg, name); | ||
566 | if (kind != NULL) | ||
567 | return kind; | ||
568 | else if (lastpc != -1) { /* could find instruction? */ | ||
569 | Instruction i = p->code[lastpc]; | ||
570 | OpCode op = GET_OPCODE(i); | ||
571 | switch (op) { | ||
543 | case OP_GETTABUP: { | 572 | case OP_GETTABUP: { |
544 | int k = GETARG_C(i); /* key index */ | 573 | int k = GETARG_C(i); /* key index */ |
545 | kname(p, k, name); | 574 | kname(p, k, name); |
546 | return gxf(p, pc, i, 1); | 575 | return isEnv(p, lastpc, i, 1); |
547 | } | 576 | } |
548 | case OP_GETTABLE: { | 577 | case OP_GETTABLE: { |
549 | int k = GETARG_C(i); /* key index */ | 578 | int k = GETARG_C(i); /* key index */ |
550 | rname(p, pc, k, name); | 579 | rname(p, lastpc, k, name); |
551 | return gxf(p, pc, i, 0); | 580 | return isEnv(p, lastpc, i, 0); |
552 | } | 581 | } |
553 | case OP_GETI: { | 582 | case OP_GETI: { |
554 | *name = "integer index"; | 583 | *name = "integer index"; |
@@ -557,24 +586,10 @@ static const char *getobjname (const Proto *p, int lastpc, int reg, | |||
557 | case OP_GETFIELD: { | 586 | case OP_GETFIELD: { |
558 | int k = GETARG_C(i); /* key index */ | 587 | int k = GETARG_C(i); /* key index */ |
559 | kname(p, k, name); | 588 | kname(p, k, name); |
560 | return gxf(p, pc, i, 0); | 589 | return isEnv(p, lastpc, i, 0); |
561 | } | ||
562 | case OP_GETUPVAL: { | ||
563 | *name = upvalname(p, GETARG_B(i)); | ||
564 | return "upvalue"; | ||
565 | } | ||
566 | case OP_LOADK: | ||
567 | case OP_LOADKX: { | ||
568 | int b = (op == OP_LOADK) ? GETARG_Bx(i) | ||
569 | : GETARG_Ax(p->code[pc + 1]); | ||
570 | if (ttisstring(&p->k[b])) { | ||
571 | *name = getstr(tsvalue(&p->k[b])); | ||
572 | return "constant"; | ||
573 | } | ||
574 | break; | ||
575 | } | 590 | } |
576 | case OP_SELF: { | 591 | case OP_SELF: { |
577 | rkname(p, pc, i, name); | 592 | rkname(p, lastpc, i, name); |
578 | return "method"; | 593 | return "method"; |
579 | } | 594 | } |
580 | default: break; /* go through to return NULL */ | 595 | default: break; /* go through to return NULL */ |
@@ -249,6 +249,15 @@ static int math_type (lua_State *L) { | |||
249 | ** =================================================================== | 249 | ** =================================================================== |
250 | */ | 250 | */ |
251 | 251 | ||
252 | /* | ||
253 | ** This code uses lots of shifts. ANSI C does not allow shifts greater | ||
254 | ** than or equal to the width of the type being shifted, so some shifts | ||
255 | ** are written in convoluted ways to match that restriction. For | ||
256 | ** preprocessor tests, it assumes a width of 32 bits, so the maximum | ||
257 | ** shift there is 31 bits. | ||
258 | */ | ||
259 | |||
260 | |||
252 | /* number of binary digits in the mantissa of a float */ | 261 | /* number of binary digits in the mantissa of a float */ |
253 | #define FIGS l_floatatt(MANT_DIG) | 262 | #define FIGS l_floatatt(MANT_DIG) |
254 | 263 | ||
@@ -271,16 +280,19 @@ static int math_type (lua_State *L) { | |||
271 | 280 | ||
272 | /* 'long' has at least 64 bits */ | 281 | /* 'long' has at least 64 bits */ |
273 | #define Rand64 unsigned long | 282 | #define Rand64 unsigned long |
283 | #define SRand64 long | ||
274 | 284 | ||
275 | #elif !defined(LUA_USE_C89) && defined(LLONG_MAX) | 285 | #elif !defined(LUA_USE_C89) && defined(LLONG_MAX) |
276 | 286 | ||
277 | /* there is a 'long long' type (which must have at least 64 bits) */ | 287 | /* there is a 'long long' type (which must have at least 64 bits) */ |
278 | #define Rand64 unsigned long long | 288 | #define Rand64 unsigned long long |
289 | #define SRand64 long long | ||
279 | 290 | ||
280 | #elif ((LUA_MAXUNSIGNED >> 31) >> 31) >= 3 | 291 | #elif ((LUA_MAXUNSIGNED >> 31) >> 31) >= 3 |
281 | 292 | ||
282 | /* 'lua_Unsigned' has at least 64 bits */ | 293 | /* 'lua_Unsigned' has at least 64 bits */ |
283 | #define Rand64 lua_Unsigned | 294 | #define Rand64 lua_Unsigned |
295 | #define SRand64 lua_Integer | ||
284 | 296 | ||
285 | #endif | 297 | #endif |
286 | 298 | ||
@@ -319,23 +331,30 @@ static Rand64 nextrand (Rand64 *state) { | |||
319 | } | 331 | } |
320 | 332 | ||
321 | 333 | ||
322 | /* must take care to not shift stuff by more than 63 slots */ | ||
323 | |||
324 | |||
325 | /* | 334 | /* |
326 | ** Convert bits from a random integer into a float in the | 335 | ** Convert bits from a random integer into a float in the |
327 | ** interval [0,1), getting the higher FIG bits from the | 336 | ** interval [0,1), getting the higher FIG bits from the |
328 | ** random unsigned integer and converting that to a float. | 337 | ** random unsigned integer and converting that to a float. |
338 | ** Some old Microsoft compilers cannot cast an unsigned long | ||
339 | ** to a floating-point number, so we use a signed long as an | ||
340 | ** intermediary. When lua_Number is float or double, the shift ensures | ||
341 | ** that 'sx' is non negative; in that case, a good compiler will remove | ||
342 | ** the correction. | ||
329 | */ | 343 | */ |
330 | 344 | ||
331 | /* must throw out the extra (64 - FIGS) bits */ | 345 | /* must throw out the extra (64 - FIGS) bits */ |
332 | #define shift64_FIG (64 - FIGS) | 346 | #define shift64_FIG (64 - FIGS) |
333 | 347 | ||
334 | /* to scale to [0, 1), multiply by scaleFIG = 2^(-FIGS) */ | 348 | /* 2^(-FIGS) == 2^-1 / 2^(FIGS-1) */ |
335 | #define scaleFIG (l_mathop(0.5) / ((Rand64)1 << (FIGS - 1))) | 349 | #define scaleFIG (l_mathop(0.5) / ((Rand64)1 << (FIGS - 1))) |
336 | 350 | ||
337 | static lua_Number I2d (Rand64 x) { | 351 | static lua_Number I2d (Rand64 x) { |
338 | return (lua_Number)(trim64(x) >> shift64_FIG) * scaleFIG; | 352 | SRand64 sx = (SRand64)(trim64(x) >> shift64_FIG); |
353 | lua_Number res = (lua_Number)(sx) * scaleFIG; | ||
354 | if (sx < 0) | ||
355 | res += 1.0; /* correct the two's complement if negative */ | ||
356 | lua_assert(0 <= res && res < 1); | ||
357 | return res; | ||
339 | } | 358 | } |
340 | 359 | ||
341 | /* convert a 'Rand64' to a 'lua_Unsigned' */ | 360 | /* convert a 'Rand64' to a 'lua_Unsigned' */ |
@@ -471,8 +490,6 @@ static lua_Number I2d (Rand64 x) { | |||
471 | 490 | ||
472 | #else /* 32 < FIGS <= 64 */ | 491 | #else /* 32 < FIGS <= 64 */ |
473 | 492 | ||
474 | /* must take care to not shift stuff by more than 31 slots */ | ||
475 | |||
476 | /* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */ | 493 | /* 2^(-FIGS) = 1.0 / 2^30 / 2^3 / 2^(FIGS-33) */ |
477 | #define scaleFIG \ | 494 | #define scaleFIG \ |
478 | (l_mathop(1.0) / (UONE << 30) / l_mathop(8.0) / (UONE << (FIGS - 33))) | 495 | (l_mathop(1.0) / (UONE << 30) / l_mathop(8.0) / (UONE << (FIGS - 33))) |
@@ -273,7 +273,7 @@ LUAI_FUNC unsigned int luaH_realasize (const Table *t) { | |||
273 | return t->alimit; /* this is the size */ | 273 | return t->alimit; /* this is the size */ |
274 | else { | 274 | else { |
275 | unsigned int size = t->alimit; | 275 | unsigned int size = t->alimit; |
276 | /* compute the smallest power of 2 not smaller than 'n' */ | 276 | /* compute the smallest power of 2 not smaller than 'size' */ |
277 | size |= (size >> 1); | 277 | size |= (size >> 1); |
278 | size |= (size >> 2); | 278 | size |= (size >> 2); |
279 | size |= (size >> 4); | 279 | size |= (size >> 4); |
@@ -772,22 +772,36 @@ static void luaH_newkey (lua_State *L, Table *t, const TValue *key, | |||
772 | 772 | ||
773 | /* | 773 | /* |
774 | ** Search function for integers. If integer is inside 'alimit', get it | 774 | ** Search function for integers. If integer is inside 'alimit', get it |
775 | ** directly from the array part. Otherwise, if 'alimit' is not equal to | 775 | ** directly from the array part. Otherwise, if 'alimit' is not |
776 | ** the real size of the array, key still can be in the array part. In | 776 | ** the real size of the array, the key still can be in the array part. |
777 | ** this case, try to avoid a call to 'luaH_realasize' when key is just | 777 | ** In this case, do the "Xmilia trick" to check whether 'key-1' is |
778 | ** one more than the limit (so that it can be incremented without | 778 | ** smaller than the real size. |
779 | ** changing the real size of the array). | 779 | ** The trick works as follow: let 'p' be an integer such that |
780 | ** '2^(p+1) >= alimit > 2^p', or '2^(p+1) > alimit-1 >= 2^p'. | ||
781 | ** That is, 2^(p+1) is the real size of the array, and 'p' is the highest | ||
782 | ** bit on in 'alimit-1'. What we have to check becomes 'key-1 < 2^(p+1)'. | ||
783 | ** We compute '(key-1) & ~(alimit-1)', which we call 'res'; it will | ||
784 | ** have the 'p' bit cleared. If the key is outside the array, that is, | ||
785 | ** 'key-1 >= 2^(p+1)', then 'res' will have some bit on higher than 'p', | ||
786 | ** therefore it will be larger or equal to 'alimit', and the check | ||
787 | ** will fail. If 'key-1 < 2^(p+1)', then 'res' has no bit on higher than | ||
788 | ** 'p', and as the bit 'p' itself was cleared, 'res' will be smaller | ||
789 | ** than 2^p, therefore smaller than 'alimit', and the check succeeds. | ||
790 | ** As special cases, when 'alimit' is 0 the condition is trivially false, | ||
791 | ** and when 'alimit' is 1 the condition simplifies to 'key-1 < alimit'. | ||
792 | ** If key is 0 or negative, 'res' will have its higher bit on, so that | ||
793 | ** if cannot be smaller than alimit. | ||
780 | */ | 794 | */ |
781 | const TValue *luaH_getint (Table *t, lua_Integer key) { | 795 | const TValue *luaH_getint (Table *t, lua_Integer key) { |
782 | if (l_castS2U(key) - 1u < t->alimit) /* 'key' in [1, t->alimit]? */ | 796 | lua_Unsigned alimit = t->alimit; |
797 | if (l_castS2U(key) - 1u < alimit) /* 'key' in [1, t->alimit]? */ | ||
783 | return &t->array[key - 1]; | 798 | return &t->array[key - 1]; |
784 | else if (!limitequalsasize(t) && /* key still may be in the array part? */ | 799 | else if (!isrealasize(t) && /* key still may be in the array part? */ |
785 | (l_castS2U(key) == t->alimit + 1 || | 800 | (((l_castS2U(key) - 1u) & ~(alimit - 1u)) < alimit)) { |
786 | l_castS2U(key) - 1u < luaH_realasize(t))) { | ||
787 | t->alimit = cast_uint(key); /* probably '#t' is here now */ | 801 | t->alimit = cast_uint(key); /* probably '#t' is here now */ |
788 | return &t->array[key - 1]; | 802 | return &t->array[key - 1]; |
789 | } | 803 | } |
790 | else { | 804 | else { /* key is not in the array part; check the hash */ |
791 | Node *n = hashint(t, key); | 805 | Node *n = hashint(t, key); |
792 | for (;;) { /* check whether 'key' is somewhere in the chain */ | 806 | for (;;) { /* check whether 'key' is somewhere in the chain */ |
793 | if (keyisinteger(n) && keyival(n) == key) | 807 | if (keyisinteger(n) && keyival(n) == key) |
@@ -108,7 +108,7 @@ static size_t loadUnsigned (LoadState *S, size_t limit) { | |||
108 | 108 | ||
109 | 109 | ||
110 | static size_t loadSize (LoadState *S) { | 110 | static size_t loadSize (LoadState *S) { |
111 | return loadUnsigned(S, ~(size_t)0); | 111 | return loadUnsigned(S, MAX_SIZET); |
112 | } | 112 | } |
113 | 113 | ||
114 | 114 | ||
diff --git a/testes/calls.lua b/testes/calls.lua index 7468d4ab..9a5eed0b 100644 --- a/testes/calls.lua +++ b/testes/calls.lua | |||
@@ -342,20 +342,6 @@ do -- another bug (in 5.4.0) | |||
342 | end | 342 | end |
343 | 343 | ||
344 | 344 | ||
345 | if not _port then -- another bug (since 5.2) | ||
346 | -- corrupted binary dump: list of upvalue names is larger than number | ||
347 | -- of upvalues, overflowing the array of upvalues. | ||
348 | local code = | ||
349 | "\x1b\x4c\x75\x61\x55\x00\x19\x93\x0d\x0a\x1a\x0a\x04\x08\x08\x78\x56\z | ||
350 | \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x28\x77\x40\x00\x86\x40\z | ||
351 | \x74\x65\x6d\x70\x81\x81\x01\x00\x02\x82\x48\x00\x02\x00\xc7\x00\x01\z | ||
352 | \x00\x80\x80\x80\x82\x00\x00\x80\x81\x82\x78\x80\x82\x81\x86\x40\x74\z | ||
353 | \x65\x6d\x70" | ||
354 | |||
355 | assert(load(code)) -- segfaults in previous versions | ||
356 | end | ||
357 | |||
358 | |||
359 | x = string.dump(load("x = 1; return x")) | 345 | x = string.dump(load("x = 1; return x")) |
360 | a = assert(load(read1(x), nil, "b")) | 346 | a = assert(load(read1(x), nil, "b")) |
361 | assert(a() == 1 and _G.x == 1) | 347 | assert(a() == 1 and _G.x == 1) |
diff --git a/testes/errors.lua b/testes/errors.lua index b777a329..01cfe906 100644 --- a/testes/errors.lua +++ b/testes/errors.lua | |||
@@ -121,6 +121,9 @@ assert(not string.find(doit"aaa={13}; local bbbb=1; aaa[bbbb](3)", "'bbbb'")) | |||
121 | checkmessage("aaa={13}; local bbbb=1; aaa[bbbb](3)", "number") | 121 | checkmessage("aaa={13}; local bbbb=1; aaa[bbbb](3)", "number") |
122 | checkmessage("aaa=(1)..{}", "a table value") | 122 | checkmessage("aaa=(1)..{}", "a table value") |
123 | 123 | ||
124 | -- bug in 5.4.6 | ||
125 | checkmessage("a = {_ENV = {}}; print(a._ENV.x + 1)", "field 'x'") | ||
126 | |||
124 | _G.aaa, _G.bbbb = nil | 127 | _G.aaa, _G.bbbb = nil |
125 | 128 | ||
126 | -- calls | 129 | -- calls |