aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/keeper.c78
-rw-r--r--src/keeper.h11
-rw-r--r--src/lanes.c43
-rw-r--r--src/tools.c446
-rw-r--r--src/tools.h13
5 files changed, 258 insertions, 333 deletions
diff --git a/src/keeper.c b/src/keeper.c
index 4a5c913..8d9f7ec 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -51,7 +51,6 @@
51#include "tools.h" 51#include "tools.h"
52#include "keeper.h" 52#include "keeper.h"
53 53
54#if KEEPER_MODEL == KEEPER_MODEL_C
55//################################################################################### 54//###################################################################################
56// Keeper implementation 55// Keeper implementation
57//################################################################################### 56//###################################################################################
@@ -207,10 +206,10 @@ int keeper_push_linda_storage( lua_State* L, void* ptr)
207 { 206 {
208 keeper_fifo* fifo = prepare_fifo_access( KL, -1); // storage key fifo 207 keeper_fifo* fifo = prepare_fifo_access( KL, -1); // storage key fifo
209 lua_pushvalue( KL, -2); // storage key fifo key 208 lua_pushvalue( KL, -2); // storage key fifo key
210 luaG_inter_move( KL, L, 1); // storage key fifo // out key 209 luaG_inter_move( KL, L, 1, eLM_FromKeeper); // storage key fifo // out key
211 STACK_MID( L, 2); 210 STACK_MID( L, 2);
212 lua_newtable( L); // out key keyout 211 lua_newtable( L); // out key keyout
213 luaG_inter_move( KL, L, 1); // storage key // out key keyout fifo 212 luaG_inter_move( KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifo
214 lua_pushinteger( L, fifo->first); // out key keyout fifo first 213 lua_pushinteger( L, fifo->first); // out key keyout fifo first
215 STACK_MID( L, 5); 214 STACK_MID( L, 5);
216 lua_setfield( L, -3, "first"); // out key keyout fifo 215 lua_setfield( L, -3, "first"); // out key keyout fifo
@@ -512,7 +511,6 @@ int keepercall_count( lua_State* L)
512 } 511 }
513 return 1; 512 return 1;
514} 513}
515#endif // KEEPER_MODEL == KEEPER_MODEL_C
516 514
517//################################################################################### 515//###################################################################################
518// Keeper API, accessed from linda methods 516// Keeper API, accessed from linda methods
@@ -576,17 +574,11 @@ char const* init_keepers( lua_State* L, int _on_state_create, int const _nbKeepe
576 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 574 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
577 // We need to load all base libraries in the keeper states so that the transfer databases are populated properly 575 // We need to load all base libraries in the keeper states so that the transfer databases are populated properly
578 // 576 //
579 // 'io' for debugging messages, 'package' because we need to require modules exporting idfuncs 577 // we don't need any libs in the keeper states
580 // the others because they export functions that we may store in a keeper for transfer between lanes 578 K = luaG_newstate( L, _on_state_create, NULL);
581 K = luaG_newstate( L, _on_state_create, "K");
582 579
583 STACK_CHECK( K); 580 STACK_CHECK( K);
584 581
585 // replace default 'package' contents with stuff gotten from the master state
586 lua_getglobal( L, "package");
587 luaG_inter_copy_package( L, K, -1);
588 lua_pop( L, 1);
589
590 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "### init_keepers %d END\n" INDENT_END, i)); 582 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "### init_keepers %d END\n" INDENT_END, i));
591 DEBUGSPEW_CODE( -- debugspew_indent_depth); 583 DEBUGSPEW_CODE( -- debugspew_indent_depth);
592 584
@@ -596,32 +588,11 @@ char const* init_keepers( lua_State* L, int _on_state_create, int const _nbKeepe
596 lua_concat( K, 2); 588 lua_concat( K, 2);
597 lua_setglobal( K, "decoda_name"); 589 lua_setglobal( K, "decoda_name");
598 590
599#if KEEPER_MODEL == KEEPER_MODEL_C
600 // create the fifos table in the keeper state 591 // create the fifos table in the keeper state
601 lua_pushlightuserdata( K, fifos_key); 592 lua_pushlightuserdata( K, fifos_key);
602 lua_newtable( K); 593 lua_newtable( K);
603 lua_rawset( K, LUA_REGISTRYINDEX); 594 lua_rawset( K, LUA_REGISTRYINDEX);
604#endif // KEEPER_MODEL == KEEPER_MODEL_C 595
605
606#if KEEPER_MODEL == KEEPER_MODEL_LUA
607 // use package.loaders[2] to find keeper microcode (NOTE: this works only if nobody tampered with the loaders table...)
608 lua_getglobal( K, "package"); // package
609 lua_getfield( K, -1, "loaders"); // package package.loaders
610 lua_rawgeti( K, -1, 2); // package package.loaders package.loaders[2]
611 lua_pushliteral( K, "lanes-keeper"); // package package.loaders package.loaders[2] "lanes-keeper"
612 STACK_MID( K, 4);
613 // first pcall loads lanes-keeper.lua, second one runs the chunk
614 if( lua_pcall( K, 1 /*args*/, 1 /*results*/, 0 /*errfunc*/) || lua_pcall( K, 0 /*args*/, 0 /*results*/, 0 /*errfunc*/))
615 {
616 // LUA_ERRRUN / LUA_ERRMEM / LUA_ERRERR
617 //
618 char const* err = lua_tostring( K, -1);
619 assert( err);
620 return err;
621 } // package package.loaders
622 STACK_MID( K, 2);
623 lua_pop( K, 2);
624#endif // KEEPER_MODEL == KEEPER_MODEL_LUA
625 STACK_END( K, 0); 596 STACK_END( K, 0);
626 MUTEX_INIT( &GKeepers[i].lock_); 597 MUTEX_INIT( &GKeepers[i].lock_);
627 GKeepers[i].L = K; 598 GKeepers[i].L = K;
@@ -633,41 +604,6 @@ char const* init_keepers( lua_State* L, int _on_state_create, int const _nbKeepe
633 return NULL; // ok 604 return NULL; // ok
634} 605}
635 606
636// cause each keeper state to populate its database of transferable functions with those from the specified module
637// do do this we simply require the module inside the keeper state, then populate the lookup database
638void populate_keepers( lua_State* L)
639{
640 size_t name_len;
641 char const* name = luaL_checklstring( L, -1, &name_len);
642 int i;
643
644 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "populate_keepers %s BEGIN\n" INDENT_END, name));
645 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
646
647 for( i = 0; i < GNbKeepers; ++ i)
648 {
649 lua_State* K = GKeepers[i].L;
650 int res;
651 MUTEX_LOCK( &GKeepers[i].lock_);
652 STACK_CHECK( K);
653 STACK_GROW( K, 2);
654 lua_getglobal( K, "require");
655 lua_pushlstring( K, name, name_len);
656 res = lua_pcall( K, 1, 1, 0);
657 if( res != LUA_OK)
658 {
659 char const* err = luaL_checkstring( K, -1);
660 luaL_error( L, "error requiring '%s' in keeper state: %s", name, err);
661 }
662 // after requiring the module, register the functions it exported in our name<->function database
663 populate_func_lookup_table( K, -1, name);
664 lua_pop( K, 1);
665 STACK_END( K, 0);
666 MUTEX_UNLOCK( &GKeepers[i].lock_);
667 }
668 DEBUGSPEW_CODE( -- debugspew_indent_depth);
669}
670
671struct s_Keeper* keeper_acquire( void const* ptr) 607struct s_Keeper* keeper_acquire( void const* ptr)
672{ 608{
673 // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers) 609 // can be 0 if this happens during main state shutdown (lanes is being GC'ed -> no keepers)
@@ -747,12 +683,12 @@ int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, ui
747 683
748 lua_pushlightuserdata( K, linda); 684 lua_pushlightuserdata( K, linda);
749 685
750 if( (args == 0) || luaG_inter_copy( L, K, args) == 0) // L->K 686 if( (args == 0) || luaG_inter_copy( L, K, args, eLM_ToKeeper) == 0) // L->K
751 { 687 {
752 lua_call( K, 1 + args, LUA_MULTRET); 688 lua_call( K, 1 + args, LUA_MULTRET);
753 689
754 retvals = lua_gettop( K) - Ktos; 690 retvals = lua_gettop( K) - Ktos;
755 if( (retvals > 0) && luaG_inter_move( K, L, retvals) != 0) // K->L 691 if( (retvals > 0) && luaG_inter_move( K, L, retvals, eLM_FromKeeper) != 0) // K->L
756 { 692 {
757 retvals = -1; 693 retvals = -1;
758 } 694 }
diff --git a/src/keeper.h b/src/keeper.h
index 29a19a9..420eca1 100644
--- a/src/keeper.h
+++ b/src/keeper.h
@@ -18,21 +18,11 @@ char const* init_keepers( lua_State* L, int _on_state_create, int const _nbKeepe
18void close_keepers( void); 18void close_keepers( void);
19#endif // HAVE_KEEPER_ATEXIT_DESINIT 19#endif // HAVE_KEEPER_ATEXIT_DESINIT
20 20
21void populate_keepers( lua_State *L);
22struct s_Keeper *keeper_acquire( const void *ptr); 21struct s_Keeper *keeper_acquire( const void *ptr);
23void keeper_release( struct s_Keeper *K); 22void keeper_release( struct s_Keeper *K);
24void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel); 23void keeper_toggle_nil_sentinels( lua_State *L, int _val_i, int _nil_to_sentinel);
25int keeper_push_linda_storage( lua_State* L, void* ptr); 24int keeper_push_linda_storage( lua_State* L, void* ptr);
26 25
27#define KEEPER_MODEL_LUA 1
28#define KEEPER_MODEL_C 2
29#define KEEPER_MODEL KEEPER_MODEL_C
30
31#if KEEPER_MODEL == KEEPER_MODEL_LUA
32typedef char const* keeper_api_t;
33#define KEEPER_API( _op) #_op
34#define PUSH_KEEPER_FUNC( K, _api) lua_getglobal( K, _api)
35#elif KEEPER_MODEL == KEEPER_MODEL_C
36typedef lua_CFunction keeper_api_t; 26typedef lua_CFunction keeper_api_t;
37#define KEEPER_API( _op) keepercall_ ## _op 27#define KEEPER_API( _op) keepercall_ ## _op
38#define PUSH_KEEPER_FUNC lua_pushcfunction 28#define PUSH_KEEPER_FUNC lua_pushcfunction
@@ -45,7 +35,6 @@ int keepercall_limit( lua_State* L);
45int keepercall_get( lua_State* L); 35int keepercall_get( lua_State* L);
46int keepercall_set( lua_State* L); 36int keepercall_set( lua_State* L);
47int keepercall_count( lua_State* L); 37int keepercall_count( lua_State* L);
48#endif // KEEPER_MODEL
49 38
50int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, uint_t starting_index); 39int keeper_call( lua_State *K, keeper_api_t _func, lua_State *L, void *linda, uint_t starting_index);
51 40
diff --git a/src/lanes.c b/src/lanes.c
index 7eef2d0..dc1eeed 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -52,7 +52,7 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.6.4"; 55char const* VERSION = "3.6.5";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
@@ -1862,23 +1862,23 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void *vs)
1862} 1862}
1863 1863
1864// --- If a client wants to transfer stuff of a given module from the current state to another Lane, the module must be required 1864// --- If a client wants to transfer stuff of a given module from the current state to another Lane, the module must be required
1865// with lanes.require, that will call the regular 'require', then populate lookup databases in source and keeper states 1865// with lanes.require, that will call the regular 'require', then populate the lookup database in the source lane
1866// module = lanes.require( "modname") 1866// module = lanes.require( "modname")
1867// upvalue[1]: _G.require 1867// upvalue[1]: _G.require
1868LUAG_FUNC( require) 1868LUAG_FUNC( require)
1869{ 1869{
1870 char const* name = lua_tostring( L, 1); 1870 char const* name = lua_tostring( L, 1);
1871 STACK_CHECK( L);
1871 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); 1872 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name));
1872 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 1873 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
1873 lua_pushvalue( L, lua_upvalueindex(1)); // "name" require 1874 lua_pushvalue( L, lua_upvalueindex(1)); // "name" require
1874 lua_pushvalue( L, 1); // "name" require "name" 1875 lua_pushvalue( L, 1); // "name" require "name"
1875 lua_call( L, 1, 1); // "name" module 1876 lua_call( L, 1, 1); // "name" module
1876 populate_func_lookup_table( L, -1, name); 1877 populate_func_lookup_table( L, -1, name);
1877 lua_insert( L, -2); // module "name" 1878 lua_remove( L, -2); // module
1878 populate_keepers( L);
1879 lua_pop( L, 1); // module
1880 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name)); 1879 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name));
1881 DEBUGSPEW_CODE( -- debugspew_indent_depth); 1880 DEBUGSPEW_CODE( -- debugspew_indent_depth);
1881 STACK_END( L, 1);
1882 return 1; 1882 return 1;
1883} 1883}
1884 1884
@@ -1937,7 +1937,7 @@ LUAG_FUNC( thread_new)
1937 // package 1937 // package
1938 if( package) 1938 if( package)
1939 { 1939 {
1940 luaG_inter_copy_package( L, L2, package); 1940 luaG_inter_copy_package( L, L2, package, eLM_LaneBody);
1941 } 1941 }
1942 1942
1943 // modules to require in the target lane *before* the function is transfered! 1943 // modules to require in the target lane *before* the function is transfered!
@@ -1986,8 +1986,6 @@ LUAG_FUNC( thread_new)
1986 populate_func_lookup_table( L2, -1, name); 1986 populate_func_lookup_table( L2, -1, name);
1987 STACK_MID( L2, 1); 1987 STACK_MID( L2, 1);
1988 lua_pop( L2, 1); 1988 lua_pop( L2, 1);
1989 // don't require this module in the keeper states as well, use lanes.require() for that!
1990 //populate_keepers( L);
1991 } 1989 }
1992 STACK_END( L2, 0); 1990 STACK_END( L2, 0);
1993 } 1991 }
@@ -2017,7 +2015,7 @@ LUAG_FUNC( thread_new)
2017 lua_pushglobaltable( L2); // Lua 5.2 wants us to push the globals table on the stack 2015 lua_pushglobaltable( L2); // Lua 5.2 wants us to push the globals table on the stack
2018 while( lua_next( L, glob)) 2016 while( lua_next( L, glob))
2019 { 2017 {
2020 luaG_inter_copy( L, L2, 2); // moves the key/value pair to the L2 stack 2018 luaG_inter_copy( L, L2, 2, eLM_LaneBody); // moves the key/value pair to the L2 stack
2021 // assign it in L2's globals table 2019 // assign it in L2's globals table
2022 lua_rawset( L2, -3); 2020 lua_rawset( L2, -3);
2023 lua_pop( L, 1); 2021 lua_pop( L, 1);
@@ -2040,7 +2038,7 @@ LUAG_FUNC( thread_new)
2040 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: transfer lane body\n" INDENT_END)); 2038 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: transfer lane body\n" INDENT_END));
2041 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 2039 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
2042 lua_pushvalue( L, 1); 2040 lua_pushvalue( L, 1);
2043 res = luaG_inter_move( L, L2, 1); // L->L2 2041 res = luaG_inter_move( L, L2, 1, eLM_LaneBody); // L->L2
2044 DEBUGSPEW_CODE( -- debugspew_indent_depth); 2042 DEBUGSPEW_CODE( -- debugspew_indent_depth);
2045 if( res != 0) 2043 if( res != 0)
2046 { 2044 {
@@ -2067,7 +2065,7 @@ LUAG_FUNC( thread_new)
2067 int res; 2065 int res;
2068 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: transfer lane arguments\n" INDENT_END)); 2066 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "thread_new: transfer lane arguments\n" INDENT_END));
2069 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 2067 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
2070 res = luaG_inter_copy( L, L2, args); // L->L2 2068 res = luaG_inter_copy( L, L2, args, eLM_LaneBody); // L->L2
2071 DEBUGSPEW_CODE( -- debugspew_indent_depth); 2069 DEBUGSPEW_CODE( -- debugspew_indent_depth);
2072 if( res != 0) 2070 if( res != 0)
2073 return luaL_error( L, "tried to copy unsupported types"); 2071 return luaL_error( L, "tried to copy unsupported types");
@@ -2317,7 +2315,7 @@ LUAG_FUNC( thread_join)
2317 case DONE: 2315 case DONE:
2318 { 2316 {
2319 uint_t n = lua_gettop( L2); // whole L2 stack 2317 uint_t n = lua_gettop( L2); // whole L2 stack
2320 if( (n > 0) && (luaG_inter_move( L2, L, n) != 0)) 2318 if( (n > 0) && (luaG_inter_move( L2, L, n, eLM_LaneBody) != 0))
2321 { 2319 {
2322 return luaL_error( L, "tried to copy unsupported types"); 2320 return luaL_error( L, "tried to copy unsupported types");
2323 } 2321 }
@@ -2327,7 +2325,7 @@ LUAG_FUNC( thread_join)
2327 2325
2328 case ERROR_ST: 2326 case ERROR_ST:
2329 lua_pushnil( L); 2327 lua_pushnil( L);
2330 if( luaG_inter_move( L2, L, 2) != 0) // error message at [-2], stack trace at [-1] 2328 if( luaG_inter_move( L2, L, 2, eLM_LaneBody) != 0) // error message at [-2], stack trace at [-1]
2331 { 2329 {
2332 return luaL_error( L, "tried to copy unsupported types"); 2330 return luaL_error( L, "tried to copy unsupported types");
2333 } 2331 }
@@ -2620,25 +2618,6 @@ static const struct luaL_Reg lanes_functions [] = {
2620 2618
2621 2619
2622/* 2620/*
2623 * minimal function registration for keepers, just so that we can populate the transfer databases with them
2624 * without recursively deadlocking ourselves during one-time inits
2625 */
2626void register_core_libfuncs_for_keeper( lua_State* L)
2627{
2628 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register_core_libfuncs_for_keeper()\n" INDENT_END));
2629 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
2630 STACK_GROW( L, 1);
2631 STACK_CHECK( L);
2632 lua_newtable( L);
2633 luaG_registerlibfuncs( L, lanes_functions);
2634 STACK_MID( L, 1);
2635 populate_func_lookup_table( L, -1, "lanes.core");
2636 lua_pop( L, 1);
2637 STACK_END( L, 0);
2638 DEBUGSPEW_CODE( -- debugspew_indent_depth);
2639}
2640
2641/*
2642** One-time initializations 2621** One-time initializations
2643*/ 2622*/
2644static void init_once_LOCKED( lua_State* L, int const _on_state_create, int const nbKeepers, lua_Number _shutdown_timeout, bool_t _track_lanes, bool_t verbose_errors) 2623static void init_once_LOCKED( lua_State* L, int const _on_state_create, int const nbKeepers, lua_Number _shutdown_timeout, bool_t _track_lanes, bool_t verbose_errors)
diff --git a/src/tools.c b/src/tools.c
index a3cc6b7..a957f41 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -515,8 +515,6 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* _name)
515* Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. 515* Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL.
516* 516*
517*/ 517*/
518extern void register_core_libfuncs_for_keeper( lua_State* L);
519
520lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs) 518lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs)
521{ 519{
522 // reuse alloc function from the originating state 520 // reuse alloc function from the originating state
@@ -534,6 +532,7 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
534 { 532 {
535 return L; 533 return L;
536 } 534 }
535 // if we are here, no keeper state is involved (because libs == NULL when we init keepers)
537 536
538 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); 537 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END));
539 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 538 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
@@ -549,9 +548,8 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
549 if( libs) 548 if( libs)
550 { 549 {
551 // special "*" case (mainly to help with LuaJIT compatibility) 550 // special "*" case (mainly to help with LuaJIT compatibility)
552 // "K" is used when opening keeper states: almost the same as "*", but for the fact we don't open lanes.core
553 // as we are called from luaopen_lanes_core() already, and that would deadlock 551 // as we are called from luaopen_lanes_core() already, and that would deadlock
554 if( (libs[0] == '*' || libs[0] == 'K') && libs[1] == 0) 552 if( libs[0] == '*' && libs[1] == 0)
555 { 553 {
556 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); 554 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END));
557 luaL_openlibs( L); 555 luaL_openlibs( L);
@@ -560,12 +558,6 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
560 // don't forget lanes.core for regular lane states 558 // don't forget lanes.core for regular lane states
561 open1lib( L, "lanes.core", 10); 559 open1lib( L, "lanes.core", 10);
562 } 560 }
563 else
564 {
565 // In keeper states however, we only want to register the lanes.core functions to be able to transfer them through lindas
566 // (we don't care about a full lanes.core init in the keeper states as we won't call anything in there)
567 register_core_libfuncs_for_keeper( L);
568 }
569 libs = NULL; // done with libs 561 libs = NULL; // done with libs
570 } 562 }
571 else 563 else
@@ -622,7 +614,7 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
622 STACK_CHECK( _from); 614 STACK_CHECK( _from);
623 // Lua function: transfer as usual (should work as long as it only uses base libraries) 615 // Lua function: transfer as usual (should work as long as it only uses base libraries)
624 lua_pushvalue( _from, _on_state_create); 616 lua_pushvalue( _from, _on_state_create);
625 luaG_inter_move( _from, L, 1); 617 luaG_inter_move( _from, L, 1, eLM_LaneBody);
626 STACK_END( _from, 0); 618 STACK_END( _from, 0);
627 } 619 }
628 // capture error and forward it to main state 620 // capture error and forward it to main state
@@ -1283,59 +1275,6 @@ static bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L,
1283} 1275}
1284 1276
1285 1277
1286/*
1287 * Check if we've already copied the same function from 'L', and reuse the old
1288 * copy.
1289 *
1290 * Always pushes a function to 'L2'.
1291 */
1292static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, char const* upName_);
1293
1294static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, char const* upName_)
1295{
1296 void* const aspointer = (void*)lua_topointer( L, i);
1297 // TBD: Merge this and same code for tables
1298 ASSERT_L( L2_cache_i != 0);
1299
1300 STACK_GROW( L2, 2);
1301
1302 // L2_cache[id_str]= function
1303 //
1304 STACK_CHECK( L2);
1305
1306 // We don't need to use the from state ('L') in ID since the life span
1307 // is only for the duration of a copy (both states are locked).
1308 //
1309
1310 // push a light userdata uniquely representing the function
1311 lua_pushlightuserdata( L2, aspointer); // ... {cache} ... p
1312
1313 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
1314
1315 lua_pushvalue( L2, -1); // ... {cache} ... p p
1316 lua_rawget( L2, L2_cache_i); // ... {cache} ... p function|nil|true
1317
1318 if( lua_isnil(L2,-1)) // function is unknown
1319 {
1320 lua_pop( L2, 1); // ... {cache} ... p
1321
1322 // Set to 'true' for the duration of creation; need to find self-references
1323 // via upvalues
1324 //
1325 // pushes a copy of the func, stores a reference in the cache
1326 inter_copy_func( L2, L2_cache_i, L, i, upName_); // ... {cache} ... function
1327 }
1328 else // found function in the cache
1329 {
1330 lua_remove( L2, -2); // ... {cache} ... function
1331 }
1332 STACK_END( L2, 1);
1333 //
1334 // L2 [-1]: function
1335
1336 ASSERT_L( lua_isfunction( L2, -1));
1337}
1338
1339/* 1278/*
1340 * Return some name helping to identify an object 1279 * Return some name helping to identify an object
1341 */ 1280 */
@@ -1509,24 +1448,41 @@ int luaG_nameof( lua_State* L)
1509 return 2; 1448 return 2;
1510} 1449}
1511 1450
1451// function sentinel used to transfer native functions from/to keeper states
1452static int sentinelfunc( lua_State* L)
1453{
1454 return luaL_error( L, "transfer sentinel function for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
1455}
1456
1512/* 1457/*
1513* Push a looked-up native/LuaJIT function. 1458* Push a looked-up native/LuaJIT function.
1514*/ 1459*/
1515static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, char const* upName_) 1460static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_)
1516{ 1461{
1517 char const* fqn; // L // L2 1462 char const* fqn; // L // L2
1518 size_t len; 1463 size_t len;
1519 _ASSERT_L( L, lua_isfunction( L, i)); // ... f ... 1464 _ASSERT_L( L, lua_isfunction( L, i)); // ... f ...
1520 STACK_CHECK( L); 1465 STACK_CHECK( L);
1521 // fetch the name from the source state's lookup table 1466 if( mode_ == eLM_FromKeeper)
1522 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // ... f ... {} 1467 {
1523 _ASSERT_L( L, lua_istable( L, -1)); 1468 lua_CFunction f = lua_tocfunction( L, i); // should *always* be sentinelfunc!
1524 lua_pushvalue( L, i); // ... f ... {} f 1469 _ASSERT_L( L, f == sentinelfunc);
1525 lua_rawget( L, -2); // ... f ... {} "f.q.n" 1470 lua_getupvalue( L, i, 1); // ... f ... "f.q.n"
1526 fqn = lua_tolstring( L, -1, &len); 1471 fqn = lua_tolstring( L, -1, &len);
1472 }
1473 else
1474 {
1475 // fetch the name from the source state's lookup table
1476 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // ... f ... {}
1477 _ASSERT_L( L, lua_istable( L, -1));
1478 lua_pushvalue( L, i); // ... f ... {} f
1479 lua_rawget( L, -2); // ... f ... {} "f.q.n"
1480 fqn = lua_tolstring( L, -1, &len);
1481 }
1527 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn)); 1482 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn));
1528 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database 1483 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database
1529 lua_pop( L, 2); // ... f ... 1484 lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... f ...
1485 STACK_MID( L, 0);
1530 if( !fqn) 1486 if( !fqn)
1531 { 1487 {
1532 char const *from, *typewhat, *what, *gotchaA, *gotchaB; 1488 char const *from, *typewhat, *what, *gotchaA, *gotchaB;
@@ -1556,21 +1512,30 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, char cons
1556 STACK_END( L, 0); 1512 STACK_END( L, 0);
1557 // push the equivalent function in the destination's stack, retrieved from the lookup table 1513 // push the equivalent function in the destination's stack, retrieved from the lookup table
1558 STACK_CHECK( L2); 1514 STACK_CHECK( L2);
1559 lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {} 1515 if( mode_ == eLM_ToKeeper)
1560 _ASSERT_L( L2, lua_istable( L2, -1));
1561 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
1562 lua_rawget( L2, -2); // {} f
1563 if( !lua_isfunction( L2, -1))
1564 { 1516 {
1565 char const* from, * to; 1517 // push a sentinel closure that holds the lookup name as upvalue
1566 lua_getglobal( L, "decoda_name"); // // ... f ... decoda_name 1518 lua_pushlstring( L2, fqn, len); // "f.q.n"
1567 from = lua_tostring( L, -1); 1519 lua_pushcclosure( L2, sentinelfunc, 1); // f
1568 lua_getglobal( L2, "decoda_name"); // {} f decoda_name 1520 }
1569 to = lua_tostring( L2, -1); 1521 else
1570 (void) luaL_error( L, "%s: function '%s' not found in %s destination transfer database.", from ? from : "main", fqn, to ? to : "main"); 1522 {
1571 return; 1523 lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}
1524 _ASSERT_L( L2, lua_istable( L2, -1));
1525 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
1526 lua_rawget( L2, -2); // {} f
1527 if( !lua_isfunction( L2, -1))
1528 {
1529 char const* from, * to;
1530 lua_getglobal( L, "decoda_name"); // ... f ... decoda_name
1531 from = lua_tostring( L, -1);
1532 lua_getglobal( L2, "decoda_name"); // {} f decoda_name
1533 to = lua_tostring( L2, -1);
1534 (void) luaL_error( L, "%s: function '%s' not found in %s destination transfer database.", from ? from : "main", fqn, to ? to : "main");
1535 return;
1536 }
1537 lua_remove( L2, -2); // f
1572 } 1538 }
1573 lua_remove( L2, -2); // f
1574 STACK_END( L2, 1); 1539 STACK_END( L2, 1);
1575} 1540}
1576 1541
@@ -1581,159 +1546,207 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, char cons
1581enum e_vt { 1546enum e_vt {
1582 VT_NORMAL, VT_KEY, VT_METATABLE 1547 VT_NORMAL, VT_KEY, VT_METATABLE
1583}; 1548};
1584static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt value_type, char const* upName_); 1549static 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_);
1585 1550
1586static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, char const* upName_) 1551static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_)
1587{ 1552{
1588 FuncSubType funcSubType; 1553 int n, needToPush;
1589 /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions 1554 luaL_Buffer b;
1590
1591 ASSERT_L( L2_cache_i != 0); // ... {cache} ... p 1555 ASSERT_L( L2_cache_i != 0); // ... {cache} ... p
1592 STACK_GROW(L,2); 1556 STACK_GROW(L,2);
1593 STACK_CHECK( L); 1557 STACK_CHECK( L);
1594 1558
1595 if( funcSubType == FST_Bytecode) 1559 // 'lua_dump()' needs the function at top of stack
1560 // if already on top of the stack, no need to push again
1561 needToPush = (i != (uint_t)lua_gettop( L));
1562 if( needToPush)
1596 { 1563 {
1597 int n; 1564 lua_pushvalue( L, i); // ... f
1598 luaL_Buffer b; 1565 }
1599 // 'lua_dump()' needs the function at top of stack
1600 // if already on top of the stack, no need to push again
1601 int needToPush = (i != (uint_t)lua_gettop( L));
1602 if( needToPush)
1603 {
1604 lua_pushvalue( L, i); // ... f
1605 }
1606 1566
1607 luaL_buffinit( L, &b); 1567 luaL_buffinit( L, &b);
1608 // 1568 //
1609 // "value returned is the error code returned by the last call 1569 // "value returned is the error code returned by the last call
1610 // to the writer" (and we only return 0) 1570 // to the writer" (and we only return 0)
1611 // not sure this could ever fail but for memory shortage reasons 1571 // not sure this could ever fail but for memory shortage reasons
1612 if( lua_dump( L, buf_writer, &b) != 0) 1572 if( lua_dump( L, buf_writer, &b) != 0)
1613 { 1573 {
1614 luaL_error( L, "internal error: function dump failed."); 1574 luaL_error( L, "internal error: function dump failed.");
1615 } 1575 }
1616 1576
1617 // pushes dumped string on 'L' 1577 // pushes dumped string on 'L'
1618 luaL_pushresult( &b); // ... f b 1578 luaL_pushresult( &b); // ... f b
1619 1579
1620 // if not pushed, no need to pop 1580 // if not pushed, no need to pop
1621 if( needToPush) 1581 if( needToPush)
1582 {
1583 lua_remove( L, -2); // ... b
1584 }
1585
1586 // transfer the bytecode, then the upvalues, to create a similar closure
1587 {
1588 char const* name = NULL;
1589
1590 #if LOG_FUNC_INFO
1591 // "To get information about a function you push it onto the
1592 // stack and start the what string with the character '>'."
1593 //
1622 { 1594 {
1623 lua_remove( L, -2); // ... b 1595 lua_Debug ar;
1596 lua_pushvalue( L, i); // ... b f
1597 // fills 'name' 'namewhat' and 'linedefined', pops function
1598 lua_getinfo(L, ">nS", &ar); // ... b
1599 name = ar.namewhat;
1600 fprintf( stderr, INDENT_BEGIN "FNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL
1624 } 1601 }
1625 1602 #endif // LOG_FUNC_INFO
1626 // transfer the bytecode, then the upvalues, to create a similar closure
1627 { 1603 {
1628 char const* name = NULL; 1604 size_t sz;
1629 1605 char const* s = lua_tolstring( L, -1, &sz); // ... b
1630 #if LOG_FUNC_INFO 1606 ASSERT_L( s && sz);
1631 // "To get information about a function you push it onto the 1607 STACK_GROW( L2, 2);
1632 // stack and start the what string with the character '>'." 1608 // Note: Line numbers seem to be taken precisely from the
1609 // original function. 'name' is not used since the chunk
1610 // is precompiled (it seems...).
1633 // 1611 //
1612 // TBD: Can we get the function's original name through, as well?
1613 //
1614 if( luaL_loadbuffer( L2, s, sz, name) != 0) // ... {cache} ... p function
1634 { 1615 {
1635 lua_Debug ar; 1616 // chunk is precompiled so only LUA_ERRMEM can happen
1636 lua_pushvalue( L, i); // ... b f 1617 // "Otherwise, it pushes an error message"
1637 // fills 'name' 'namewhat' and 'linedefined', pops function
1638 lua_getinfo(L, ">nS", &ar); // ... b
1639 name = ar.namewhat;
1640 fprintf( stderr, INDENT_BEGIN "FNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL
1641 }
1642 #endif // LOG_FUNC_INFO
1643 {
1644 size_t sz;
1645 char const* s = lua_tolstring( L, -1, &sz); // ... b
1646 ASSERT_L( s && sz);
1647 STACK_GROW( L2, 2);
1648 // Note: Line numbers seem to be taken precisely from the
1649 // original function. 'name' is not used since the chunk
1650 // is precompiled (it seems...).
1651 //
1652 // TBD: Can we get the function's original name through, as well?
1653 // 1618 //
1654 if( luaL_loadbuffer( L2, s, sz, name) != 0) // ... {cache} ... p function 1619 STACK_GROW( L, 1);
1655 { 1620 luaL_error( L, "%s", lua_tostring( L2, -1));
1656 // chunk is precompiled so only LUA_ERRMEM can happen
1657 // "Otherwise, it pushes an error message"
1658 //
1659 STACK_GROW( L, 1);
1660 luaL_error( L, "%s", lua_tostring( L2, -1));
1661 }
1662 // remove the dumped string
1663 lua_pop( L, 1); // ...
1664 // now set the cache as soon as we can.
1665 // this is necessary if one of the function's upvalues references it indirectly
1666 // we need to find it in the cache even if it isn't fully transfered yet
1667 lua_insert( L2, -2); // ... {cache} ... function p
1668 lua_pushvalue( L2, -2); // ... {cache} ... function p function
1669 // cache[p] = function
1670 lua_rawset( L2, L2_cache_i); // ... {cache} ... function
1671 } 1621 }
1672 STACK_MID( L, 0); 1622 // remove the dumped string
1623 lua_pop( L, 1); // ...
1624 // now set the cache as soon as we can.
1625 // this is necessary if one of the function's upvalues references it indirectly
1626 // we need to find it in the cache even if it isn't fully transfered yet
1627 lua_insert( L2, -2); // ... {cache} ... function p
1628 lua_pushvalue( L2, -2); // ... {cache} ... function p function
1629 // cache[p] = function
1630 lua_rawset( L2, L2_cache_i); // ... {cache} ... function
1631 }
1632 STACK_MID( L, 0);
1673 1633
1674 /* push over any upvalues; references to this function will come from 1634 /* push over any upvalues; references to this function will come from
1675 * cache so we don't end up in eternal loop. 1635 * cache so we don't end up in eternal loop.
1676 * Lua5.2: one of the upvalues is _ENV, which we don't want to copy! 1636 * Lua5.2: one of the upvalues is _ENV, which we don't want to copy!
1677 * instead, the function shall have LUA_RIDX_GLOBALS taken in the destination state! 1637 * instead, the function shall have LUA_RIDX_GLOBALS taken in the destination state!
1678 */ 1638 */
1679 { 1639 {
1680 char const* upname; 1640 char const* upname;
1681#if LUA_VERSION_NUM == 502 1641#if LUA_VERSION_NUM == 502
1682 // With Lua 5.2, each Lua function gets its environment as one of its upvalues (named LUA_ENV, aka "_ENV" by default) 1642 // With Lua 5.2, each Lua function gets its environment as one of its upvalues (named LUA_ENV, aka "_ENV" by default)
1683 // Generally this is LUA_RIDX_GLOBALS, which we don't want to copy from the source to the destination state... 1643 // Generally this is LUA_RIDX_GLOBALS, which we don't want to copy from the source to the destination state...
1684 // -> if we encounter an upvalue equal to the global table in the source, bind it to the destination's global table 1644 // -> if we encounter an upvalue equal to the global table in the source, bind it to the destination's global table
1685 lua_pushglobaltable( L); // ... _G 1645 lua_pushglobaltable( L); // ... _G
1686#endif // LUA_VERSION_NUM 1646#endif // LUA_VERSION_NUM
1687 for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n) 1647 for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n)
1688 { // ... _G up[n] 1648 { // ... _G up[n]
1689 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "UPNAME[%d]: %s\n" INDENT_END, n, upname)); 1649 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "UPNAME[%d]: %s\n" INDENT_END, n, upname));
1690#if LUA_VERSION_NUM == 502 1650#if LUA_VERSION_NUM == 502
1691 if( lua_rawequal( L, -1, -2)) // is the upvalue equal to the global table? 1651 if( lua_rawequal( L, -1, -2)) // is the upvalue equal to the global table?
1692 { 1652 {
1693 lua_pushglobaltable( L2); // ... {cache} ... function <upvalues> 1653 lua_pushglobaltable( L2); // ... {cache} ... function <upvalues>
1694 } 1654 }
1695 else 1655 else
1696#endif // LUA_VERSION_NUM 1656#endif // LUA_VERSION_NUM
1657 {
1658 if( !inter_copy_one_( L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, mode_, upname)) // ... {cache} ... function <upvalues>
1697 { 1659 {
1698 if( !inter_copy_one_( L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, upname)) // ... {cache} ... function <upvalues> 1660 luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1));
1699 {
1700 luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1));
1701 }
1702 } 1661 }
1703 lua_pop( L, 1); // ... _G
1704 } 1662 }
1663 lua_pop( L, 1); // ... _G
1664 }
1705#if LUA_VERSION_NUM == 502 1665#if LUA_VERSION_NUM == 502
1706 lua_pop( L, 1); // ... 1666 lua_pop( L, 1); // ...
1707#endif // LUA_VERSION_NUM 1667#endif // LUA_VERSION_NUM
1708 } 1668 }
1709 // L2: function + 'n' upvalues (>=0) 1669 // L2: function + 'n' upvalues (>=0)
1710 1670
1711 STACK_MID( L, 0); 1671 STACK_MID( L, 0);
1712 1672
1713 // Set upvalues (originally set to 'nil' by 'lua_load') 1673 // Set upvalues (originally set to 'nil' by 'lua_load')
1674 {
1675 int func_index = lua_gettop( L2) - n;
1676 for( ; n > 0; -- n)
1714 { 1677 {
1715 int func_index = lua_gettop( L2) - n; 1678 char const* rc = lua_setupvalue( L2, func_index, n); // ... {cache} ... function
1716 for( ; n > 0; -- n) 1679 //
1717 { 1680 // "assigns the value at the top of the stack to the upvalue and returns its name.
1718 char const* rc = lua_setupvalue( L2, func_index, n); // ... {cache} ... function 1681 // It also pops the value from the stack."
1719 //
1720 // "assigns the value at the top of the stack to the upvalue and returns its name.
1721 // It also pops the value from the stack."
1722 1682
1723 ASSERT_L( rc); // not having enough slots? 1683 ASSERT_L( rc); // not having enough slots?
1724 }
1725 // once all upvalues have been set we are left
1726 // with the function at the top of the stack // ... {cache} ... function
1727 } 1684 }
1685 // once all upvalues have been set we are left
1686 // with the function at the top of the stack // ... {cache} ... function
1728 } 1687 }
1729 } 1688 }
1730 else // C function OR LuaJIT fast function!!! 1689 STACK_END( L, 0);
1690}
1691
1692/*
1693 * Check if we've already copied the same function from 'L', and reuse the old
1694 * copy.
1695 *
1696 * Always pushes a function to 'L2'.
1697 */
1698static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_)
1699{
1700 FuncSubType funcSubType;
1701 /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions
1702 if( funcSubType == FST_Bytecode)
1703 {
1704 void* const aspointer = (void*)lua_topointer( L, i);
1705 // TBD: Merge this and same code for tables
1706 ASSERT_L( L2_cache_i != 0);
1707
1708 STACK_GROW( L2, 2);
1709
1710 // L2_cache[id_str]= function
1711 //
1712 STACK_CHECK( L2);
1713
1714 // We don't need to use the from state ('L') in ID since the life span
1715 // is only for the duration of a copy (both states are locked).
1716 //
1717
1718 // push a light userdata uniquely representing the function
1719 lua_pushlightuserdata( L2, aspointer); // ... {cache} ... p
1720
1721 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
1722
1723 lua_pushvalue( L2, -1); // ... {cache} ... p p
1724 lua_rawget( L2, L2_cache_i); // ... {cache} ... p function|nil|true
1725
1726 if( lua_isnil(L2,-1)) // function is unknown
1727 {
1728 lua_pop( L2, 1); // ... {cache} ... p
1729
1730 // Set to 'true' for the duration of creation; need to find self-references
1731 // via upvalues
1732 //
1733 // pushes a copy of the func, stores a reference in the cache
1734 inter_copy_func( L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function
1735 }
1736 else // found function in the cache
1737 {
1738 lua_remove( L2, -2); // ... {cache} ... function
1739 }
1740 STACK_END( L2, 1);
1741 }
1742 else // function is native/LuaJIT: no need to cache
1731 { 1743 {
1732 lua_pop( L2, 1); // ... {cache} ... 1744 lookup_native_func( L2, L, i, mode_, upName_); // ... {cache} ... function
1733 // No need to transfer upvalues for C/JIT functions since they weren't actually copied, only looked up
1734 lookup_native_func( L2, L, i, upName_); // ... {cache} ... function
1735 } 1745 }
1736 STACK_END( L, 0); 1746
1747 //
1748 // L2 [-1]: function
1749 ASSERT_L( lua_isfunction( L2, -1));
1737} 1750}
1738 1751
1739/* 1752/*
@@ -1746,7 +1759,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin
1746* 1759*
1747* Returns TRUE if value was pushed, FALSE if its type is non-supported. 1760* Returns TRUE if value was pushed, FALSE if its type is non-supported.
1748*/ 1761*/
1749static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, char const* upName_) 1762static 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_)
1750{ 1763{
1751 bool_t ret = TRUE; 1764 bool_t ret = TRUE;
1752 1765
@@ -1764,6 +1777,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1764 1777
1765 case LUA_TNUMBER: 1778 case LUA_TNUMBER:
1766 /* LNUM patch support (keeping integer accuracy) */ 1779 /* LNUM patch support (keeping integer accuracy) */
1780 // TODO: support for integer in Lua 5.3
1767#ifdef LUA_LNUM 1781#ifdef LUA_LNUM
1768 if( lua_isinteger(L,i)) 1782 if( lua_isinteger(L,i))
1769 { 1783 {
@@ -1831,7 +1845,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1831 { 1845 {
1832 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "FUNCTION\n" INDENT_END)); 1846 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "FUNCTION\n" INDENT_END));
1833 STACK_CHECK( L2); 1847 STACK_CHECK( L2);
1834 push_cached_func( L2, L2_cache_i, L, i, upName_); 1848 push_cached_func( L2, L2_cache_i, L, i, mode_, upName_);
1835 STACK_END( L2, 1); 1849 STACK_END( L2, 1);
1836 } 1850 }
1837 break; 1851 break;
@@ -1873,7 +1887,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1873 1887
1874 /* Only basic key types are copied over; others ignored 1888 /* Only basic key types are copied over; others ignored
1875 */ 1889 */
1876 if( inter_copy_one_( L2, 0 /*key*/, L, key_i, VT_KEY, upName_)) 1890 if( inter_copy_one_( L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_))
1877 { 1891 {
1878 char* valPath = (char*) upName_; 1892 char* valPath = (char*) upName_;
1879 if( GVerboseErrors) 1893 if( GVerboseErrors)
@@ -1894,7 +1908,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1894 * Contents of metatables are copied with cache checking; 1908 * Contents of metatables are copied with cache checking;
1895 * important to detect loops. 1909 * important to detect loops.
1896 */ 1910 */
1897 if( inter_copy_one_( L2, L2_cache_i, L, val_i, VT_NORMAL, valPath)) 1911 if( inter_copy_one_( L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath))
1898 { 1912 {
1899 ASSERT_L( lua_istable(L2,-3)); 1913 ASSERT_L( lua_istable(L2,-3));
1900 lua_rawset( L2, -3); // add to table (pops key & val) 1914 lua_rawset( L2, -3); // add to table (pops key & val)
@@ -1936,7 +1950,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1936 lua_pop( L2, 1); 1950 lua_pop( L2, 1);
1937 STACK_MID( L2, 2); 1951 STACK_MID( L2, 2);
1938 ASSERT_L( lua_istable(L,-1)); 1952 ASSERT_L( lua_istable(L,-1));
1939 if( inter_copy_one_( L2, L2_cache_i /*for function cacheing*/, L, lua_gettop(L) /*[-1]*/, VT_METATABLE, upName_)) 1953 if( inter_copy_one_( L2, L2_cache_i /*for function cacheing*/, L, lua_gettop(L) /*[-1]*/, VT_METATABLE, mode_, upName_))
1940 { 1954 {
1941 // 1955 //
1942 // L2 ([-3]: copied table) 1956 // L2 ([-3]: copied table)
@@ -1981,8 +1995,8 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1981 } 1995 }
1982 STACK_END( L2, 1); 1996 STACK_END( L2, 1);
1983 STACK_END( L, 0); 1997 STACK_END( L, 0);
1984 } 1998 }
1985 break; 1999 break;
1986 2000
1987 /* The following types cannot be copied */ 2001 /* The following types cannot be copied */
1988 2002
@@ -2004,7 +2018,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
2004* 2018*
2005* Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'. 2019* Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'.
2006*/ 2020*/
2007int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n) 2021int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_)
2008{ 2022{
2009 uint_t top_L = lua_gettop( L); 2023 uint_t top_L = lua_gettop( L);
2010 uint_t top_L2 = lua_gettop( L2); 2024 uint_t top_L2 = lua_gettop( L2);
@@ -2034,7 +2048,7 @@ int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n)
2034 { 2048 {
2035 sprintf( tmpBuf, "arg_%d", j); 2049 sprintf( tmpBuf, "arg_%d", j);
2036 } 2050 }
2037 copyok = inter_copy_one_( L2, top_L2 + 1, L, i, VT_NORMAL, pBuf); 2051 copyok = inter_copy_one_( L2, top_L2 + 1, L, i, VT_NORMAL, mode_, pBuf);
2038 if( !copyok) 2052 if( !copyok)
2039 { 2053 {
2040 break; 2054 break;
@@ -2062,14 +2076,14 @@ int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n)
2062} 2076}
2063 2077
2064 2078
2065int luaG_inter_move( lua_State* L, lua_State* L2, uint_t n) 2079int luaG_inter_move( lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_)
2066{ 2080{
2067 int ret = luaG_inter_copy( L, L2, n); 2081 int ret = luaG_inter_copy( L, L2, n, mode_);
2068 lua_pop( L, (int) n); 2082 lua_pop( L, (int) n);
2069 return ret; 2083 return ret;
2070} 2084}
2071 2085
2072void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx) 2086void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx, enum eLookupMode mode_)
2073{ 2087{
2074 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); 2088 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END));
2075 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 2089 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
@@ -2100,7 +2114,7 @@ void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx)
2100 else 2114 else
2101 { 2115 {
2102 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 2116 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
2103 luaG_inter_move( L, L2, 1); // moves the entry to L2 2117 luaG_inter_move( L, L2, 1, mode_); // moves the entry to L2
2104 DEBUGSPEW_CODE( -- debugspew_indent_depth); 2118 DEBUGSPEW_CODE( -- debugspew_indent_depth);
2105 lua_setfield( L2, -2, entries[i]); // set package[entries[i]] 2119 lua_setfield( L2, -2, entries[i]); // set package[entries[i]]
2106 } 2120 }
diff --git a/src/tools.h b/src/tools.h
index 93ed92c..bf48f1f 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -90,10 +90,17 @@ typedef struct {
90} DEEP_PRELUDE; 90} DEEP_PRELUDE;
91 91
92void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *deep_userdata); 92void luaG_push_proxy( lua_State *L, luaG_IdFunction idfunc, DEEP_PRELUDE *deep_userdata);
93void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx); 93void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx, enum eLookupMode mode_);
94 94
95int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n); 95enum eLookupMode
96int luaG_inter_move( lua_State *L, lua_State *L2, uint_t n); 96{
97 eLM_LaneBody, // send the lane body directly from the source to the destination lane
98 eLM_ToKeeper, // send a function from a lane to a keeper state
99 eLM_FromKeeper, // send a function from a keeper state to a lane
100};
101
102int luaG_inter_copy( lua_State *L, lua_State *L2, uint_t n, enum eLookupMode mode_);
103int luaG_inter_move( lua_State *L, lua_State *L2, uint_t n, enum eLookupMode mode_);
97 104
98int luaG_nameof( lua_State* L); 105int luaG_nameof( lua_State* L);
99int luaG_new_require( lua_State* L); 106int luaG_new_require( lua_State* L);