diff options
author | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-02-26 11:53:30 +0100 |
---|---|---|
committer | Benoit Germain <bnt period germain arrobase gmail period com> | 2014-02-26 11:53:30 +0100 |
commit | fe3c44e63f99538a02d42d2504ba405a6977ec0a (patch) | |
tree | ee369b7c44fb52b2030b784297e2b5ee788305c3 /src/tools.c | |
parent | d2bd8f65c678d898b6b7e5e92f76cb4dcce97b3c (diff) | |
download | lanes-fe3c44e63f99538a02d42d2504ba405a6977ec0a.tar.gz lanes-fe3c44e63f99538a02d42d2504ba405a6977ec0a.tar.bz2 lanes-fe3c44e63f99538a02d42d2504ba405a6977ec0a.zip |
Multiverse compatibility
* bumped version to 3.9.2
* Internal rework: the whole Lanes engine now works "per universe" to
allow concurrent Lanes execution in more than one embedded master state
* this universe is a full userdata created in the master state,
selfdestruct_gc is the __gc for this userdata
* most of what was initialized only once is now per-universe
* Fixed potential crashes at desinit if problems occur during keeper
states initialisation
* Fixed require() not always serialized properly
* Raise an error instead of crashing on deep userdata prelude memory
allocation failure
* Added forgotten mutex desinitialisation at universe shutdown
Diffstat (limited to 'src/tools.c')
-rw-r--r-- | src/tools.c | 347 |
1 files changed, 197 insertions, 150 deletions
diff --git a/src/tools.c b/src/tools.c index 81ddf5c..65387e5 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -46,6 +46,8 @@ THE SOFTWARE. | |||
46 | #include <malloc.h> | 46 | #include <malloc.h> |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | void* const UNIVERSE_REGKEY = (void*) luaopen_lanes_core; | ||
50 | |||
49 | /* | 51 | /* |
50 | * ############################################################################################### | 52 | * ############################################################################################### |
51 | * ########################################### ASSERT ############################################ | 53 | * ########################################### ASSERT ############################################ |
@@ -59,9 +61,6 @@ void ASSERT_IMPL( lua_State* L, bool_t cond_, char const* file_, int const line_ | |||
59 | } | 61 | } |
60 | } | 62 | } |
61 | 63 | ||
62 | // for verbose errors | ||
63 | bool_t GVerboseErrors = FALSE; | ||
64 | |||
65 | char const* const CONFIG_REGKEY = "ee932492-a654-4506-9da8-f16540bdb5d4"; | 64 | char const* const CONFIG_REGKEY = "ee932492-a654-4506-9da8-f16540bdb5d4"; |
66 | char const* const LOOKUP_REGKEY = "ddea37aa-50c7-4d3f-8e0b-fb7a9d62bac5"; | 65 | char const* const LOOKUP_REGKEY = "ddea37aa-50c7-4d3f-8e0b-fb7a9d62bac5"; |
67 | 66 | ||
@@ -109,11 +108,7 @@ void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int | |||
109 | #endif // LUA_VERSION_NUM | 108 | #endif // LUA_VERSION_NUM |
110 | 109 | ||
111 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); | 110 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); |
112 | DEBUGSPEW_CODE( int debugspew_indent_depth = 0); | ||
113 | |||
114 | 111 | ||
115 | MUTEX_T deep_lock; | ||
116 | MUTEX_T mtid_lock; | ||
117 | 112 | ||
118 | /*---=== luaG_dump ===---*/ | 113 | /*---=== luaG_dump ===---*/ |
119 | 114 | ||
@@ -161,46 +156,58 @@ void luaG_dump( lua_State* L ) { | |||
161 | fprintf( stderr, "\n" ); | 156 | fprintf( stderr, "\n" ); |
162 | } | 157 | } |
163 | 158 | ||
164 | static lua_CFunction s_on_state_create_func = NULL; | 159 | void initialize_on_state_create( struct s_Universe* U, lua_State* L) |
165 | int initialize_on_state_create( lua_State* L) | ||
166 | { | 160 | { |
167 | STACK_CHECK( L); | 161 | STACK_CHECK( L); |
168 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil | 162 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil |
169 | if( !lua_isnil( L, -1)) | 163 | if( !lua_isnil( L, -1)) |
170 | { | 164 | { |
171 | // store C function pointer in an internal variable | 165 | // store C function pointer in an internal variable |
172 | s_on_state_create_func = lua_tocfunction( L, -1); // settings on_state_create | 166 | U->on_state_create_func = lua_tocfunction( L, -1); // settings on_state_create |
173 | if( s_on_state_create_func != NULL) | 167 | if( U->on_state_create_func != NULL) |
174 | { | 168 | { |
175 | // make sure the function doesn't have upvalues | 169 | // make sure the function doesn't have upvalues |
176 | char const* upname = lua_getupvalue( L, -1, 1); // settings on_state_create upval? | 170 | char const* upname = lua_getupvalue( L, -1, 1); // settings on_state_create upval? |
177 | if( upname != NULL) // should be "" for C functions with upvalues if any | 171 | if( upname != NULL) // should be "" for C functions with upvalues if any |
178 | { | 172 | { |
179 | luaL_error( L, "on_state_create shouldn't have upvalues"); | 173 | (void) luaL_error( L, "on_state_create shouldn't have upvalues"); |
180 | } | 174 | } |
181 | // remove this C function from the config table so that it doesn't cause problems | 175 | // remove this C function from the config table so that it doesn't cause problems |
182 | // when we transfer the config table in newly created Lua states | 176 | // when we transfer the config table in newly created Lua states |
183 | lua_pushnil( L); // settings on_state_create nil | 177 | lua_pushnil( L); // settings on_state_create nil |
184 | lua_setfield( L, -3, "on_state_create"); // settings on_state_create | 178 | lua_setfield( L, -3, "on_state_create"); // settings on_state_create |
185 | } | 179 | } |
186 | else | 180 | else |
187 | { | 181 | { |
188 | // optim: store marker saying we have such a function in the config table | 182 | // optim: store marker saying we have such a function in the config table |
189 | s_on_state_create_func = initialize_on_state_create; | 183 | U->on_state_create_func = (lua_CFunction) initialize_on_state_create; |
190 | } | 184 | } |
191 | } | 185 | } |
192 | lua_pop( L, 1); // settings | 186 | lua_pop( L, 1); // settings |
193 | STACK_END( L, 0); | 187 | STACK_END( L, 0); |
194 | return 0; | 188 | } |
189 | |||
190 | |||
191 | struct s_Universe* get_universe( lua_State* L) | ||
192 | { | ||
193 | struct s_Universe* universe; | ||
194 | STACK_GROW( L, 2); | ||
195 | STACK_CHECK( L); | ||
196 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); | ||
197 | lua_rawget( L, LUA_REGISTRYINDEX); | ||
198 | universe = lua_touserdata( L, -1); // NULL if nil | ||
199 | lua_pop( L, 1); | ||
200 | STACK_END( L, 0); | ||
201 | return universe; | ||
195 | } | 202 | } |
196 | 203 | ||
197 | // just like lua_xmove, args are (from, to) | 204 | // just like lua_xmove, args are (from, to) |
198 | void luaG_copy_one_time_settings( lua_State* L, lua_State* L2) | 205 | void luaG_copy_one_time_settings( struct s_Universe* U, lua_State* L, lua_State* L2) |
199 | { | 206 | { |
200 | STACK_GROW( L, 1); | 207 | STACK_GROW( L, 1); |
201 | // copy settings from from source to destination registry | 208 | // copy settings from from source to destination registry |
202 | lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); | 209 | lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); |
203 | if( luaG_inter_move( L, L2, 1, eLM_LaneBody) < 0) // error? | 210 | if( luaG_inter_move( U, L, L2, 1, eLM_LaneBody) < 0) // error? |
204 | { | 211 | { |
205 | (void) luaL_error( L, "failed to copy settings when loading lanes.core"); | 212 | (void) luaL_error( L, "failed to copy settings when loading lanes.core"); |
206 | } | 213 | } |
@@ -241,7 +248,7 @@ static const luaL_Reg libs[] = | |||
241 | { NULL, NULL } | 248 | { NULL, NULL } |
242 | }; | 249 | }; |
243 | 250 | ||
244 | static void open1lib( lua_State* L, char const* name_, size_t len_, lua_State* from_) | 251 | static void open1lib( struct s_Universe* U, lua_State* L, char const* name_, size_t len_, lua_State* from_) |
245 | { | 252 | { |
246 | int i; | 253 | int i; |
247 | for( i = 0; libs[i].name; ++ i) | 254 | for( i = 0; libs[i].name; ++ i) |
@@ -258,7 +265,7 @@ static void open1lib( lua_State* L, char const* name_, size_t len_, lua_State* f | |||
258 | if( isLanesCore == TRUE) | 265 | if( isLanesCore == TRUE) |
259 | { | 266 | { |
260 | // copy settings from from source to destination registry | 267 | // copy settings from from source to destination registry |
261 | luaG_copy_one_time_settings( from_, L); | 268 | luaG_copy_one_time_settings( U, from_, L); |
262 | } | 269 | } |
263 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) | 270 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) |
264 | luaL_requiref( L, name_, libfunc, !isLanesCore); | 271 | luaL_requiref( L, name_, libfunc, !isLanesCore); |
@@ -377,6 +384,7 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
377 | int const cache = _ctx_base + 2; | 384 | int const cache = _ctx_base + 2; |
378 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) | 385 | // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search) |
379 | int const breadth_first_cache = lua_gettop( L) + 1; | 386 | int const breadth_first_cache = lua_gettop( L) + 1; |
387 | DEBUGSPEW_CODE( struct s_Universe* U = get_universe( L)); | ||
380 | 388 | ||
381 | STACK_GROW( L, 6); | 389 | STACK_GROW( L, 6); |
382 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) | 390 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) |
@@ -503,7 +511,7 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
503 | { | 511 | { |
504 | DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"); | 512 | DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string"); |
505 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); | 513 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key)); |
506 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | 514 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
507 | // un-visit this table in case we do need to process it | 515 | // un-visit this table in case we do need to process it |
508 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} | 516 | lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} |
509 | lua_rawget( L, cache); // ... {_i} {bfc} k {} n | 517 | lua_rawget( L, cache); // ... {_i} {bfc} k {} n |
@@ -526,7 +534,7 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
526 | populate_func_lookup_table_recur( L, _ctx_base, lua_gettop( L), _depth); // ... {_i} {bfc} k {} | 534 | populate_func_lookup_table_recur( L, _ctx_base, lua_gettop( L), _depth); // ... {_i} {bfc} k {} |
527 | lua_pop( L, 1); // ... {_i} {bfc} k | 535 | lua_pop( L, 1); // ... {_i} {bfc} k |
528 | STACK_MID( L, 2); | 536 | STACK_MID( L, 2); |
529 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | 537 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
530 | } | 538 | } |
531 | // remove table name from fqn stack | 539 | // remove table name from fqn stack |
532 | lua_pushnil( L); // ... {_i} {bfc} nil | 540 | lua_pushnil( L); // ... {_i} {bfc} nil |
@@ -546,8 +554,9 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
546 | int const ctx_base = lua_gettop( L) + 1; | 554 | int const ctx_base = lua_gettop( L) + 1; |
547 | int const in_base = lua_absindex( L, _i); | 555 | int const in_base = lua_absindex( L, _i); |
548 | int const start_depth = name_ ? 1 : 0; | 556 | int const start_depth = name_ ? 1 : 0; |
557 | DEBUGSPEW_CODE( struct s_Universe* U = get_universe( L)); | ||
549 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL")); | 558 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL")); |
550 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | 559 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
551 | STACK_GROW( L, 3); | 560 | STACK_GROW( L, 3); |
552 | STACK_CHECK( L); | 561 | STACK_CHECK( L); |
553 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} | 562 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} |
@@ -588,19 +597,19 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
588 | (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); | 597 | (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); |
589 | } | 598 | } |
590 | STACK_END( L, 0); | 599 | STACK_END( L, 0); |
591 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | 600 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
592 | } | 601 | } |
593 | 602 | ||
594 | int call_on_state_create( lua_State* L, lua_State* from_, enum eLookupMode mode_) | 603 | void call_on_state_create( struct s_Universe* U, lua_State* L, lua_State* from_, enum eLookupMode mode_) |
595 | { | 604 | { |
596 | if( s_on_state_create_func != NULL) | 605 | if( U->on_state_create_func != NULL) |
597 | { | 606 | { |
598 | STACK_CHECK( L); | 607 | STACK_CHECK( L); |
599 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); | 608 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); |
600 | if( s_on_state_create_func != initialize_on_state_create) | 609 | if( U->on_state_create_func != (lua_CFunction) initialize_on_state_create) |
601 | { | 610 | { |
602 | // C function: recreate a closure in the new state, bypassing the lookup scheme | 611 | // C function: recreate a closure in the new state, bypassing the lookup scheme |
603 | lua_pushcfunction( L, s_on_state_create_func); | 612 | lua_pushcfunction( L, U->on_state_create_func); |
604 | } | 613 | } |
605 | else // Lua function located in the config table, copied when we opened "lanes.core" | 614 | else // Lua function located in the config table, copied when we opened "lanes.core" |
606 | { | 615 | { |
@@ -608,24 +617,22 @@ int call_on_state_create( lua_State* L, lua_State* from_, enum eLookupMode mode_ | |||
608 | { | 617 | { |
609 | // if attempting to call in a keeper state, do nothing because the function doesn't exist there | 618 | // if attempting to call in a keeper state, do nothing because the function doesn't exist there |
610 | // this doesn't count as an error though | 619 | // this doesn't count as an error though |
611 | return 0; | 620 | return; |
612 | } | 621 | } |
613 | lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); | 622 | lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); |
614 | lua_getfield( L, -1, "on_state_create"); | 623 | lua_getfield( L, -1, "on_state_create"); |
615 | lua_remove( L, -2); | 624 | lua_remove( L, -2); |
616 | } | 625 | } |
617 | // capture error and forward it to main state | 626 | // capture error and raise it in caller state |
618 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) | 627 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) |
619 | { | 628 | { |
620 | lua_pushfstring( from_, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); | 629 | luaL_error( from_, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); |
621 | return 1; | ||
622 | } | 630 | } |
623 | STACK_END( L, 0); | 631 | STACK_END( L, 0); |
624 | } | 632 | } |
625 | return 0; | ||
626 | } | 633 | } |
627 | 634 | ||
628 | /* | 635 | /* |
629 | * Like 'luaL_openlibs()' but allows the set of libraries be selected | 636 | * Like 'luaL_openlibs()' but allows the set of libraries be selected |
630 | * | 637 | * |
631 | * NULL no libraries, not even base | 638 | * NULL no libraries, not even base |
@@ -638,7 +645,7 @@ int call_on_state_create( lua_State* L, lua_State* from_, enum eLookupMode mode_ | |||
638 | * *NOT* called for keeper states! | 645 | * *NOT* called for keeper states! |
639 | * | 646 | * |
640 | */ | 647 | */ |
641 | lua_State* luaG_newstate( lua_State* from_, char const* libs_) | 648 | lua_State* luaG_newstate( struct s_Universe* U, lua_State* from_, char const* libs_) |
642 | { | 649 | { |
643 | // re-use alloc function from the originating state | 650 | // re-use alloc function from the originating state |
644 | #if PROPAGATE_ALLOCF | 651 | #if PROPAGATE_ALLOCF |
@@ -651,22 +658,30 @@ lua_State* luaG_newstate( lua_State* from_, char const* libs_) | |||
651 | (void) luaL_error( from_, "luaG_newstate() failed while creating state; out of memory"); | 658 | (void) luaL_error( from_, "luaG_newstate() failed while creating state; out of memory"); |
652 | } | 659 | } |
653 | 660 | ||
661 | STACK_GROW( L, 2); | ||
662 | STACK_CHECK( L); | ||
663 | |||
664 | // copy the universe as a light userdata (only the master state holds the full userdata) | ||
665 | // that way, if Lanes is required in this new state, we'll know we are part of this universe | ||
666 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); | ||
667 | lua_pushlightuserdata( L, U); | ||
668 | lua_rawset( L, LUA_REGISTRYINDEX); | ||
669 | STACK_MID( L, 0); | ||
670 | |||
654 | // we'll need this every time we transfer some C function from/to this state | 671 | // we'll need this every time we transfer some C function from/to this state |
655 | lua_newtable( L); | 672 | lua_newtable( L); |
656 | lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); | 673 | lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); |
657 | 674 | ||
658 | // neither libs (not even 'base') nor special init func: we are done | 675 | // neither libs (not even 'base') nor special init func: we are done |
659 | if( libs_ == NULL && s_on_state_create_func == NULL) | 676 | if( libs_ == NULL && U->on_state_create_func == NULL) |
660 | { | 677 | { |
661 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END)); | 678 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate(NULL)\n" INDENT_END)); |
662 | return L; | 679 | return L; |
663 | } | 680 | } |
664 | 681 | ||
665 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); | 682 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); |
666 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | 683 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
667 | 684 | ||
668 | STACK_GROW( L, 2); | ||
669 | STACK_CHECK( L); | ||
670 | // 'lua.c' stops GC during initialization so perhaps its a good idea. :) | 685 | // 'lua.c' stops GC during initialization so perhaps its a good idea. :) |
671 | lua_gc( L, LUA_GCSTOP, 0); | 686 | lua_gc( L, LUA_GCSTOP, 0); |
672 | 687 | ||
@@ -681,7 +696,7 @@ lua_State* luaG_newstate( lua_State* from_, char const* libs_) | |||
681 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); | 696 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); |
682 | luaL_openlibs( L); | 697 | luaL_openlibs( L); |
683 | // don't forget lanes.core for regular lane states | 698 | // don't forget lanes.core for regular lane states |
684 | open1lib( L, "lanes.core", 10, from_); | 699 | open1lib( U, L, "lanes.core", 10, from_); |
685 | libs_ = NULL; // done with libs | 700 | libs_ = NULL; // done with libs |
686 | } | 701 | } |
687 | else | 702 | else |
@@ -715,19 +730,16 @@ lua_State* luaG_newstate( lua_State* from_, char const* libs_) | |||
715 | while( isalnum( p[len]) || p[len] == '.') | 730 | while( isalnum( p[len]) || p[len] == '.') |
716 | ++ len; | 731 | ++ len; |
717 | // open library | 732 | // open library |
718 | open1lib( L, p, len, from_); | 733 | open1lib( U, L, p, len, from_); |
719 | } | 734 | } |
720 | serialize_require( L); | ||
721 | } | 735 | } |
722 | |||
723 | lua_gc( L, LUA_GCRESTART, 0); | 736 | lua_gc( L, LUA_GCRESTART, 0); |
724 | 737 | ||
738 | serialize_require( L); | ||
739 | |||
725 | // call this after the base libraries are loaded and GC is restarted | 740 | // call this after the base libraries are loaded and GC is restarted |
726 | if( call_on_state_create( L, from_, eLM_LaneBody)) | 741 | // will raise an error in from_ in case of problem |
727 | { | 742 | call_on_state_create( U, L, from_, eLM_LaneBody); |
728 | // if something went wrong, the error message is pushed on the stack | ||
729 | lua_error( from_); | ||
730 | } | ||
731 | 743 | ||
732 | STACK_CHECK( L); | 744 | STACK_CHECK( L); |
733 | // after all this, register everything we find in our name<->function database | 745 | // after all this, register everything we find in our name<->function database |
@@ -735,7 +747,7 @@ lua_State* luaG_newstate( lua_State* from_, char const* libs_) | |||
735 | populate_func_lookup_table( L, -1, NULL); | 747 | populate_func_lookup_table( L, -1, NULL); |
736 | lua_pop( L, 1); | 748 | lua_pop( L, 1); |
737 | STACK_END( L, 0); | 749 | STACK_END( L, 0); |
738 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | 750 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
739 | return L; | 751 | return L; |
740 | } | 752 | } |
741 | 753 | ||
@@ -845,6 +857,16 @@ static inline luaG_IdFunction get_idfunc( lua_State* L, int index, enum eLookupM | |||
845 | } | 857 | } |
846 | 858 | ||
847 | 859 | ||
860 | void free_deep_prelude( lua_State* L, DEEP_PRELUDE* prelude_) | ||
861 | { | ||
862 | // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup | ||
863 | lua_pushlightuserdata( L, prelude_->deep); | ||
864 | ASSERT_L( prelude_->idfunc); | ||
865 | prelude_->idfunc( L, eDO_delete); | ||
866 | DEEP_FREE( (void*) prelude_); | ||
867 | } | ||
868 | |||
869 | |||
848 | /* | 870 | /* |
849 | * void= mt.__gc( proxy_ud ) | 871 | * void= mt.__gc( proxy_ud ) |
850 | * | 872 | * |
@@ -855,23 +877,20 @@ static int deep_userdata_gc( lua_State* L) | |||
855 | { | 877 | { |
856 | DEEP_PRELUDE** proxy = (DEEP_PRELUDE**) lua_touserdata( L, 1); | 878 | DEEP_PRELUDE** proxy = (DEEP_PRELUDE**) lua_touserdata( L, 1); |
857 | DEEP_PRELUDE* p = *proxy; | 879 | DEEP_PRELUDE* p = *proxy; |
880 | struct s_Universe* U = get_universe( L); | ||
858 | int v; | 881 | int v; |
859 | 882 | ||
860 | *proxy = 0; // make sure we don't use it any more | 883 | *proxy = 0; // make sure we don't use it any more |
861 | 884 | ||
862 | MUTEX_LOCK( &deep_lock); | 885 | MUTEX_LOCK( &U->deep_lock); |
863 | v = -- (p->refcount); | 886 | v = -- (p->refcount); |
864 | MUTEX_UNLOCK( &deep_lock); | 887 | MUTEX_UNLOCK( &U->deep_lock); |
865 | 888 | ||
866 | if( v == 0) | 889 | if( v == 0) |
867 | { | 890 | { |
868 | // clean stack so we can call 'idfunc' directly | 891 | // 'idfunc' expects a clean stack to work on |
869 | lua_settop( L, 0); | 892 | lua_settop( L, 0); |
870 | // Call 'idfunc( "delete", deep_ptr )' to make deep cleanup | 893 | free_deep_prelude( L, p); |
871 | lua_pushlightuserdata( L, p->deep); | ||
872 | ASSERT_L( p->idfunc); | ||
873 | p->idfunc( L, eDO_delete); | ||
874 | DEEP_FREE( (void*) p); | ||
875 | 894 | ||
876 | // top was set to 0, then userdata was pushed. "delete" might want to pop the userdata (we don't care), but should not push anything! | 895 | // top was set to 0, then userdata was pushed. "delete" might want to pop the userdata (we don't care), but should not push anything! |
877 | if ( lua_gettop( L) > 1) | 896 | if ( lua_gettop( L) > 1) |
@@ -892,7 +911,7 @@ static int deep_userdata_gc( lua_State* L) | |||
892 | * used in this Lua state (metatable, registring it). Otherwise, increments the | 911 | * used in this Lua state (metatable, registring it). Otherwise, increments the |
893 | * reference count. | 912 | * reference count. |
894 | */ | 913 | */ |
895 | char const* push_deep_proxy( lua_State* L, DEEP_PRELUDE* prelude, enum eLookupMode mode_) | 914 | char const* push_deep_proxy( struct s_Universe* U, lua_State* L, DEEP_PRELUDE* prelude, enum eLookupMode mode_) |
896 | { | 915 | { |
897 | DEEP_PRELUDE** proxy; | 916 | DEEP_PRELUDE** proxy; |
898 | 917 | ||
@@ -910,9 +929,9 @@ char const* push_deep_proxy( lua_State* L, DEEP_PRELUDE* prelude, enum eLookupMo | |||
910 | lua_pop( L, 1); // DPC | 929 | lua_pop( L, 1); // DPC |
911 | } | 930 | } |
912 | 931 | ||
913 | MUTEX_LOCK( &deep_lock); | 932 | MUTEX_LOCK( &U->deep_lock); |
914 | ++ (prelude->refcount); // one more proxy pointing to this deep data | 933 | ++ (prelude->refcount); // one more proxy pointing to this deep data |
915 | MUTEX_UNLOCK( &deep_lock); | 934 | MUTEX_UNLOCK( &U->deep_lock); |
916 | 935 | ||
917 | STACK_GROW( L, 7); | 936 | STACK_GROW( L, 7); |
918 | STACK_CHECK( L); | 937 | STACK_CHECK( L); |
@@ -1048,9 +1067,9 @@ char const* push_deep_proxy( lua_State* L, DEEP_PRELUDE* prelude, enum eLookupMo | |||
1048 | * | 1067 | * |
1049 | * 'idfunc' must fulfill the following features: | 1068 | * 'idfunc' must fulfill the following features: |
1050 | * | 1069 | * |
1051 | * lightuserdata= idfunc( "new" [, ...] ) -- creates a new deep data instance | 1070 | * lightuserdata = idfunc( eDO_new [, ...] ) -- creates a new deep data instance |
1052 | * void= idfunc( "delete", lightuserdata ) -- releases a deep data instance | 1071 | * void = idfunc( eDO_delete, lightuserdata ) -- releases a deep data instance |
1053 | * tbl= idfunc( "metatable" ) -- gives metatable for userdata proxies | 1072 | * tbl = idfunc( eDO_metatable ) -- gives metatable for userdata proxies |
1054 | * | 1073 | * |
1055 | * Reference counting and true userdata proxying are taken care of for the | 1074 | * Reference counting and true userdata proxying are taken care of for the |
1056 | * actual data type. | 1075 | * actual data type. |
@@ -1064,7 +1083,10 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) | |||
1064 | { | 1083 | { |
1065 | char const* errmsg; | 1084 | char const* errmsg; |
1066 | DEEP_PRELUDE* prelude = DEEP_MALLOC( sizeof(DEEP_PRELUDE)); | 1085 | DEEP_PRELUDE* prelude = DEEP_MALLOC( sizeof(DEEP_PRELUDE)); |
1067 | ASSERT_L( prelude); | 1086 | if( prelude == NULL) |
1087 | { | ||
1088 | return luaL_error( L, "couldn't not allocate deep prelude: out of memory"); | ||
1089 | } | ||
1068 | 1090 | ||
1069 | prelude->refcount = 0; // 'push_deep_proxy' will lift it to 1 | 1091 | prelude->refcount = 0; // 'push_deep_proxy' will lift it to 1 |
1070 | prelude->idfunc = idfunc; | 1092 | prelude->idfunc = idfunc; |
@@ -1084,7 +1106,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) | |||
1084 | luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); | 1106 | luaL_error( L, "Bad idfunc(eDO_new): should not push anything on the stack"); |
1085 | } | 1107 | } |
1086 | } | 1108 | } |
1087 | errmsg = push_deep_proxy( L, prelude, eLM_LaneBody); // proxy | 1109 | errmsg = push_deep_proxy( get_universe( L), L, prelude, eLM_LaneBody); // proxy |
1088 | if( errmsg != NULL) | 1110 | if( errmsg != NULL) |
1089 | { | 1111 | { |
1090 | luaL_error( L, errmsg); | 1112 | luaL_error( L, errmsg); |
@@ -1125,7 +1147,7 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) | |||
1125 | * the id function of the copied value, or NULL for non-deep userdata | 1147 | * the id function of the copied value, or NULL for non-deep userdata |
1126 | * (not copied) | 1148 | * (not copied) |
1127 | */ | 1149 | */ |
1128 | static luaG_IdFunction copydeep( lua_State* L, lua_State* L2, int index, enum eLookupMode mode_) | 1150 | static luaG_IdFunction copydeep( struct s_Universe* U, lua_State* L, lua_State* L2, int index, enum eLookupMode mode_) |
1129 | { | 1151 | { |
1130 | char const* errmsg; | 1152 | char const* errmsg; |
1131 | luaG_IdFunction idfunc = get_idfunc( L, index, mode_); | 1153 | luaG_IdFunction idfunc = get_idfunc( L, index, mode_); |
@@ -1134,7 +1156,7 @@ static luaG_IdFunction copydeep( lua_State* L, lua_State* L2, int index, enum eL | |||
1134 | return NULL; // not a deep userdata | 1156 | return NULL; // not a deep userdata |
1135 | } | 1157 | } |
1136 | 1158 | ||
1137 | errmsg = push_deep_proxy( L2, *(DEEP_PRELUDE**) lua_touserdata( L, index), mode_); | 1159 | errmsg = push_deep_proxy( U, L2, *(DEEP_PRELUDE**) lua_touserdata( L, index), mode_); |
1138 | if( errmsg != NULL) | 1160 | if( errmsg != NULL) |
1139 | { | 1161 | { |
1140 | // raise the error in the proper state (not the keeper) | 1162 | // raise the error in the proper state (not the keeper) |
@@ -1207,47 +1229,47 @@ static inline void push_registry_subtable( lua_State* L, void* key_) | |||
1207 | /* | 1229 | /* |
1208 | * Get a unique ID for metatable at [i]. | 1230 | * Get a unique ID for metatable at [i]. |
1209 | */ | 1231 | */ |
1210 | static | 1232 | static uint_t get_mt_id( struct s_Universe* U, lua_State* L, int i) |
1211 | uint_t get_mt_id( lua_State *L, int i ) { | 1233 | { |
1212 | static uint_t last_id= 0; | 1234 | uint_t id; |
1213 | uint_t id; | 1235 | |
1214 | 1236 | i = lua_absindex( L, i); | |
1215 | i = lua_absindex( L, i); | 1237 | |
1216 | 1238 | STACK_GROW( L, 3); | |
1217 | STACK_GROW(L,3); | 1239 | |
1218 | 1240 | STACK_CHECK( L); | |
1219 | STACK_CHECK( L); | 1241 | push_registry_subtable( L, REG_MTID); |
1220 | push_registry_subtable( L, REG_MTID ); | 1242 | lua_pushvalue( L, i); |
1221 | lua_pushvalue(L, i); | 1243 | lua_rawget( L, -2); |
1222 | lua_rawget( L, -2 ); | 1244 | // |
1223 | // | 1245 | // [-2]: reg[REG_MTID] |
1224 | // [-2]: reg[REG_MTID] | 1246 | // [-1]: nil/uint |
1225 | // [-1]: nil/uint | 1247 | |
1226 | 1248 | id = (uint_t) lua_tointeger( L, -1); // 0 for nil | |
1227 | id= (uint_t)lua_tointeger(L,-1); // 0 for nil | 1249 | lua_pop( L, 1); |
1228 | lua_pop(L,1); | 1250 | STACK_MID( L, 1); |
1229 | STACK_MID( L, 1); | 1251 | |
1230 | 1252 | if( id == 0) | |
1231 | if (id==0) { | 1253 | { |
1232 | MUTEX_LOCK( &mtid_lock ); | 1254 | MUTEX_LOCK( &U->mtid_lock); |
1233 | id= ++last_id; | 1255 | id = ++ U->last_mt_id; |
1234 | MUTEX_UNLOCK( &mtid_lock ); | 1256 | MUTEX_UNLOCK( &U->mtid_lock); |
1235 | 1257 | ||
1236 | /* Create two-way references: id_uint <-> table | 1258 | /* Create two-way references: id_uint <-> table |
1237 | */ | 1259 | */ |
1238 | lua_pushvalue(L,i); | 1260 | lua_pushvalue( L, i); |
1239 | lua_pushinteger(L,id); | 1261 | lua_pushinteger( L, id); |
1240 | lua_rawset( L, -3 ); | 1262 | lua_rawset( L, -3); |
1241 | 1263 | ||
1242 | lua_pushinteger(L,id); | 1264 | lua_pushinteger( L, id); |
1243 | lua_pushvalue(L,i); | 1265 | lua_pushvalue( L, i); |
1244 | lua_rawset( L, -3 ); | 1266 | lua_rawset( L, -3); |
1245 | } | 1267 | } |
1246 | lua_pop(L,1); // remove 'reg[REG_MTID]' reference | 1268 | lua_pop( L, 1); // remove 'reg[REG_MTID]' reference |
1247 | 1269 | ||
1248 | STACK_END( L, 0); | 1270 | STACK_END( L, 0); |
1249 | 1271 | ||
1250 | return id; | 1272 | return id; |
1251 | } | 1273 | } |
1252 | 1274 | ||
1253 | 1275 | ||
@@ -1518,7 +1540,7 @@ static int sentinelfunc( lua_State* L) | |||
1518 | /* | 1540 | /* |
1519 | * Push a looked-up native/LuaJIT function. | 1541 | * Push a looked-up native/LuaJIT function. |
1520 | */ | 1542 | */ |
1521 | static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) | 1543 | static void lookup_native_func( struct s_Universe* U, lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) |
1522 | { | 1544 | { |
1523 | char const* fqn; // L // L2 | 1545 | char const* fqn; // L // L2 |
1524 | size_t len; | 1546 | size_t len; |
@@ -1576,14 +1598,20 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLoo | |||
1576 | // push the equivalent function in the destination's stack, retrieved from the lookup table | 1598 | // push the equivalent function in the destination's stack, retrieved from the lookup table |
1577 | STACK_CHECK( L2); | 1599 | STACK_CHECK( L2); |
1578 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error | 1600 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error |
1579 | if( mode_ == eLM_ToKeeper) | 1601 | switch( mode_) |
1580 | { | 1602 | { |
1603 | default: // shouldn't happen, in theory... | ||
1604 | (void) luaL_error( L, "internal error: unknown lookup mode"); | ||
1605 | return; | ||
1606 | |||
1607 | case eLM_ToKeeper: | ||
1581 | // push a sentinel closure that holds the lookup name as upvalue | 1608 | // push a sentinel closure that holds the lookup name as upvalue |
1582 | lua_pushlstring( L2, fqn, len); // "f.q.n" | 1609 | lua_pushlstring( L2, fqn, len); // "f.q.n" |
1583 | lua_pushcclosure( L2, sentinelfunc, 1); // f | 1610 | lua_pushcclosure( L2, sentinelfunc, 1); // f |
1584 | } | 1611 | break; |
1585 | else | 1612 | |
1586 | { | 1613 | case eLM_LaneBody: |
1614 | case eLM_FromKeeper: | ||
1587 | lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} | 1615 | lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} |
1588 | ASSERT_L( lua_istable( L2, -1)); | 1616 | ASSERT_L( lua_istable( L2, -1)); |
1589 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" | 1617 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" |
@@ -1600,6 +1628,23 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLoo | |||
1600 | return; | 1628 | return; |
1601 | } | 1629 | } |
1602 | lua_remove( L2, -2); // f | 1630 | lua_remove( L2, -2); // f |
1631 | break; | ||
1632 | |||
1633 | /* keep it in case I need it someday, who knows... | ||
1634 | case eLM_RawFunctions: | ||
1635 | { | ||
1636 | int n; | ||
1637 | char const* upname; | ||
1638 | lua_CFunction f = lua_tocfunction( L, i); | ||
1639 | // copy upvalues | ||
1640 | for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n) | ||
1641 | { | ||
1642 | luaG_inter_move( U, L, L2, 1, mode_); // [up[,up ...]] | ||
1643 | } | ||
1644 | lua_pushcclosure( L2, f, n); // | ||
1645 | } | ||
1646 | break; | ||
1647 | */ | ||
1603 | } | 1648 | } |
1604 | STACK_END( L2, 1); | 1649 | STACK_END( L2, 1); |
1605 | } | 1650 | } |
@@ -1608,12 +1653,15 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLoo | |||
1608 | * Copy a function over, which has not been found in the cache. | 1653 | * Copy a function over, which has not been found in the cache. |
1609 | * L2 has the cache key for this function at the top of the stack | 1654 | * L2 has the cache key for this function at the top of the stack |
1610 | */ | 1655 | */ |
1611 | enum e_vt { | 1656 | enum e_vt |
1612 | VT_NORMAL, VT_KEY, VT_METATABLE | 1657 | { |
1658 | VT_NORMAL, | ||
1659 | VT_KEY, | ||
1660 | VT_METATABLE | ||
1613 | }; | 1661 | }; |
1614 | static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt value_type, enum eLookupMode mode_, char const* upName_); | 1662 | static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt value_type, enum eLookupMode mode_, char const* upName_); |
1615 | 1663 | ||
1616 | static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) | 1664 | static void inter_copy_func( struct s_Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) |
1617 | { | 1665 | { |
1618 | int n, needToPush; | 1666 | int n, needToPush; |
1619 | luaL_Buffer b; | 1667 | luaL_Buffer b; |
@@ -1722,7 +1770,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1722 | #endif // LUA_VERSION_NUM | 1770 | #endif // LUA_VERSION_NUM |
1723 | { | 1771 | { |
1724 | DEBUGSPEW_CODE( fprintf( stderr, "copying value\n")); | 1772 | DEBUGSPEW_CODE( fprintf( stderr, "copying value\n")); |
1725 | if( !inter_copy_one_( L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, mode_, upname)) // ... {cache} ... function <upvalues> | 1773 | if( !inter_copy_one_( U, L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, mode_, upname)) // ... {cache} ... function <upvalues> |
1726 | { | 1774 | { |
1727 | luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1)); | 1775 | luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1)); |
1728 | } | 1776 | } |
@@ -1742,7 +1790,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1742 | int func_index = lua_gettop( L2) - n; | 1790 | int func_index = lua_gettop( L2) - n; |
1743 | for( ; n > 0; -- n) | 1791 | for( ; n > 0; -- n) |
1744 | { | 1792 | { |
1745 | char const* rc = lua_setupvalue( L2, func_index, n); // ... {cache} ... function | 1793 | char const* rc = lua_setupvalue( L2, func_index, n); // ... {cache} ... function |
1746 | // | 1794 | // |
1747 | // "assigns the value at the top of the stack to the upvalue and returns its name. | 1795 | // "assigns the value at the top of the stack to the upvalue and returns its name. |
1748 | // It also pops the value from the stack." | 1796 | // It also pops the value from the stack." |
@@ -1750,7 +1798,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1750 | ASSERT_L( rc); // not having enough slots? | 1798 | ASSERT_L( rc); // not having enough slots? |
1751 | } | 1799 | } |
1752 | // once all upvalues have been set we are left | 1800 | // once all upvalues have been set we are left |
1753 | // with the function at the top of the stack // ... {cache} ... function | 1801 | // with the function at the top of the stack // ... {cache} ... function |
1754 | } | 1802 | } |
1755 | } | 1803 | } |
1756 | STACK_END( L, 0); | 1804 | STACK_END( L, 0); |
@@ -1762,7 +1810,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin | |||
1762 | * | 1810 | * |
1763 | * Always pushes a function to 'L2'. | 1811 | * Always pushes a function to 'L2'. |
1764 | */ | 1812 | */ |
1765 | static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) | 1813 | static void push_cached_func( struct s_Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) |
1766 | { | 1814 | { |
1767 | FuncSubType funcSubType; | 1815 | FuncSubType funcSubType; |
1768 | /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions | 1816 | /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions |
@@ -1798,7 +1846,7 @@ static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, ui | |||
1798 | // via upvalues | 1846 | // via upvalues |
1799 | // | 1847 | // |
1800 | // pushes a copy of the func, stores a reference in the cache | 1848 | // pushes a copy of the func, stores a reference in the cache |
1801 | inter_copy_func( L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function | 1849 | inter_copy_func( U, L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function |
1802 | } | 1850 | } |
1803 | else // found function in the cache | 1851 | else // found function in the cache |
1804 | { | 1852 | { |
@@ -1808,7 +1856,7 @@ static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, ui | |||
1808 | } | 1856 | } |
1809 | else // function is native/LuaJIT: no need to cache | 1857 | else // function is native/LuaJIT: no need to cache |
1810 | { | 1858 | { |
1811 | lookup_native_func( L2, L, i, mode_, upName_); // ... {cache} ... function | 1859 | lookup_native_func( U, L2, L, i, mode_, upName_); // ... {cache} ... function |
1812 | } | 1860 | } |
1813 | 1861 | ||
1814 | // | 1862 | // |
@@ -1826,7 +1874,7 @@ static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, ui | |||
1826 | * | 1874 | * |
1827 | * Returns TRUE if value was pushed, FALSE if its type is non-supported. | 1875 | * Returns TRUE if value was pushed, FALSE if its type is non-supported. |
1828 | */ | 1876 | */ |
1829 | static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, enum eLookupMode mode_, char const* upName_) | 1877 | static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, enum eLookupMode mode_, char const* upName_) |
1830 | { | 1878 | { |
1831 | bool_t ret = TRUE; | 1879 | bool_t ret = TRUE; |
1832 | STACK_GROW( L2, 1); | 1880 | STACK_GROW( L2, 1); |
@@ -1884,7 +1932,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u | |||
1884 | /* Allow only deep userdata entities to be copied across | 1932 | /* Allow only deep userdata entities to be copied across |
1885 | */ | 1933 | */ |
1886 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "USERDATA\n" INDENT_END)); | 1934 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "USERDATA\n" INDENT_END)); |
1887 | if( !copydeep( L, L2, i, mode_)) | 1935 | if( !copydeep( U, L, L2, i, mode_)) |
1888 | { | 1936 | { |
1889 | // Not a deep full userdata | 1937 | // Not a deep full userdata |
1890 | bool_t demote = FALSE; | 1938 | bool_t demote = FALSE; |
@@ -1928,11 +1976,11 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u | |||
1928 | } | 1976 | } |
1929 | { | 1977 | { |
1930 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "FUNCTION %s\n" INDENT_END, upName_)); | 1978 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "FUNCTION %s\n" INDENT_END, upName_)); |
1931 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | 1979 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
1932 | STACK_CHECK( L2); | 1980 | STACK_CHECK( L2); |
1933 | push_cached_func( L2, L2_cache_i, L, i, mode_, upName_); | 1981 | push_cached_func( U, L2, L2_cache_i, L, i, mode_, upName_); |
1934 | STACK_END( L2, 1); | 1982 | STACK_END( L2, 1); |
1935 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | 1983 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1936 | } | 1984 | } |
1937 | break; | 1985 | break; |
1938 | 1986 | ||
@@ -1973,10 +2021,10 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u | |||
1973 | 2021 | ||
1974 | /* Only basic key types are copied over; others ignored | 2022 | /* Only basic key types are copied over; others ignored |
1975 | */ | 2023 | */ |
1976 | if( inter_copy_one_( L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_)) | 2024 | if( inter_copy_one_( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_)) |
1977 | { | 2025 | { |
1978 | char* valPath = (char*) upName_; | 2026 | char* valPath = (char*) upName_; |
1979 | if( GVerboseErrors) | 2027 | if( U->verboseErrors) |
1980 | { | 2028 | { |
1981 | // for debug purposes, let's try to build a useful name | 2029 | // for debug purposes, let's try to build a useful name |
1982 | if( lua_type( L, key_i) == LUA_TSTRING) | 2030 | if( lua_type( L, key_i) == LUA_TSTRING) |
@@ -1994,7 +2042,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u | |||
1994 | * Contents of metatables are copied with cache checking; | 2042 | * Contents of metatables are copied with cache checking; |
1995 | * important to detect loops. | 2043 | * important to detect loops. |
1996 | */ | 2044 | */ |
1997 | if( inter_copy_one_( L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath)) | 2045 | if( inter_copy_one_( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath)) |
1998 | { | 2046 | { |
1999 | ASSERT_L( lua_istable( L2, -3)); | 2047 | ASSERT_L( lua_istable( L2, -3)); |
2000 | lua_rawset( L2, -3); // add to table (pops key & val) | 2048 | lua_rawset( L2, -3); // add to table (pops key & val) |
@@ -2016,7 +2064,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u | |||
2016 | // | 2064 | // |
2017 | // L [-1]: metatable | 2065 | // L [-1]: metatable |
2018 | 2066 | ||
2019 | uint_t mt_id = get_mt_id( L, -1); // Unique id for the metatable | 2067 | uint_t mt_id = get_mt_id( U, L, -1); // Unique id for the metatable |
2020 | 2068 | ||
2021 | STACK_GROW( L2, 4); | 2069 | STACK_GROW( L2, 4); |
2022 | 2070 | ||
@@ -2036,7 +2084,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u | |||
2036 | lua_pop( L2, 1); | 2084 | lua_pop( L2, 1); |
2037 | STACK_MID( L2, 2); | 2085 | STACK_MID( L2, 2); |
2038 | ASSERT_L( lua_istable(L,-1)); | 2086 | ASSERT_L( lua_istable(L,-1)); |
2039 | if( inter_copy_one_( L2, L2_cache_i /*for function cacheing*/, L, lua_gettop(L) /*[-1]*/, VT_METATABLE, mode_, upName_)) | 2087 | if( inter_copy_one_( U, L2, L2_cache_i /*for function cacheing*/, L, lua_gettop(L) /*[-1]*/, VT_METATABLE, mode_, upName_)) |
2040 | { | 2088 | { |
2041 | // | 2089 | // |
2042 | // L2 ([-3]: copied table) | 2090 | // L2 ([-3]: copied table) |
@@ -2103,13 +2151,13 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u | |||
2103 | * | 2151 | * |
2104 | * Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'. | 2152 | * Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'. |
2105 | */ | 2153 | */ |
2106 | int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_) | 2154 | int luaG_inter_copy( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_) |
2107 | { | 2155 | { |
2108 | uint_t top_L = lua_gettop( L); | 2156 | uint_t top_L = lua_gettop( L); |
2109 | uint_t top_L2 = lua_gettop( L2); | 2157 | uint_t top_L2 = lua_gettop( L2); |
2110 | uint_t i, j; | 2158 | uint_t i, j; |
2111 | char tmpBuf[16]; | 2159 | char tmpBuf[16]; |
2112 | char* pBuf = GVerboseErrors ? tmpBuf : "?"; | 2160 | char* pBuf = U->verboseErrors ? tmpBuf : "?"; |
2113 | bool_t copyok = TRUE; | 2161 | bool_t copyok = TRUE; |
2114 | 2162 | ||
2115 | if( n > top_L) | 2163 | if( n > top_L) |
@@ -2129,11 +2177,11 @@ int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mod | |||
2129 | 2177 | ||
2130 | for( i = top_L - n + 1, j = 1; i <= top_L; ++ i, ++ j) | 2178 | for( i = top_L - n + 1, j = 1; i <= top_L; ++ i, ++ j) |
2131 | { | 2179 | { |
2132 | if( GVerboseErrors) | 2180 | if( U->verboseErrors) |
2133 | { | 2181 | { |
2134 | sprintf( tmpBuf, "arg_%d", j); | 2182 | sprintf( tmpBuf, "arg_%d", j); |
2135 | } | 2183 | } |
2136 | copyok = inter_copy_one_( L2, top_L2 + 1, L, i, VT_NORMAL, mode_, pBuf); | 2184 | copyok = inter_copy_one_( U, L2, top_L2 + 1, L, i, VT_NORMAL, mode_, pBuf); |
2137 | if( !copyok) | 2185 | if( !copyok) |
2138 | { | 2186 | { |
2139 | break; | 2187 | break; |
@@ -2161,17 +2209,17 @@ int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mod | |||
2161 | } | 2209 | } |
2162 | 2210 | ||
2163 | 2211 | ||
2164 | int luaG_inter_move( lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_) | 2212 | int luaG_inter_move( struct s_Universe* U, lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_) |
2165 | { | 2213 | { |
2166 | int ret = luaG_inter_copy( L, L2, n, mode_); | 2214 | int ret = luaG_inter_copy( U, L, L2, n, mode_); |
2167 | lua_pop( L, (int) n); | 2215 | lua_pop( L, (int) n); |
2168 | return ret; | 2216 | return ret; |
2169 | } | 2217 | } |
2170 | 2218 | ||
2171 | int luaG_inter_copy_package( lua_State* L, lua_State* L2, int package_idx_, enum eLookupMode mode_) | 2219 | int luaG_inter_copy_package( struct s_Universe* U, lua_State* L, lua_State* L2, int package_idx_, enum eLookupMode mode_) |
2172 | { | 2220 | { |
2173 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); | 2221 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); |
2174 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | 2222 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
2175 | // package | 2223 | // package |
2176 | STACK_CHECK( L); | 2224 | STACK_CHECK( L); |
2177 | STACK_CHECK( L2); | 2225 | STACK_CHECK( L2); |
@@ -2202,9 +2250,9 @@ int luaG_inter_copy_package( lua_State* L, lua_State* L2, int package_idx_, enum | |||
2202 | } | 2250 | } |
2203 | else | 2251 | else |
2204 | { | 2252 | { |
2205 | DEBUGSPEW_CODE( ++ debugspew_indent_depth); | 2253 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
2206 | luaG_inter_move( L, L2, 1, mode_); // moves the entry to L2 | 2254 | luaG_inter_move( U, L, L2, 1, mode_); // moves the entry to L2 |
2207 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | 2255 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
2208 | lua_setfield( L2, -2, entries[i]); // set package[entries[i]] | 2256 | lua_setfield( L2, -2, entries[i]); // set package[entries[i]] |
2209 | } | 2257 | } |
2210 | } | 2258 | } |
@@ -2216,7 +2264,7 @@ int luaG_inter_copy_package( lua_State* L, lua_State* L2, int package_idx_, enum | |||
2216 | lua_pop( L2, 1); | 2264 | lua_pop( L2, 1); |
2217 | STACK_END( L2, 0); | 2265 | STACK_END( L2, 0); |
2218 | STACK_END( L, 0); | 2266 | STACK_END( L, 0); |
2219 | DEBUGSPEW_CODE( -- debugspew_indent_depth); | 2267 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
2220 | return 0; | 2268 | return 0; |
2221 | } | 2269 | } |
2222 | 2270 | ||
@@ -2224,8 +2272,6 @@ int luaG_inter_copy_package( lua_State* L, lua_State* L2, int package_idx_, enum | |||
2224 | /*---=== Serialize require ===--- | 2272 | /*---=== Serialize require ===--- |
2225 | */ | 2273 | */ |
2226 | 2274 | ||
2227 | MUTEX_T require_cs; | ||
2228 | |||
2229 | //--- | 2275 | //--- |
2230 | // [val]= new_require( ... ) | 2276 | // [val]= new_require( ... ) |
2231 | // | 2277 | // |
@@ -2237,12 +2283,13 @@ int luaG_new_require( lua_State* L) | |||
2237 | { | 2283 | { |
2238 | int rc, i; | 2284 | int rc, i; |
2239 | int args = lua_gettop( L); | 2285 | int args = lua_gettop( L); |
2286 | struct s_Universe* U = get_universe( L); | ||
2240 | //char const* modname = luaL_checkstring( L, 1); | 2287 | //char const* modname = luaL_checkstring( L, 1); |
2241 | 2288 | ||
2242 | STACK_GROW( L, args + 1); | 2289 | STACK_GROW( L, args + 1); |
2243 | STACK_CHECK( L); | 2290 | STACK_CHECK( L); |
2244 | 2291 | ||
2245 | lua_pushvalue( L, lua_upvalueindex(1)); | 2292 | lua_pushvalue( L, lua_upvalueindex( 1)); |
2246 | for( i = 1; i <= args; ++ i) | 2293 | for( i = 1; i <= args; ++ i) |
2247 | { | 2294 | { |
2248 | lua_pushvalue( L, i); | 2295 | lua_pushvalue( L, i); |
@@ -2251,9 +2298,9 @@ int luaG_new_require( lua_State* L) | |||
2251 | // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would | 2298 | // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would |
2252 | // leave us locked, blocking any future 'require' calls from other lanes. | 2299 | // leave us locked, blocking any future 'require' calls from other lanes. |
2253 | // | 2300 | // |
2254 | MUTEX_LOCK( &require_cs); | 2301 | MUTEX_LOCK( &U->require_cs); |
2255 | rc = lua_pcall( L, args, 1 /*retvals*/, 0 /*errfunc*/ ); | 2302 | rc = lua_pcall( L, args, 1 /*retvals*/, 0 /*errfunc*/ ); |
2256 | MUTEX_UNLOCK( &require_cs); | 2303 | MUTEX_UNLOCK( &U->require_cs); |
2257 | 2304 | ||
2258 | // the required module (or an error message) is left on the stack as returned value by original require function | 2305 | // the required module (or an error message) is left on the stack as returned value by original require function |
2259 | STACK_END( L, 1); | 2306 | STACK_END( L, 1); |