aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2013-09-26 21:11:24 +0200
committerBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2013-09-26 21:11:24 +0200
commitf823c6887e28c815234f8b4bd355887b4f554857 (patch)
tree862b37cc93d6779c3c2577e78ed6ff5389412f90
parentc97ad8630ea9dcb92b4e9db16c4dbade1de18884 (diff)
downloadlanes-f823c6887e28c815234f8b4bd355887b4f554857.tar.gz
lanes-f823c6887e28c815234f8b4bd355887b4f554857.tar.bz2
lanes-f823c6887e28c815234f8b4bd355887b4f554857.zip
Reduce memory footprint, simplify module order setup in conjuction with Lanes, and send over native functions a bit faster as well
* Lanes no longer has to internally require modules inside the keeper states because they no longer need a lookup database. the lookup name is stored as-is and actually converted in the destination state * optimisation: bypass cache when sending native functions over * removed all the KEEPER_MODEL_LUA code, as it can no longer work anyway
-rw-r--r--CHANGES8
-rw-r--r--docs/index.html17
-rw-r--r--lanes-3.6.5-1.rockspec66
-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
8 files changed, 338 insertions, 344 deletions
diff --git a/CHANGES b/CHANGES
index 5fdcd83..a52a404 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,13 @@
1CHANGES: 1CHANGES:
2 2
3CHANGE 69: BGe 26-Sept-13
4 * version 3.6.5
5 * Reduce memory footprint, simplify module order setup in conjuction with Lanes, and send over native functions a bit faster as well
6 * Lanes no longer has to internally require modules inside the keeper states because they no longer need a lookup database
7 the lookup name is stored as-is and actually converted in the destination state
8 * optimisation: bypass cache when sending native functions over
9 * removed all the KEEPER_MODEL_LUA code, as it can no longer work anyway
10
3CHANGE 68: BGe 24-Sept-13 11CHANGE 68: BGe 24-Sept-13
4 * version 3.6.4 12 * version 3.6.4
5 * Fix possible application hang at shutdown if a keeper state referenced a linda. 13 * Fix possible application hang at shutdown if a keeper state referenced a linda.
diff --git a/docs/index.html b/docs/index.html
index 1c60aaa..ac4fa6b 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -70,7 +70,7 @@
70 </p> 70 </p>
71 71
72 <p> 72 <p>
73 This document was revised on 24-Sept-13, and applies to version <tt>3.6.4</tt>. 73 This document was revised on 26-Sept-13, and applies to version <tt>3.6.5</tt>.
74 </p> 74 </p>
75 </font> 75 </font>
76 </center> 76 </center>
@@ -314,7 +314,7 @@
314 </td> 314 </td>
315 <td> 315 <td>
316 (Since v3.5.2) If equal to <tt>true</tt>, Lanes wraps all calls to the state's allocator function inside a mutex. Useful when running Lanes with LuaJIT, whose allocator is not threadsafe. 316 (Since v3.5.2) If equal to <tt>true</tt>, Lanes wraps all calls to the state's allocator function inside a mutex. Useful when running Lanes with LuaJIT, whose allocator is not threadsafe.
317 Default is <tt>nil</tt>. 317 Default is <tt>true</tt> when Lanes detects it is run by LuaJIT, else <tt>nil</tt>.
318 </td> 318 </td>
319 </tr> 319 </tr>
320 320
@@ -603,8 +603,6 @@
603 Specifying it when <code>libs_str</code> doesn't cause the <code>package</code> library to be loaded will generate an error. 603 Specifying it when <code>libs_str</code> doesn't cause the <code>package</code> library to be loaded will generate an error.
604 <br> 604 <br>
605 If not specified, the created lane will receive the current values of <tt>package</tt>. Only <tt>path</tt>, <tt>cpath</tt>, <tt>preload</tt> and <tt>loaders</tt> (Lua 5.1)/<tt>searchers</tt> (Lua 5.2) are transfered. 605 If not specified, the created lane will receive the current values of <tt>package</tt>. Only <tt>path</tt>, <tt>cpath</tt>, <tt>preload</tt> and <tt>loaders</tt> (Lua 5.1)/<tt>searchers</tt> (Lua 5.2) are transfered.
606 <br>
607 IMPORTANT: The contents of whatever package table is actually provided to the lane won't be known to the keeper states: they will stick to whatever was found in the main state's package table when Lane was required.
608 </td> 606 </td>
609 </tr> 607 </tr>
610 </table> 608 </table>
@@ -1251,10 +1249,7 @@ events to a common Linda, but... :).</font>
1251 </ul> 1249 </ul>
1252 </li> 1250 </li>
1253 <li> 1251 <li>
1254 C functions (<tt>lua_CFunction</tt>) referring to <tt>LUA_ENVIRONINDEX</tt> or <tt>LUA_REGISTRYINDEX</tt> might not work right in the target 1252 C functions (<tt>lua_CFunction</tt>) referring to <tt>LUA_ENVIRONINDEX</tt> or <tt>LUA_REGISTRYINDEX</tt> might not do what you expect in the target, since they will actually use a different environment.
1255 <ul>
1256 <li>Rather completely re-initialize a module with <tt>require</tt> in the target lane.</li>
1257 </ul>
1258 </li> 1253 </li>
1259 <li> 1254 <li>
1260 Lua 5.2 functions may have a special <tt>_ENV</tt> upvalue if they perform 'global namespace' lookups. Unless special care is taken, this upvalue defaults to the table found at <tt>LUA_RIDX_GLOBALS</tt>. 1255 Lua 5.2 functions may have a special <tt>_ENV</tt> upvalue if they perform 'global namespace' lookups. Unless special care is taken, this upvalue defaults to the table found at <tt>LUA_RIDX_GLOBALS</tt>.
@@ -1319,7 +1314,7 @@ events to a common Linda, but... :).</font>
1319 <br> 1314 <br>
1320 When a lane generator creates a lane and performs initializations described by the list of base libraries and the list of required modules, it recursively scans the table created by the initialisation of the module, looking for all values that are C functions. 1315 When a lane generator creates a lane and performs initializations described by the list of base libraries and the list of required modules, it recursively scans the table created by the initialisation of the module, looking for all values that are C functions.
1321 <br> 1316 <br>
1322 Each time a function is encountered, the sequence of keys that reached that function is contatenated in a (hopefully) unique name. The [name, function] and [function, name] pairs are both stored in a lookup table in all involved Lua states (main Lua state, keeper states, lanes states). 1317 Each time a function is encountered, the sequence of keys that reached that function is contatenated in a (hopefully) unique name. The [name, function] and [function, name] pairs are both stored in a lookup table in all involved Lua states (main Lua state and lanes states).
1323 <br> 1318 <br>
1324 Then when a function is transfered from one state to another, all we have to do is retrieve the name associated to a function in the source Lua state, then with that name retrieve the equivalent function that already exists in the destination state. 1319 Then when a function is transfered from one state to another, all we have to do is retrieve the name associated to a function in the source Lua state, then with that name retrieve the equivalent function that already exists in the destination state.
1325 <br> 1320 <br>
@@ -1336,7 +1331,7 @@ events to a common Linda, but... :).</font>
1336 string2 = string 1331 string2 = string
1337 </pre></td></tr></table> 1332 </pre></td></tr></table>
1338 When iterating over all keys of the global table, Lanes has no guarantee that it will hit <tt>"string"</tt> before or after <tt>"string2"</tt>. However, the values associated to <tt>string.match</tt> and <tt>string2.match</tt> are the same C function. 1333 When iterating over all keys of the global table, Lanes has no guarantee that it will hit <tt>"string"</tt> before or after <tt>"string2"</tt>. However, the values associated to <tt>string.match</tt> and <tt>string2.match</tt> are the same C function.
1339 Lanes doesn't expect a C function value to be encountered more than once. In the event it occurs, when the lookup table is populated with a [function, name] pair, an existing pair won't be updated if it is already found. In other words, the first name that was computed is retained. 1334 Lanes doesn't normally expect a C function value to be encountered more than once. In the event it occurs, the shortest name that was computed is retained.
1340 If Lanes processed <tt>"string2"</tt> first, it means that if the Lua state that contains the <tt>"string2"</tt> global name sends function <tt>string.match</tt>, <tt>lookup_func_name</tt> would return name <tt>"string2.match"</tt>, with the obvious effect that <tt>push_resolved_func</tt> 1335 If Lanes processed <tt>"string2"</tt> first, it means that if the Lua state that contains the <tt>"string2"</tt> global name sends function <tt>string.match</tt>, <tt>lookup_func_name</tt> would return name <tt>"string2.match"</tt>, with the obvious effect that <tt>push_resolved_func</tt>
1341 won't find <tt>"string2.match"</tt> in the destination lookup database, thus failing the transfer (even though this function exists, but is referenced under name <tt>"string.match"</tt>). 1336 won't find <tt>"string2.match"</tt> in the destination lookup database, thus failing the transfer (even though this function exists, but is referenced under name <tt>"string.match"</tt>).
1342 </li> 1337 </li>
@@ -1345,7 +1340,7 @@ events to a common Linda, but... :).</font>
1345 When Lua is built with compatibility options (such as LUA_COMPAT_ALL), this causes several base libraries to register functions under multiple names. 1340 When Lua is built with compatibility options (such as LUA_COMPAT_ALL), this causes several base libraries to register functions under multiple names.
1346 This, with the randomizer, can cause the first encountered name of a function to be different on different VMs, which breaks function transfer. 1341 This, with the randomizer, can cause the first encountered name of a function to be different on different VMs, which breaks function transfer.
1347 Even under Lua 5.1, this may cause trouble if some module registers a function under several keys. 1342 Even under Lua 5.1, this may cause trouble if some module registers a function under several keys.
1348 To circumvent this, Lanes has to select one name among all candidates, and the rule for this is to keep the 'smaller' one: first in bytes, then in lexical order. 1343 To circumvent this, Lanes has to select one name among all candidates, and the rule for this is to keep the 'smaller' one: first in byte count, then in lexical order.
1349 </li> 1344 </li>
1350 </ul> 1345 </ul>
1351 Another more immediate reason of failed transfer is when the destination state doesn't know about the C function that has to be transferred. This occurs if a function is transferred in a lane before it had a chance to scan the module. 1346 Another more immediate reason of failed transfer is when the destination state doesn't know about the C function that has to be transferred. This occurs if a function is transferred in a lane before it had a chance to scan the module.
diff --git a/lanes-3.6.5-1.rockspec b/lanes-3.6.5-1.rockspec
new file mode 100644
index 0000000..0f11854
--- /dev/null
+++ b/lanes-3.6.5-1.rockspec
@@ -0,0 +1,66 @@
1--
2-- Lanes rockspec
3--
4-- Ref:
5-- <http://luarocks.org/en/Rockspec_format>
6--
7
8package = "Lanes"
9
10version = "3.6.5-1"
11
12source= {
13 url= "git://github.com/LuaLanes/lanes.git",
14 branch= "v3.6.5"
15}
16
17description = {
18 summary= "Multithreading support for Lua",
19 detailed= [[
20 Lua Lanes is a portable, message passing multithreading library
21 providing the possibility to run multiple Lua states in parallel.
22 ]],
23 license= "MIT/X11",
24 homepage="https://github.com/LuaLanes/lanes",
25 maintainer="Benoit Germain <bnt.germain@gmail.com>"
26}
27
28-- Q: What is the difference of "windows" and "win32"? Seems there is none;
29-- so should we list either one or both?
30--
31supported_platforms= { "win32",
32 "macosx",
33 "linux",
34 "freebsd", -- TBD: not tested
35 "msys", -- TBD: not supported by LuaRocks 1.0 (or is it?)
36}
37
38dependencies= {
39 "lua >= 5.1", -- builds with either 5.1 and 5.2
40}
41
42build = {
43 type = "builtin",
44 platforms =
45 {
46 linux =
47 {
48 modules =
49 {
50 ["lanes.core"] =
51 {
52 libraries = "pthread"
53 },
54 }
55 }
56 },
57 modules =
58 {
59 ["lanes.core"] =
60 {
61 sources = { "src/lanes.c", "src/keeper.c", "src/tools.c", "src/threading.c"},
62 incdirs = { "src"},
63 },
64 lanes = "src/lanes.lua"
65 }
66}
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);