@@ -190,7 +190,7 @@ LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) {
190
190
}
191
191
192
192
193
- int luaL_typeerror (lua_State * L , int arg , const char * tname ) {
193
+ LUALIB_API int luaL_typeerror (lua_State * L , int arg , const char * tname ) {
194
194
const char * msg ;
195
195
const char * typearg ; /* name for the type of the actual argument */
196
196
if (luaL_getmetafield (L , arg , "__name" ) == LUA_TSTRING )
@@ -378,7 +378,7 @@ LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def,
378
378
** but without 'msg'.)
379
379
*/
380
380
LUALIB_API void luaL_checkstack (lua_State * L , int space , const char * msg ) {
381
- if (!lua_checkstack (L , space )) {
381
+ if (l_unlikely ( !lua_checkstack (L , space ) )) {
382
382
if (msg )
383
383
luaL_error (L , "stack overflow (%s)" , msg );
384
384
else
@@ -388,20 +388,20 @@ LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
388
388
389
389
390
390
LUALIB_API void luaL_checktype (lua_State * L , int arg , int t ) {
391
- if (lua_type (L , arg ) != t )
391
+ if (l_unlikely ( lua_type (L , arg ) != t ) )
392
392
tag_error (L , arg , t );
393
393
}
394
394
395
395
396
396
LUALIB_API void luaL_checkany (lua_State * L , int arg ) {
397
- if (lua_type (L , arg ) == LUA_TNONE )
397
+ if (l_unlikely ( lua_type (L , arg ) == LUA_TNONE ) )
398
398
luaL_argerror (L , arg , "value expected" );
399
399
}
400
400
401
401
402
402
LUALIB_API const char * luaL_checklstring (lua_State * L , int arg , size_t * len ) {
403
403
const char * s = lua_tolstring (L , arg , len );
404
- if (! s ) tag_error (L , arg , LUA_TSTRING );
404
+ if (l_unlikely (! s ) ) tag_error (L , arg , LUA_TSTRING );
405
405
return s ;
406
406
}
407
407
@@ -420,7 +420,7 @@ LUALIB_API const char *luaL_optlstring (lua_State *L, int arg,
420
420
LUALIB_API lua_Number luaL_checknumber (lua_State * L , int arg ) {
421
421
int isnum ;
422
422
lua_Number d = lua_tonumberx (L , arg , & isnum );
423
- if (!isnum )
423
+ if (l_unlikely ( !isnum ) )
424
424
tag_error (L , arg , LUA_TNUMBER );
425
425
return d ;
426
426
}
@@ -442,7 +442,7 @@ static void interror (lua_State *L, int arg) {
442
442
LUALIB_API lua_Integer luaL_checkinteger (lua_State * L , int arg ) {
443
443
int isnum ;
444
444
lua_Integer d = lua_tointegerx (L , arg , & isnum );
445
- if (!isnum ) {
445
+ if (l_unlikely ( !isnum ) ) {
446
446
interror (L , arg );
447
447
}
448
448
return d ;
@@ -475,7 +475,7 @@ static void *resizebox (lua_State *L, int idx, size_t newsize) {
475
475
lua_Alloc allocf = lua_getallocf (L , & ud );
476
476
UBox * box = (UBox * )lua_touserdata (L , idx );
477
477
void * temp = allocf (ud , box -> box , box -> bsize , newsize );
478
- if (temp == NULL && newsize > 0 ) { /* allocation error? */
478
+ if (l_unlikely ( temp == NULL && newsize > 0 ) ) { /* allocation error? */
479
479
lua_pushliteral (L , "not enough memory" );
480
480
lua_error (L ); /* raise a memory error */
481
481
}
@@ -515,13 +515,22 @@ static void newbox (lua_State *L) {
515
515
#define buffonstack (B ) ((B)->b != (B)->init.b)
516
516
517
517
518
+ /*
519
+ ** Whenever buffer is accessed, slot 'idx' must either be a box (which
520
+ ** cannot be NULL) or it is a placeholder for the buffer.
521
+ */
522
+ #define checkbufferlevel (B ,idx ) \
523
+ lua_assert(buffonstack(B) ? lua_touserdata(B->L, idx) != NULL \
524
+ : lua_touserdata(B->L, idx) == (void*)B)
525
+
526
+
518
527
/*
519
528
** Compute new size for buffer 'B', enough to accommodate extra 'sz'
520
529
** bytes.
521
530
*/
522
531
static size_t newbuffsize (luaL_Buffer * B , size_t sz ) {
523
532
size_t newsize = B -> size * 2 ; /* double buffer size */
524
- if (MAX_SIZET - sz < B -> n ) /* overflow in (B->n + sz)? */
533
+ if (l_unlikely ( MAX_SIZET - sz < B -> n ) ) /* overflow in (B->n + sz)? */
525
534
return luaL_error (B -> L , "buffer too large" );
526
535
if (newsize < B -> n + sz ) /* double is not big enough? */
527
536
newsize = B -> n + sz ;
@@ -531,10 +540,11 @@ static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
531
540
532
541
/*
533
542
** Returns a pointer to a free area with at least 'sz' bytes in buffer
534
- ** 'B'. 'boxidx' is the relative position in the stack where the
535
- ** buffer's box is or should be .
543
+ ** 'B'. 'boxidx' is the relative position in the stack where is the
544
+ ** buffer's box or its placeholder .
536
545
*/
537
546
static char * prepbuffsize (luaL_Buffer * B , size_t sz , int boxidx ) {
547
+ checkbufferlevel (B , boxidx );
538
548
if (B -> size - B -> n >= sz ) /* enough space? */
539
549
return B -> b + B -> n ;
540
550
else {
@@ -545,10 +555,9 @@ static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) {
545
555
if (buffonstack (B )) /* buffer already has a box? */
546
556
newbuff = (char * )resizebox (L , boxidx , newsize ); /* resize it */
547
557
else { /* no box yet */
548
- lua_pushnil ( L ); /* reserve slot for final result */
558
+ lua_remove ( L , boxidx ); /* remove placeholder */
549
559
newbox (L ); /* create a new box */
550
- /* move box (and slot) to its intended position */
551
- lua_rotate (L , boxidx - 1 , 2 );
560
+ lua_insert (L , boxidx ); /* move box to its intended position */
552
561
lua_toclose (L , boxidx );
553
562
newbuff = (char * )resizebox (L , boxidx , newsize );
554
563
memcpy (newbuff , B -> b , B -> n * sizeof (char )); /* copy original content */
@@ -583,11 +592,11 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) {
583
592
584
593
LUALIB_API void luaL_pushresult (luaL_Buffer * B ) {
585
594
lua_State * L = B -> L ;
595
+ checkbufferlevel (B , -1 );
586
596
lua_pushlstring (L , B -> b , B -> n );
587
- if (buffonstack (B )) {
588
- lua_copy (L , -1 , -3 ); /* move string to reserved slot */
589
- lua_pop (L , 2 ); /* pop string and box (closing the box) */
590
- }
597
+ if (buffonstack (B ))
598
+ lua_closeslot (L , -2 ); /* close the box */
599
+ lua_remove (L , -2 ); /* remove box or placeholder from the stack */
591
600
}
592
601
593
602
@@ -622,6 +631,7 @@ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
622
631
B -> b = B -> init .b ;
623
632
B -> n = 0 ;
624
633
B -> size = LUAL_BUFFERSIZE ;
634
+ lua_pushlightuserdata (L , (void * )B ); /* push placeholder */
625
635
}
626
636
627
637
@@ -639,20 +649,31 @@ LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
639
649
** =======================================================
640
650
*/
641
651
642
- /* index of free-list header */
643
- #define freelist 0
644
-
652
+ /* index of free-list header (after the predefined values) */
653
+ #define freelist (LUA_RIDX_LAST + 1)
645
654
655
+ /*
656
+ ** The previously freed references form a linked list:
657
+ ** t[freelist] is the index of a first free index, or zero if list is
658
+ ** empty; t[t[freelist]] is the index of the second element; etc.
659
+ */
646
660
LUALIB_API int luaL_ref (lua_State * L , int t ) {
647
661
int ref ;
648
662
if (lua_isnil (L , -1 )) {
649
663
lua_pop (L , 1 ); /* remove from stack */
650
664
return LUA_REFNIL ; /* 'nil' has a unique fixed reference */
651
665
}
652
666
t = lua_absindex (L , t );
653
- lua_rawgeti (L , t , freelist ); /* get first free element */
654
- ref = (int )lua_tointeger (L , -1 ); /* ref = t[freelist] */
655
- lua_pop (L , 1 ); /* remove it from stack */
667
+ if (lua_rawgeti (L , t , freelist ) == LUA_TNIL ) { /* first access? */
668
+ ref = 0 ; /* list is empty */
669
+ lua_pushinteger (L , 0 ); /* initialize as an empty list */
670
+ lua_rawseti (L , t , freelist ); /* ref = t[freelist] = 0 */
671
+ }
672
+ else { /* already initialized */
673
+ lua_assert (lua_isinteger (L , -1 ));
674
+ ref = (int )lua_tointeger (L , -1 ); /* ref = t[freelist] */
675
+ }
676
+ lua_pop (L , 1 ); /* remove element from stack */
656
677
if (ref != 0 ) { /* any free element? */
657
678
lua_rawgeti (L , t , ref ); /* remove it from list */
658
679
lua_rawseti (L , t , freelist ); /* (t[freelist] = t[ref]) */
@@ -668,6 +689,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
668
689
if (ref >= 0 ) {
669
690
t = lua_absindex (L , t );
670
691
lua_rawgeti (L , t , freelist );
692
+ lua_assert (lua_isinteger (L , -1 ));
671
693
lua_rawseti (L , t , ref ); /* t[ref] = t[freelist] */
672
694
lua_pushinteger (L , ref );
673
695
lua_rawseti (L , t , freelist ); /* t[freelist] = ref */
@@ -851,7 +873,7 @@ LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
851
873
int isnum ;
852
874
lua_len (L , idx );
853
875
l = lua_tointegerx (L , -1 , & isnum );
854
- if (!isnum )
876
+ if (l_unlikely ( !isnum ) )
855
877
luaL_error (L , "object length is not an integer" );
856
878
lua_pop (L , 1 ); /* remove object */
857
879
return l ;
@@ -1064,7 +1086,7 @@ static void warnfon (void *ud, const char *message, int tocont) {
1064
1086
1065
1087
LUALIB_API lua_State * luaL_newstate (void ) {
1066
1088
lua_State * L = lua_newstate (l_alloc , NULL );
1067
- if (L ) {
1089
+ if (l_likely ( L ) ) {
1068
1090
lua_atpanic (L , & panic );
1069
1091
lua_setwarnf (L , warnfoff , L ); /* default is warnings off */
1070
1092
}
0 commit comments