@@ -190,7 +190,7 @@ LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) {
190190}
191191
192192
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 ) {
194194 const char * msg ;
195195 const char * typearg ; /* name for the type of the actual argument */
196196 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,
378378** but without 'msg'.)
379379*/
380380LUALIB_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 ) )) {
382382 if (msg )
383383 luaL_error (L , "stack overflow (%s)" , msg );
384384 else
@@ -388,20 +388,20 @@ LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) {
388388
389389
390390LUALIB_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 ) )
392392 tag_error (L , arg , t );
393393}
394394
395395
396396LUALIB_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 ) )
398398 luaL_argerror (L , arg , "value expected" );
399399}
400400
401401
402402LUALIB_API const char * luaL_checklstring (lua_State * L , int arg , size_t * len ) {
403403 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 );
405405 return s ;
406406}
407407
@@ -420,7 +420,7 @@ LUALIB_API const char *luaL_optlstring (lua_State *L, int arg,
420420LUALIB_API lua_Number luaL_checknumber (lua_State * L , int arg ) {
421421 int isnum ;
422422 lua_Number d = lua_tonumberx (L , arg , & isnum );
423- if (!isnum )
423+ if (l_unlikely ( !isnum ) )
424424 tag_error (L , arg , LUA_TNUMBER );
425425 return d ;
426426}
@@ -442,7 +442,7 @@ static void interror (lua_State *L, int arg) {
442442LUALIB_API lua_Integer luaL_checkinteger (lua_State * L , int arg ) {
443443 int isnum ;
444444 lua_Integer d = lua_tointegerx (L , arg , & isnum );
445- if (!isnum ) {
445+ if (l_unlikely ( !isnum ) ) {
446446 interror (L , arg );
447447 }
448448 return d ;
@@ -475,7 +475,7 @@ static void *resizebox (lua_State *L, int idx, size_t newsize) {
475475 lua_Alloc allocf = lua_getallocf (L , & ud );
476476 UBox * box = (UBox * )lua_touserdata (L , idx );
477477 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? */
479479 lua_pushliteral (L , "not enough memory" );
480480 lua_error (L ); /* raise a memory error */
481481 }
@@ -515,13 +515,22 @@ static void newbox (lua_State *L) {
515515#define buffonstack (B ) ((B)->b != (B)->init.b)
516516
517517
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+
518527/*
519528** Compute new size for buffer 'B', enough to accommodate extra 'sz'
520529** bytes.
521530*/
522531static size_t newbuffsize (luaL_Buffer * B , size_t sz ) {
523532 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)? */
525534 return luaL_error (B -> L , "buffer too large" );
526535 if (newsize < B -> n + sz ) /* double is not big enough? */
527536 newsize = B -> n + sz ;
@@ -531,10 +540,11 @@ static size_t newbuffsize (luaL_Buffer *B, size_t sz) {
531540
532541/*
533542** 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 .
536545*/
537546static char * prepbuffsize (luaL_Buffer * B , size_t sz , int boxidx ) {
547+ checkbufferlevel (B , boxidx );
538548 if (B -> size - B -> n >= sz ) /* enough space? */
539549 return B -> b + B -> n ;
540550 else {
@@ -545,10 +555,9 @@ static char *prepbuffsize (luaL_Buffer *B, size_t sz, int boxidx) {
545555 if (buffonstack (B )) /* buffer already has a box? */
546556 newbuff = (char * )resizebox (L , boxidx , newsize ); /* resize it */
547557 else { /* no box yet */
548- lua_pushnil ( L ); /* reserve slot for final result */
558+ lua_remove ( L , boxidx ); /* remove placeholder */
549559 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 */
552561 lua_toclose (L , boxidx );
553562 newbuff = (char * )resizebox (L , boxidx , newsize );
554563 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) {
583592
584593LUALIB_API void luaL_pushresult (luaL_Buffer * B ) {
585594 lua_State * L = B -> L ;
595+ checkbufferlevel (B , -1 );
586596 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 */
591600}
592601
593602
@@ -622,6 +631,7 @@ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
622631 B -> b = B -> init .b ;
623632 B -> n = 0 ;
624633 B -> size = LUAL_BUFFERSIZE ;
634+ lua_pushlightuserdata (L , (void * )B ); /* push placeholder */
625635}
626636
627637
@@ -639,20 +649,31 @@ LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) {
639649** =======================================================
640650*/
641651
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)
645654
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+ */
646660LUALIB_API int luaL_ref (lua_State * L , int t ) {
647661 int ref ;
648662 if (lua_isnil (L , -1 )) {
649663 lua_pop (L , 1 ); /* remove from stack */
650664 return LUA_REFNIL ; /* 'nil' has a unique fixed reference */
651665 }
652666 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 */
656677 if (ref != 0 ) { /* any free element? */
657678 lua_rawgeti (L , t , ref ); /* remove it from list */
658679 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) {
668689 if (ref >= 0 ) {
669690 t = lua_absindex (L , t );
670691 lua_rawgeti (L , t , freelist );
692+ lua_assert (lua_isinteger (L , -1 ));
671693 lua_rawseti (L , t , ref ); /* t[ref] = t[freelist] */
672694 lua_pushinteger (L , ref );
673695 lua_rawseti (L , t , freelist ); /* t[freelist] = ref */
@@ -851,7 +873,7 @@ LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) {
851873 int isnum ;
852874 lua_len (L , idx );
853875 l = lua_tointegerx (L , -1 , & isnum );
854- if (!isnum )
876+ if (l_unlikely ( !isnum ) )
855877 luaL_error (L , "object length is not an integer" );
856878 lua_pop (L , 1 ); /* remove object */
857879 return l ;
@@ -1064,7 +1086,7 @@ static void warnfon (void *ud, const char *message, int tocont) {
10641086
10651087LUALIB_API lua_State * luaL_newstate (void ) {
10661088 lua_State * L = lua_newstate (l_alloc , NULL );
1067- if (L ) {
1089+ if (l_likely ( L ) ) {
10681090 lua_atpanic (L , & panic );
10691091 lua_setwarnf (L , warnfoff , L ); /* default is warnings off */
10701092 }
0 commit comments