aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/keeper.c10
-rw-r--r--src/lanes.c42
-rw-r--r--src/lanes.lua21
-rw-r--r--src/tools.c597
-rw-r--r--src/tools.h4
5 files changed, 420 insertions, 254 deletions
diff --git a/src/keeper.c b/src/keeper.c
index 056c01e..9a7c804 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -103,7 +103,7 @@ static void fifo_push( lua_State* L, keeper_fifo* fifo_, lua_Integer count_)
103 for( i = count_; i >= 1; -- i) 103 for( i = count_; i >= 1; -- i)
104 { 104 {
105 // store in the fifo the value at the top of the stack at the specified index, popping it from the stack 105 // store in the fifo the value at the top of the stack at the specified index, popping it from the stack
106 lua_rawseti( L, idx, start + i); 106 lua_rawseti( L, idx, (int)(start + i));
107 } 107 }
108 fifo_->count += count_; 108 fifo_->count += count_;
109} 109}
@@ -115,11 +115,11 @@ static void fifo_push( lua_State* L, keeper_fifo* fifo_, lua_Integer count_)
115// function assumes that there is enough data in the fifo to satisfy the request 115// function assumes that there is enough data in the fifo to satisfy the request
116static void fifo_peek( lua_State* L, keeper_fifo* fifo_, lua_Integer count_) 116static void fifo_peek( lua_State* L, keeper_fifo* fifo_, lua_Integer count_)
117{ 117{
118 int i; 118 lua_Integer i;
119 STACK_GROW( L, count_); 119 STACK_GROW( L, count_);
120 for( i = 0; i < count_; ++ i) 120 for( i = 0; i < count_; ++ i)
121 { 121 {
122 lua_rawgeti( L, 1, fifo_->first + i); 122 lua_rawgeti( L, 1, (int)( fifo_->first + i));
123 } 123 }
124} 124}
125 125
@@ -134,7 +134,7 @@ static void fifo_pop( lua_State* L, keeper_fifo* fifo_, lua_Integer count_)
134 // skip first item, we will push it last 134 // skip first item, we will push it last
135 for( i = 1; i < count_; ++ i) 135 for( i = 1; i < count_; ++ i)
136 { 136 {
137 lua_Integer const at = fifo_->first + i; 137 int const at = (int)( fifo_->first + i);
138 // push item on the stack 138 // push item on the stack
139 lua_rawgeti( L, fifo_idx, at); // ... fifo val 139 lua_rawgeti( L, fifo_idx, at); // ... fifo val
140 // remove item from the fifo 140 // remove item from the fifo
@@ -143,7 +143,7 @@ static void fifo_pop( lua_State* L, keeper_fifo* fifo_, lua_Integer count_)
143 } 143 }
144 // now process first item 144 // now process first item
145 { 145 {
146 lua_Integer const at = fifo_->first; 146 int const at = (int)( fifo_->first);
147 lua_rawgeti( L, fifo_idx, at); // ... fifo vals val 147 lua_rawgeti( L, fifo_idx, at); // ... fifo vals val
148 lua_pushnil( L); // ... fifo vals val nil 148 lua_pushnil( L); // ... fifo vals val nil
149 lua_rawseti( L, fifo_idx, at); // ... fifo vals val 149 lua_rawseti( L, fifo_idx, at); // ... fifo vals val
diff --git a/src/lanes.c b/src/lanes.c
index d0ffee1..8410ca2 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * LANES.C Copyright (c) 2007-08, Asko Kauppi 2 * LANES.C Copyright (c) 2007-08, Asko Kauppi
3 * Copyright (C) 2009-14, Benoit Germain 3 * Copyright (C) 2009-17, Benoit Germain
4 * 4 *
5 * Multithreading in Lua. 5 * Multithreading in Lua.
6 * 6 *
@@ -52,13 +52,13 @@
52 * ... 52 * ...
53 */ 53 */
54 54
55char const* VERSION = "3.10.1"; 55char const* VERSION = "3.11";
56 56
57/* 57/*
58=============================================================================== 58===============================================================================
59 59
60Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com> 60Copyright (C) 2007-10 Asko Kauppi <akauppi@gmail.com>
61 2011-14 Benoit Germain <bnt.germain@gmail.com> 61 2011-17 Benoit Germain <bnt.germain@gmail.com>
62 62
63Permission is hereby granted, free of charge, to any person obtaining a copy 63Permission is hereby granted, free of charge, to any person obtaining a copy
64of this software and associated documentation files (the "Software"), to deal 64of this software and associated documentation files (the "Software"), to deal
@@ -162,7 +162,8 @@ struct s_lane
162 // lane status changes to DONE/ERROR_ST/CANCELLED. 162 // lane status changes to DONE/ERROR_ST/CANCELLED.
163#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR 163#endif // THREADWAIT_METHOD == THREADWAIT_CONDVAR
164 164
165 volatile enum { 165 volatile enum
166 {
166 NORMAL, // normal master side state 167 NORMAL, // normal master side state
167 KILLED // issued an OS kill 168 KILLED // issued an OS kill
168 } mstatus; 169 } mstatus;
@@ -307,7 +308,7 @@ static bool_t push_registry_table( lua_State* L, void* key, bool_t create)
307 return FALSE; 308 return FALSE;
308 } 309 }
309 310
310 lua_newtable(L); // t 311 lua_newtable( L); // t
311 lua_pushlightuserdata( L, key); // t key 312 lua_pushlightuserdata( L, key); // t key
312 lua_pushvalue( L, -2); // t key t 313 lua_pushvalue( L, -2); // t key t
313 lua_rawset( L, LUA_REGISTRYINDEX); // t 314 lua_rawset( L, LUA_REGISTRYINDEX); // t
@@ -351,7 +352,7 @@ static bool_t tracking_remove( struct s_lane* s)
351 // still (at process exit they will remove us from chain and then 352 // still (at process exit they will remove us from chain and then
352 // cancel/kill). 353 // cancel/kill).
353 // 354 //
354 if (s->tracking_next != NULL) 355 if( s->tracking_next != NULL)
355 { 356 {
356 struct s_lane** ref = (struct s_lane**) &s->U->tracking_first; 357 struct s_lane** ref = (struct s_lane**) &s->U->tracking_first;
357 358
@@ -539,7 +540,7 @@ LUAG_FUNC( linda_send)
539 break; 540 break;
540 } 541 }
541 542
542 // instant timout to bypass the 543 // instant timout to bypass the wait syscall
543 if( timeout == 0.0) 544 if( timeout == 0.0)
544 { 545 {
545 break; /* no wait; instant timeout */ 546 break; /* no wait; instant timeout */
@@ -2157,6 +2158,30 @@ LUAG_FUNC( require)
2157 return 1; 2158 return 1;
2158} 2159}
2159 2160
2161
2162// --- If a client wants to transfer stuff of a previously required module from the current state to another Lane, the module must be registered
2163// to populate the lookup database in the source lane (and in the destination too, of course)
2164// lanes.register( "modname", module)
2165LUAG_FUNC( register)
2166{
2167 char const* name = luaL_checkstring( L, 1);
2168 int const nargs = lua_gettop( L);
2169 int const mod_type = lua_type( L, 2);
2170 // ignore extra parameters, just in case
2171 lua_settop( L, 2);
2172 luaL_argcheck( L, (mod_type == LUA_TTABLE) || (mod_type == LUA_TFUNCTION), 2, "unexpected module type");
2173 DEBUGSPEW_CODE( struct s_Universe* U = get_universe( L));
2174 STACK_CHECK( L); // "name" mod_table
2175 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name));
2176 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
2177 populate_func_lookup_table( L, -1, name);
2178 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END, name));
2179 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
2180 STACK_END( L, 0);
2181 return 0;
2182}
2183
2184
2160LUAG_FUNC( thread_gc); 2185LUAG_FUNC( thread_gc);
2161#define GCCB_KEY (void*)LG_thread_gc 2186#define GCCB_KEY (void*)LG_thread_gc
2162//--- 2187//---
@@ -2945,6 +2970,7 @@ static const struct luaL_Reg lanes_functions [] = {
2945 {"wakeup_conv", LG_wakeup_conv}, 2970 {"wakeup_conv", LG_wakeup_conv},
2946 {"set_thread_priority", LG_set_thread_priority}, 2971 {"set_thread_priority", LG_set_thread_priority},
2947 {"nameof", luaG_nameof}, 2972 {"nameof", luaG_nameof},
2973 {"register", LG_register},
2948 {"set_singlethreaded", LG_set_singlethreaded}, 2974 {"set_singlethreaded", LG_set_singlethreaded},
2949 {NULL, NULL} 2975 {NULL, NULL}
2950}; 2976};
@@ -3201,7 +3227,7 @@ LUAG_FUNC( configure)
3201 { 3227 {
3202 // don't do this when called during the initialization of a new lane, 3228 // don't do this when called during the initialization of a new lane,
3203 // because we will do it after on_state_create() is called, 3229 // because we will do it after on_state_create() is called,
3204 // and we don't want skip _G because of caching in case globals are created then 3230 // and we don't want to skip _G because of caching in case globals are created then
3205 lua_pushglobaltable( L); // settings M _G 3231 lua_pushglobaltable( L); // settings M _G
3206 populate_func_lookup_table( L, -1, NULL); 3232 populate_func_lookup_table( L, -1, NULL);
3207 lua_pop( L, 1); // settings M 3233 lua_pop( L, 1); // settings M
diff --git a/src/lanes.lua b/src/lanes.lua
index 6cbbd65..35071ae 100644
--- a/src/lanes.lua
+++ b/src/lanes.lua
@@ -40,9 +40,8 @@ local core = require "lanes.core"
40-- Lua 5.2: module() is gone 40-- Lua 5.2: module() is gone
41-- almost everything module() does is done by require() anyway 41-- almost everything module() does is done by require() anyway
42-- -> simply create a table, populate it, return it, and be done 42-- -> simply create a table, populate it, return it, and be done
43local lanes = {}
44local lanesMeta = {} 43local lanesMeta = {}
45setmetatable(lanes,lanesMeta) 44local lanes = setmetatable( {}, lanesMeta)
46 45
47-- this function is available in the public interface until it is called, after which it disappears 46-- this function is available in the public interface until it is called, after which it disappears
48lanes.configure = function( settings_) 47lanes.configure = function( settings_)
@@ -55,7 +54,7 @@ lanes.configure = function( settings_)
55 error( "To use 'lanes', you will also need to have 'string' available.", 2) 54 error( "To use 'lanes', you will also need to have 'string' available.", 2)
56 end 55 end
57 -- Configure called so remove metatable from lanes 56 -- Configure called so remove metatable from lanes
58 setmetatable(lanes,nil) 57 setmetatable( lanes, nil)
59 -- 58 --
60 -- Cache globals for code that might run under sandboxing 59 -- Cache globals for code that might run under sandboxing
61 -- 60 --
@@ -139,7 +138,7 @@ lanes.configure = function( settings_)
139 author= "Asko Kauppi <akauppi@gmail.com>, Benoit Germain <bnt.germain@gmail.com>", 138 author= "Asko Kauppi <akauppi@gmail.com>, Benoit Germain <bnt.germain@gmail.com>",
140 description= "Running multiple Lua states in parallel", 139 description= "Running multiple Lua states in parallel",
141 license= "MIT/X11", 140 license= "MIT/X11",
142 copyright= "Copyright (c) 2007-10, Asko Kauppi; (c) 2011-13, Benoit Germain", 141 copyright= "Copyright (c) 2007-10, Asko Kauppi; (c) 2011-17, Benoit Germain",
143 version = assert( core.version) 142 version = assert( core.version)
144 } 143 }
145 144
@@ -220,6 +219,9 @@ lanes.configure = function( settings_)
220 ["debug"] = true, 219 ["debug"] = true,
221 ["bit32"] = true, -- Lua 5.2 only, ignored silently under 5.1 220 ["bit32"] = true, -- Lua 5.2 only, ignored silently under 5.1
222 ["utf8"] = true, -- Lua 5.3 only, ignored silently under 5.1 and 5.2 221 ["utf8"] = true, -- Lua 5.3 only, ignored silently under 5.1 and 5.2
222 ["bit"] = true, -- LuaJIT only, ignored silently under PUC-Lua
223 ["jit"] = true, -- LuaJIT only, ignored silently under PUC-Lua
224 ["ffi"] = true, -- LuaJIT only, ignored silently under PUC-Lua
223 -- 225 --
224 ["base"] = true, 226 ["base"] = true,
225 ["coroutine"] = true, -- part of "base" in Lua 5.1 227 ["coroutine"] = true, -- part of "base" in Lua 5.1
@@ -713,6 +715,7 @@ lanes.configure = function( settings_)
713 715
714 -- activate full interface 716 -- activate full interface
715 lanes.require = core.require 717 lanes.require = core.require
718 lanes.register = core.register
716 lanes.gen = gen 719 lanes.gen = gen
717 lanes.linda = core.linda 720 lanes.linda = core.linda
718 lanes.cancel_error = core.cancel_error 721 lanes.cancel_error = core.cancel_error
@@ -731,20 +734,18 @@ lanes.configure = function( settings_)
731 return lanes 734 return lanes
732end -- lanes.configure 735end -- lanes.configure
733 736
734lanesMeta.__index = function(t,k) 737lanesMeta.__index = function( t, k)
735 -- This is called when some functionality is accessed without calling configure() 738 -- This is called when some functionality is accessed without calling configure()
736 lanes.configure() -- Initialize with default settings 739 lanes.configure() -- initialize with default settings
737 -- Access the required key 740 -- Access the required key
738 return lanes[k] 741 return lanes[k]
739end 742end
740 743
741-- no need to force calling configure() excepted the first time 744-- no need to force calling configure() manually excepted the first time (other times will reuse the internally stored settings of the first call)
742if core.settings then 745if core.settings then
743 return lanes.configure() 746 return lanes.configure()
744else 747else
745 return lanes 748 return lanes
746end 749end
747 750
748 751--the end
749--the end (Unreachable Code)
750--return lanes
diff --git a/src/tools.c b/src/tools.c
index f1b0372..c2491ba 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -8,7 +8,7 @@
8=============================================================================== 8===============================================================================
9 9
10Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com> 10Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com>
11 2011-14 benoit Germain <bnt.germain@gmail.com> 11 2011-17 benoit Germain <bnt.germain@gmail.com>
12 12
13Permission is hereby granted, free of charge, to any person obtaining a copy 13Permission is hereby granted, free of charge, to any person obtaining a copy
14of this software and associated documentation files (the "Software"), to deal 14of this software and associated documentation files (the "Software"), to deal
@@ -71,48 +71,52 @@ DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!--
71 71
72/*---=== luaG_dump ===---*/ 72/*---=== luaG_dump ===---*/
73 73
74void luaG_dump( lua_State* L ) { 74void luaG_dump( lua_State* L)
75 75{
76 int top= lua_gettop(L); 76 int top = lua_gettop( L);
77 int i; 77 int i;
78 78
79 fprintf( stderr, "\n\tDEBUG STACK:\n" ); 79 fprintf( stderr, "\n\tDEBUG STACK:\n");
80 80
81 if (top==0) 81 if( top == 0)
82 fprintf( stderr, "\t(none)\n" ); 82 fprintf( stderr, "\t(none)\n");
83 83
84 for( i=1; i<=top; i++ ) { 84 for( i = 1; i <= top; ++ i)
85 int type= lua_type( L, i ); 85 {
86 int type = lua_type( L, i);
86 87
87 fprintf( stderr, "\t[%d]= (%s) ", i, lua_typename(L,type) ); 88 fprintf( stderr, "\t[%d]= (%s) ", i, lua_typename( L, type));
88 89
89 // Print item contents here... 90 // Print item contents here...
90 // 91 //
91 // Note: this requires 'tostring()' to be defined. If it is NOT, 92 // Note: this requires 'tostring()' to be defined. If it is NOT,
92 // enable it for more debugging. 93 // enable it for more debugging.
93 // 94 //
94 STACK_CHECK( L); 95 STACK_CHECK( L);
95 STACK_GROW( L, 2); 96 STACK_GROW( L, 2);
96 97
97 lua_getglobal( L, "tostring" ); 98 lua_getglobal( L, "tostring");
98 // 99 //
99 // [-1]: tostring function, or nil 100 // [-1]: tostring function, or nil
100 101
101 if (!lua_isfunction(L,-1)) { 102 if( !lua_isfunction( L, -1))
102 fprintf( stderr, "('tostring' not available)" ); 103 {
103 } else { 104 fprintf( stderr, "('tostring' not available)");
104 lua_pushvalue( L, i );
105 lua_call( L, 1 /*args*/, 1 /*retvals*/ );
106
107 // Don't trust the string contents
108 //
109 fprintf( stderr, "%s", lua_tostring(L,-1) );
110 }
111 lua_pop(L,1);
112 STACK_END( L, 0);
113 fprintf( stderr, "\n" );
114 } 105 }
115 fprintf( stderr, "\n" ); 106 else
107 {
108 lua_pushvalue( L, i);
109 lua_call( L, 1 /*args*/, 1 /*retvals*/);
110
111 // Don't trust the string contents
112 //
113 fprintf( stderr, "%s", lua_tostring( L, -1));
114 }
115 lua_pop( L, 1);
116 STACK_END( L, 0);
117 fprintf( stderr, "\n");
118 }
119 fprintf( stderr, "\n");
116} 120}
117 121
118void initialize_on_state_create( struct s_Universe* U, lua_State* L) 122void initialize_on_state_create( struct s_Universe* U, lua_State* L)
@@ -206,6 +210,14 @@ static const luaL_Reg libs[] =
206 { LUA_COLIBNAME, NULL}, // Lua 5.1: part of base package 210 { LUA_COLIBNAME, NULL}, // Lua 5.1: part of base package
207#endif // LUA_VERSION_NUM 211#endif // LUA_VERSION_NUM
208 { LUA_DBLIBNAME, luaopen_debug}, 212 { LUA_DBLIBNAME, luaopen_debug},
213#if defined LUA_JITLIBNAME // building against LuaJIT headers, add some LuaJIT-specific libs
214//#pragma message( "supporting JIT base libs")
215 { LUA_BITLIBNAME, luaopen_bit},
216 { LUA_JITLIBNAME, luaopen_jit},
217 { LUA_FFILIBNAME, luaopen_ffi},
218#endif // LUA_JITLIBNAME
219
220 { LUA_DBLIBNAME, luaopen_debug},
209 { "lanes.core", require_lanes_core}, // So that we can open it like any base library (possible since we have access to the init function) 221 { "lanes.core", require_lanes_core}, // So that we can open it like any base library (possible since we have access to the init function)
210 // 222 //
211 { "base", NULL}, // ignore "base" (already acquired it) 223 { "base", NULL}, // ignore "base" (already acquired it)
@@ -246,7 +258,8 @@ static void open1lib( struct s_Universe* U, lua_State* L, char const* name_, siz
246 } 258 }
247} 259}
248 260
249static int dummy_writer(lua_State *L, const void* p, size_t sz, void* ud) 261
262static int dummy_writer( lua_State* L, void const* p, size_t sz, void* ud)
250{ 263{
251 (void)L; (void)p; (void)sz; (void) ud; // unused 264 (void)L; (void)p; (void)sz; (void) ud; // unused
252 return 666; 265 return 666;
@@ -314,12 +327,12 @@ static lua_CFunction luaG_tocfunction( lua_State *L, int _i, FuncSubType *_out)
314 327
315 328
316// inspired from tconcat() in ltablib.c 329// inspired from tconcat() in ltablib.c
317static char const* luaG_pushFQN(lua_State *L, int t, int last, size_t* length) 330static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length)
318{ 331{
319 int i = 1; 332 int i = 1;
320 luaL_Buffer b; 333 luaL_Buffer b;
321 STACK_CHECK( L); 334 STACK_CHECK( L);
322 luaL_buffinit(L, &b); 335 luaL_buffinit( L, &b);
323 for( ; i < last; ++ i) 336 for( ; i < last; ++ i)
324 { 337 {
325 lua_rawgeti( L, t, i); 338 lua_rawgeti( L, t, i);
@@ -336,12 +349,89 @@ static char const* luaG_pushFQN(lua_State *L, int t, int last, size_t* length)
336 return lua_tolstring( L, -1, length); 349 return lua_tolstring( L, -1, length);
337} 350}
338 351
352/*
353 * receives 2 arguments: a name k and an object o
354 * add two entries ["fully.qualified.name"] = o
355 * and [o] = "fully.qualified.name"
356 * where <o> is either a table or a function
357 * if we already had an entry of type [o] = ..., replace the name if the new one is shorter
358 * pops the processed object from the stack
359 */
360static void update_lookup_entry( lua_State* L, int _ctx_base, int _depth)
361{
362 // slot 1 in the stack contains the table that receives everything we found
363 int const dest = _ctx_base;
364 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i
365 int const fqn = _ctx_base + 1;
366
367 size_t prevNameLength, newNameLength;
368 char const* prevName;
369 DEBUGSPEW_CODE( char const *newName);
370 DEBUGSPEW_CODE( struct s_Universe* U = get_universe( L));
371
372 STACK_CHECK( L);
373 // first, raise an error if the function is already known
374 lua_pushvalue( L, -1); // ... {bfc} k o o
375 lua_rawget( L, dest); // ... {bfc} k o name?
376 prevName = lua_tolstring( L, -1, &prevNameLength); // NULL if we got nil (first encounter of this object)
377 // push name in fqn stack (note that concatenation will crash if name is a not string or a number)
378 lua_pushvalue( L, -3); // ... {bfc} k o name? k
379 ASSERT_L( lua_type( L, -1) == LUA_TNUMBER || lua_type( L, -1) == LUA_TSTRING);
380 ++ _depth;
381 lua_rawseti( L, fqn, _depth); // ... {bfc} k o name?
382 // generate name
383 DEBUGSPEW_CODE( newName =) luaG_pushFQN( L, fqn, _depth, &newNameLength); // ... {bfc} k o name? "f.q.n"
384 // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order
385 // on different VMs even when the tables are populated the exact same way.
386 // When Lua is built with compatibility options (such as LUA_COMPAT_ALL),
387 // this causes several base libraries to register functions under multiple names.
388 // This, with the randomizer, can cause the first generated name of an object to be different on different VMs,
389 // which breaks function transfer.
390 // Also, nothing prevents any external module from exposing a given object under several names, so...
391 // Therefore, when we encounter an object for which a name was previously registered, we need to select the names
392 // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded
393 if( prevName != NULL && (prevNameLength < newNameLength || lua_lessthan( L, -2, -1)))
394 {
395 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s' remained named '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -3)), newName, prevName));
396 // the previous name is 'smaller' than the one we just generated: keep it!
397 lua_pop( L, 3); // ... {bfc} k
398 }
399 else
400 {
401 // the name we generated is either the first one, or a better fit for our purposes
402 if( prevName)
403 {
404 // clear the previous name for the database to avoid clutter
405 lua_insert( L, -2); // ... {bfc} k o "f.q.n" prevName
406 // t[prevName] = nil
407 lua_pushnil( L); // ... {bfc} k o "f.q.n" prevName nil
408 lua_rawset( L, dest); // ... {bfc} k o "f.q.n"
409 }
410 else
411 {
412 lua_remove( L, -2); // ... {bfc} k o "f.q.n"
413 }
414 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -2)), newName));
415 // prepare the stack for database feed
416 lua_pushvalue( L, -1); // ... {bfc} k o "f.q.n" "f.q.n"
417 lua_pushvalue( L, -3); // ... {bfc} k o "f.q.n" "f.q.n" o
418 ASSERT_L( lua_rawequal( L, -1, -4));
419 ASSERT_L( lua_rawequal( L, -2, -3));
420 // t["f.q.n"] = o
421 lua_rawset( L, dest); // ... {bfc} k o "f.q.n"
422 // t[o] = "f.q.n"
423 lua_rawset( L, dest); // ... {bfc} k
424 // remove table name from fqn stack
425 lua_pushnil( L); // ... {bfc} k nil
426 lua_rawseti( L, fqn, _depth); // ... {bfc} k
427 }
428 -- _depth;
429 STACK_END( L, -1);
430}
339 431
340static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _i, int _depth) 432static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _i, int _depth)
341{ 433{
342 lua_Integer visit_count; 434 lua_Integer visit_count;
343 // slot 1 in the stack contains the table that receives everything we found
344 int const dest = _ctx_base;
345 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i 435 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i
346 int const fqn = _ctx_base + 1; 436 int const fqn = _ctx_base + 1;
347 // slot 3 contains a cache that stores all already visited tables to avoid infinite recursion loops 437 // slot 3 contains a cache that stores all already visited tables to avoid infinite recursion loops
@@ -400,69 +490,15 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _
400 lua_rawset( L, cache); // ... {_i} {bfc} k {} 490 lua_rawset( L, cache); // ... {_i} {bfc} k {}
401 // store the table in the breadth-first cache 491 // store the table in the breadth-first cache
402 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k 492 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k
403 lua_insert( L, -2); // ... {_i} {bfc} k k {} 493 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k {}
404 lua_rawset( L, breadth_first_cache); // ... {_i} {bfc} k 494 lua_rawset( L, breadth_first_cache); // ... {_i} {bfc} k {}
495 // generate a name, and if we already had one name, keep whichever is the shorter
496 update_lookup_entry( L, _ctx_base, _depth); // ... {_i} {bfc} k
405 } 497 }
406 else if( lua_isfunction( L, -1) && (luaG_getfuncsubtype( L, -1) != FST_Bytecode)) // ... {_i} {bfc} k func 498 else if( lua_isfunction( L, -1) && (luaG_getfuncsubtype( L, -1) != FST_Bytecode)) // ... {_i} {bfc} k func
407 { 499 {
408 size_t prevNameLength, newNameLength; 500 // generate a name, and if we already had one name, keep whichever is the shorter
409 char const* prevName; 501 update_lookup_entry( L, _ctx_base, _depth); // ... {_i} {bfc} k
410 DEBUGSPEW_CODE( char const *newName);
411 // first, raise an error if the function is already known
412 lua_pushvalue( L, -1); // ... {_i} {bfc} k func func
413 lua_rawget( L, dest); // ... {_i} {bfc} k func name?
414 prevName = lua_tolstring( L, -1, &prevNameLength); // NULL if we got nil (first encounter of this function)
415 // push function name in fqn stack (note that concatenation will crash if name is a not string or a number)
416 lua_pushvalue( L, -3); // ... {_i} {bfc} k func name? k
417 ++ _depth;
418 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k func name?
419 // generate name
420 DEBUGSPEW_CODE( newName =) luaG_pushFQN( L, fqn, _depth, &newNameLength); // ... {_i} {bfc} k func name? "f.q.n"
421 // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order
422 // on different VMs even when the tables are populated the exact same way.
423 // When Lua is built with compatibility options (such as LUA_COMPAT_ALL),
424 // this causes several base libraries to register functions under multiple names.
425 // This, with the randomizer, can cause the first name of a function to be different on different VMs,
426 // which breaks function transfer.
427 // Also, nothing prevents any external module from exposing a given function under several names, so...
428 // Therefore, when we encounter a function for which a name was previously registered, we need to select the names
429 // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded
430 if( prevName != NULL && (prevNameLength < newNameLength || lua_lessthan( L, -2, -1)))
431 {
432 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function '%s' remained named '%s'\n" INDENT_END, newName, prevName));
433 // the previous name is 'smaller' than the one we just generated: keep it!
434 lua_pop( L, 3); // ... {_i} {bfc} k
435 }
436 else
437 {
438 // the name we generated is either the first one, or a better fit for our purposes
439 if( prevName)
440 {
441 // clear the previous name for the database to avoid clutter
442 lua_insert( L, -2); // ... {_i} {bfc} k func "f.q.n" prevName
443 // t[prevName] = nil
444 lua_pushnil( L); // ... {_i} {bfc} k func "f.q.n" prevName nil
445 lua_rawset( L, dest); // ... {_i} {bfc} k func "f.q.n"
446 }
447 else
448 {
449 lua_remove( L, -2); // ... {_i} {bfc} k func "f.q.n"
450 }
451 // prepare the stack for database feed
452 lua_pushvalue( L, -1); // ... {_i} {bfc} k func "f.q.n" "f.q.n"
453 lua_pushvalue( L, -3); // ... {_i} {bfc} k func "f.q.n" "f.q.n" func
454 ASSERT_L( lua_rawequal( L, -1, -4));
455 ASSERT_L( lua_rawequal( L, -2, -3));
456 // t["f.q.n"] = func
457 lua_rawset( L, dest); // ... {_i} {bfc} k func "f.q.n"
458 // t[func] = "f.q.n"
459 lua_rawset( L, dest); // ... {_i} {bfc} k
460 // remove table name from fqn stack
461 lua_pushnil( L); // ... {_i} {bfc} k nil
462 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k
463 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function '%s'\n" INDENT_END, newName));
464 }
465 -- _depth;
466 } 502 }
467 else 503 else
468 { 504 {
@@ -519,7 +555,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_)
519{ 555{
520 int const ctx_base = lua_gettop( L) + 1; 556 int const ctx_base = lua_gettop( L) + 1;
521 int const in_base = lua_absindex( L, _i); 557 int const in_base = lua_absindex( L, _i);
522 int const start_depth = name_ ? 1 : 0; 558 int start_depth = 0;
523 DEBUGSPEW_CODE( struct s_Universe* U = get_universe( L)); 559 DEBUGSPEW_CODE( struct s_Universe* U = get_universe( L));
524 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL")); 560 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL"));
525 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 561 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
@@ -543,9 +579,17 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_)
543 lua_newtable( L); // {} {fqn} 579 lua_newtable( L); // {} {fqn}
544 if( name_) 580 if( name_)
545 { 581 {
582 STACK_MID( L, 2);
546 lua_pushstring( L, name_); // {} {fqn} "name" 583 lua_pushstring( L, name_); // {} {fqn} "name"
584 // generate a name, and if we already had one name, keep whichever is the shorter
585 lua_pushvalue( L, in_base); // {} {fqn} "name" t
586 update_lookup_entry( L, ctx_base, start_depth); // {} {fqn} "name"
587 // don't forget to store the name at the bottom of the fqn stack
588 ++ start_depth;
547 lua_rawseti( L, -2, start_depth); // {} {fqn} 589 lua_rawseti( L, -2, start_depth); // {} {fqn}
590 STACK_MID( L, 2);
548 } 591 }
592 // retrieve the cache, create it if we haven't done it yet
549 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY_CACHE); // {} {fqn} {cache}? 593 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY_CACHE); // {} {fqn} {cache}?
550 if( lua_isnil( L, -1)) 594 if( lua_isnil( L, -1))
551 { 595 {
@@ -554,6 +598,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_)
554 lua_pushvalue( L, -1); // {} {fqn} {cache} {cache} 598 lua_pushvalue( L, -1); // {} {fqn} {cache} {cache}
555 lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY_CACHE); // {} {fqn} {cache} 599 lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY_CACHE); // {} {fqn} {cache}
556 } 600 }
601 // process everything we find in that table, filling in lookup data for all functions and tables we see there
557 populate_func_lookup_table_recur( L, ctx_base, in_base, start_depth); // {...} {fqn} {cache} 602 populate_func_lookup_table_recur( L, ctx_base, in_base, start_depth); // {...} {fqn} {cache}
558 lua_pop( L, 3); 603 lua_pop( L, 3);
559 } 604 }
@@ -795,6 +840,158 @@ static int buf_writer( lua_State *L, const void* b, size_t n, void* B ) {
795} 840}
796 841
797 842
843// function sentinel used to transfer native functions from/to keeper states
844static int func_lookup_sentinel( lua_State* L)
845{
846 return luaL_error( L, "function lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
847}
848
849
850// function sentinel used to transfer native table from/to keeper states
851static int table_lookup_sentinel( lua_State* L)
852{
853 return luaL_error( L, "table lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex(1)));
854}
855
856/*
857 * retrieve the name of a function/table in the lookup database
858 */
859static char const* find_lookup_name( lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_, size_t* len_)
860{
861 DEBUGSPEW_CODE( struct s_Universe* const U = get_universe( L));
862 char const* fqn;
863 ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ...
864 STACK_CHECK( L);
865 STACK_GROW( L, 3); // up to 3 slots are necessary on error
866 if( mode_ == eLM_FromKeeper)
867 {
868 lua_CFunction f = lua_tocfunction( L, i); // should *always* be func_lookup_sentinel or table_lookup_sentinel!
869 if( f == func_lookup_sentinel || f == table_lookup_sentinel)
870 {
871 lua_getupvalue( L, i, 1); // ... v ... "f.q.n"
872 }
873 else
874 {
875 // if this is not a sentinel, this is some user-created table we wanted to lookup
876 ASSERT_L( NULL == f && lua_istable( L, i));
877 // push anything that will convert to NULL string
878 lua_pushnil( L); // ... v ... nil
879 }
880 }
881 else
882 {
883 // fetch the name from the source state's lookup table
884 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // ... v ... {}
885 ASSERT_L( lua_istable( L, -1));
886 lua_pushvalue( L, i); // ... v ... {} v
887 lua_rawget( L, -2); // ... v ... {} "f.q.n"
888 }
889 fqn = lua_tolstring( L, -1, len_);
890 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn));
891 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database
892 lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... v ...
893 STACK_MID( L, 0);
894 if( NULL == fqn && !lua_istable( L, i)) // raise an error if we try to send an unknown function (but not for tables)
895 {
896 char const *from, *typewhat, *what, *gotchaA, *gotchaB;
897 // try to discover the name of the function we want to send
898 lua_getglobal( L, "decoda_name"); // ... v ... decoda_name
899 from = lua_tostring( L, -1);
900 lua_pushcfunction( L, luaG_nameof); // ... v ... decoda_name luaG_nameof
901 lua_pushvalue( L, i); // ... v ... decoda_name luaG_nameof t
902 lua_call( L, 1, 2); // ... v ... decoda_name "type" "name"|nil
903 typewhat = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : luaL_typename( L, -2);
904 // second return value can be nil if the table was not found
905 // probable reason: the function was removed from the source Lua state before Lanes was required.
906 if( lua_isnil( L, -1))
907 {
908 gotchaA = " referenced by";
909 gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)";
910 what = upName_;
911 }
912 else
913 {
914 gotchaA = "";
915 gotchaB = "";
916 what = (lua_type( L, -1) == LUA_TSTRING) ? lua_tostring( L, -1) : luaL_typename( L, -1);
917 }
918 (void) luaL_error( L, "%s%s '%s' not found in %s origin transfer database.%s", typewhat, gotchaA, what, from ? from : "main", gotchaB);
919 *len_ = 0;
920 return NULL;
921 }
922 STACK_END( L, 0);
923 return fqn;
924}
925
926
927/*
928 * Push a looked-up table, or nothing if we found nothing
929 */
930static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_)
931{
932 // get the name of the table we want to send
933 size_t len;
934 char const* fqn = find_lookup_name( L, i, mode_, upName_, &len);
935 if( NULL == fqn) // name not found, it is some user-created table
936 {
937 return FALSE;
938 }
939 // push the equivalent table in the destination's stack, retrieved from the lookup table
940 STACK_CHECK( L2); // L // L2
941 STACK_GROW( L2, 3); // up to 3 slots are necessary on error
942 switch( mode_)
943 {
944 default: // shouldn't happen, in theory...
945 (void) luaL_error( L, "internal error: unknown lookup mode");
946 return FALSE;
947
948 case eLM_ToKeeper:
949 // push a sentinel closure that holds the lookup name as upvalue
950 lua_pushlstring( L2, fqn, len); // "f.q.n"
951 lua_pushcclosure( L2, table_lookup_sentinel, 1); // f
952 break;
953
954 case eLM_LaneBody:
955 case eLM_FromKeeper:
956 lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {}
957 ASSERT_L( lua_istable( L2, -1));
958 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
959 lua_rawget( L2, -2); // {} t
960 // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead)
961 // but not when we extract something out of a keeper, as there is nothing to clone!
962 if( lua_isnil( L2, -1) && mode_ == eLM_LaneBody)
963 {
964 lua_pop( L2, 2); //
965 STACK_MID( L2, 0);
966 return FALSE;
967 }
968 else if( !lua_istable( L2, -1))
969 {
970 char const* from, *to;
971 lua_getglobal( L, "decoda_name"); // ... t ... decoda_name
972 from = lua_tostring( L, -1);
973 lua_pop( L, 1); // ... t ...
974 lua_getglobal( L2, "decoda_name"); // {} t decoda_name
975 to = lua_tostring( L2, -1);
976 lua_pop( L2, 1); // {} t
977 // when mode_ == eLM_FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error
978 (void) luaL_error(
979 (mode_ == eLM_FromKeeper) ? L2 : L
980 , "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database."
981 , from ? from : "main"
982 , fqn
983 , to ? to : "main"
984 );
985 return FALSE;
986 }
987 lua_remove( L2, -2); // t
988 break;
989 }
990 STACK_END( L2, 1);
991 return TRUE;
992}
993
994
798/* 995/*
799 * Check if we've already copied the same table from 'L', and 996 * Check if we've already copied the same table from 'L', and
800 * reuse the old copy. This allows table upvalues shared by multiple 997 * reuse the old copy. This allows table upvalues shared by multiple
@@ -805,60 +1002,35 @@ static int buf_writer( lua_State *L, const void* b, size_t n, void* B ) {
805 * Returns TRUE if the table was cached (no need to fill it!); FALSE if 1002 * Returns TRUE if the table was cached (no need to fill it!); FALSE if
806 * it's a virgin. 1003 * it's a virgin.
807 */ 1004 */
808static bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) 1005static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i)
809{ 1006{
810 bool_t ret; 1007 bool_t not_found_in_cache; // L2
1008 void* const p = (void*)lua_topointer( L, i);
811 1009
812 ASSERT_L( L2_cache_i != 0 ); 1010 ASSERT_L( L2_cache_i != 0);
813 1011 STACK_GROW( L2, 3);
814 STACK_GROW(L2,3);
815
816 // L2_cache[id_str]= [{...}]
817 //
818 STACK_CHECK( L2); 1012 STACK_CHECK( L2);
819 1013
820 // We don't need to use the from state ('L') in ID since the life span 1014 // We don't need to use the from state ('L') in ID since the life span
821 // is only for the duration of a copy (both states are locked). 1015 // is only for the duration of a copy (both states are locked).
822 // 1016 // push a light userdata uniquely representing the table
823 lua_pushlightuserdata( L2, (void*)lua_topointer( L, i )); // push a light userdata uniquely representing the table 1017 lua_pushlightuserdata( L2, p); // ... p
824
825 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
826 1018
827 lua_pushvalue( L2, -1 ); 1019 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1));
828 lua_rawget( L2, L2_cache_i );
829 //
830 // [-2]: identity table pointer lightuserdata
831 // [-1]: table|nil
832 1020
833 if (lua_isnil(L2,-1)) 1021 lua_rawget( L2, L2_cache_i); // ... {cached|nil}
1022 not_found_in_cache = lua_isnil( L2, -1);
1023 if( not_found_in_cache)
834 { 1024 {
835 lua_pop(L2,1); 1025 lua_pop( L2, 1); // ...
836 lua_newtable(L2); 1026 lua_newtable( L2); // ... {}
837 lua_pushvalue(L2,-1); 1027 lua_pushlightuserdata( L2, p); // ... {} p
838 lua_insert(L2,-3); 1028 lua_pushvalue( L2, -2); // ... {} p {}
839 // 1029 lua_rawset( L2, L2_cache_i); // ... {}
840 // [-3]: new table (2nd ref)
841 // [-2]: identity table pointer lightuserdata
842 // [-1]: new table
843
844 lua_rawset(L2, L2_cache_i);
845 //
846 // [-1]: new table (tied to 'L2_cache' table')
847
848 ret= FALSE; // brand new
849
850 }
851 else
852 {
853 lua_remove(L2,-2);
854 ret= TRUE; // from cache
855 } 1030 }
856 STACK_END( L2, 1); 1031 STACK_END( L2, 1);
857 // 1032 ASSERT_L( lua_istable( L2, -1));
858 // L2 [-1]: table to use as destination 1033 return !not_found_in_cache;
859
860 ASSERT_L( lua_istable(L2,-1) );
861 return ret;
862} 1034}
863 1035
864 1036
@@ -999,6 +1171,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_)
999 return shortest_; 1171 return shortest_;
1000} 1172}
1001 1173
1174
1002/* 1175/*
1003 * "type", "name" = lanes.nameof( o) 1176 * "type", "name" = lanes.nameof( o)
1004 */ 1177 */
@@ -1046,72 +1219,17 @@ int luaG_nameof( lua_State* L)
1046 return 2; 1219 return 2;
1047} 1220}
1048 1221
1049// function sentinel used to transfer native functions from/to keeper states
1050static int sentinelfunc( lua_State* L)
1051{
1052 return luaL_error( L, "transfer sentinel function for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
1053}
1054 1222
1055/* 1223/*
1056* Push a looked-up native/LuaJIT function. 1224 * Push a looked-up native/LuaJIT function.
1057*/ 1225 */
1058static void lookup_native_func( struct s_Universe* U, lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_) 1226static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_)
1059{ 1227{
1060 char const* fqn; // L // L2 1228 // get the name of the function we want to send
1061 size_t len; 1229 size_t len;
1062 ASSERT_L( lua_isfunction( L, i)); // ... f ... 1230 char const* fqn = find_lookup_name( L, i, mode_, upName_, &len);
1063 STACK_CHECK( L);
1064 STACK_GROW( L, 3); // up to 3 slots are necessary on error
1065 if( mode_ == eLM_FromKeeper)
1066 {
1067 lua_CFunction f = lua_tocfunction( L, i); // should *always* be sentinelfunc!
1068 ASSERT_L( f == sentinelfunc);
1069 lua_getupvalue( L, i, 1); // ... f ... "f.q.n"
1070 fqn = lua_tolstring( L, -1, &len);
1071 }
1072 else
1073 {
1074 // fetch the name from the source state's lookup table
1075 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // ... f ... {}
1076 ASSERT_L( lua_istable( L, -1));
1077 lua_pushvalue( L, i); // ... f ... {} f
1078 lua_rawget( L, -2); // ... f ... {} "f.q.n"
1079 fqn = lua_tolstring( L, -1, &len);
1080 }
1081 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn));
1082 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database
1083 lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... f ...
1084 STACK_MID( L, 0);
1085 if( !fqn)
1086 {
1087 char const *from, *typewhat, *what, *gotchaA, *gotchaB;
1088 // try to discover the name of the function we want to send
1089 lua_getglobal( L, "decoda_name"); // ... f ... decoda_name
1090 from = lua_tostring( L, -1);
1091 lua_pushcfunction( L, luaG_nameof); // ... f ... decoda_name luaG_nameof
1092 lua_pushvalue( L, i); // ... f ... decoda_name luaG_nameof f
1093 lua_call( L, 1, 2); // ... f ... decoda_name "type" "name"|nil
1094 typewhat = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : luaL_typename( L, -2);
1095 // second return value can be nil if the function was not found
1096 // probable reason: the function was removed from the source Lua state before Lanes was required.
1097 if( lua_isnil( L, -1))
1098 {
1099 gotchaA = " referenced by";
1100 gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)";
1101 what = upName_;
1102 }
1103 else
1104 {
1105 gotchaA = "";
1106 gotchaB = "";
1107 what = (lua_type( L, -1) == LUA_TSTRING) ? lua_tostring( L, -1) : luaL_typename( L, -1);
1108 }
1109 (void) luaL_error( L, "%s%s '%s' not found in %s origin transfer database.%s", typewhat, gotchaA, what, from ? from : "main", gotchaB);
1110 return;
1111 }
1112 STACK_END( L, 0);
1113 // push the equivalent function in the destination's stack, retrieved from the lookup table 1231 // push the equivalent function in the destination's stack, retrieved from the lookup table
1114 STACK_CHECK( L2); 1232 STACK_CHECK( L2); // L // L2
1115 STACK_GROW( L2, 3); // up to 3 slots are necessary on error 1233 STACK_GROW( L2, 3); // up to 3 slots are necessary on error
1116 switch( mode_) 1234 switch( mode_)
1117 { 1235 {
@@ -1122,7 +1240,7 @@ static void lookup_native_func( struct s_Universe* U, lua_State* L2, lua_State*
1122 case eLM_ToKeeper: 1240 case eLM_ToKeeper:
1123 // push a sentinel closure that holds the lookup name as upvalue 1241 // push a sentinel closure that holds the lookup name as upvalue
1124 lua_pushlstring( L2, fqn, len); // "f.q.n" 1242 lua_pushlstring( L2, fqn, len); // "f.q.n"
1125 lua_pushcclosure( L2, sentinelfunc, 1); // f 1243 lua_pushcclosure( L2, func_lookup_sentinel, 1); // f
1126 break; 1244 break;
1127 1245
1128 case eLM_LaneBody: 1246 case eLM_LaneBody:
@@ -1131,15 +1249,26 @@ static void lookup_native_func( struct s_Universe* U, lua_State* L2, lua_State*
1131 ASSERT_L( lua_istable( L2, -1)); 1249 ASSERT_L( lua_istable( L2, -1));
1132 lua_pushlstring( L2, fqn, len); // {} "f.q.n" 1250 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
1133 lua_rawget( L2, -2); // {} f 1251 lua_rawget( L2, -2); // {} f
1134 if( !lua_isfunction( L2, -1)) 1252 // nil means we don't know how to transfer stuff: user should do something
1253 // anything other than function or table should not happen!
1254 if( !lua_isfunction( L2, -1) && !lua_istable( L2, -1))
1135 { 1255 {
1136 char const* from, * to; 1256 char const* from, * to;
1137 lua_getglobal( L, "decoda_name"); // ... f ... decoda_name 1257 lua_getglobal( L, "decoda_name"); // ... f ... decoda_name
1138 from = lua_tostring( L, -1); 1258 from = lua_tostring( L, -1);
1259 lua_pop( L, 1); // ... f ...
1139 lua_getglobal( L2, "decoda_name"); // {} f decoda_name 1260 lua_getglobal( L2, "decoda_name"); // {} f decoda_name
1140 to = lua_tostring( L2, -1); 1261 to = lua_tostring( L2, -1);
1262 lua_pop( L2, 1); // {} f
1141 // when mode_ == eLM_FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error 1263 // when mode_ == eLM_FromKeeper, L is a keeper state and L2 is not, therefore L2 is the state where we want to raise the error
1142 (void) luaL_error( (mode_ == eLM_FromKeeper) ? L2 : L, "%s: function '%s' not found in %s destination transfer database.", from ? from : "main", fqn, to ? to : "main"); 1264 (void) luaL_error(
1265 (mode_ == eLM_FromKeeper) ? L2 : L
1266 , "%s%s: function '%s' not found in %s destination transfer database."
1267 , lua_isnil( L2, -1) ? "" : "INTERNAL ERROR IN "
1268 , from ? from : "main"
1269 , fqn
1270 , to ? to : "main"
1271 );
1143 return; 1272 return;
1144 } 1273 }
1145 lua_remove( L2, -2); // f 1274 lua_remove( L2, -2); // f
@@ -1164,6 +1293,7 @@ static void lookup_native_func( struct s_Universe* U, lua_State* L2, lua_State*
1164 STACK_END( L2, 1); 1293 STACK_END( L2, 1);
1165} 1294}
1166 1295
1296
1167/* 1297/*
1168 * Copy a function over, which has not been found in the cache. 1298 * Copy a function over, which has not been found in the cache.
1169 * L2 has the cache key for this function at the top of the stack 1299 * L2 has the cache key for this function at the top of the stack
@@ -1181,7 +1311,7 @@ static void inter_copy_func( struct s_Universe* U, lua_State* L2, uint_t L2_cach
1181 int n, needToPush; 1311 int n, needToPush;
1182 luaL_Buffer b; 1312 luaL_Buffer b;
1183 ASSERT_L( L2_cache_i != 0); // ... {cache} ... p 1313 ASSERT_L( L2_cache_i != 0); // ... {cache} ... p
1184 STACK_GROW(L,2); 1314 STACK_GROW( L, 2);
1185 STACK_CHECK( L); 1315 STACK_CHECK( L);
1186 1316
1187 // 'lua_dump()' needs the function at top of stack 1317 // 'lua_dump()' needs the function at top of stack
@@ -1223,7 +1353,7 @@ static void inter_copy_func( struct s_Universe* U, lua_State* L2, uint_t L2_cach
1223 lua_Debug ar; 1353 lua_Debug ar;
1224 lua_pushvalue( L, i); // ... b f 1354 lua_pushvalue( L, i); // ... b f
1225 // fills 'name' 'namewhat' and 'linedefined', pops function 1355 // fills 'name' 'namewhat' and 'linedefined', pops function
1226 lua_getinfo(L, ">nS", &ar); // ... b 1356 lua_getinfo( L, ">nS", &ar); // ... b
1227 name = ar.namewhat; 1357 name = ar.namewhat;
1228 fprintf( stderr, INDENT_BEGIN "FNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL 1358 fprintf( stderr, INDENT_BEGIN "FNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL
1229 } 1359 }
@@ -1348,12 +1478,12 @@ static void push_cached_func( struct s_Universe* U, lua_State* L2, uint_t L2_cac
1348 // push a light userdata uniquely representing the function 1478 // push a light userdata uniquely representing the function
1349 lua_pushlightuserdata( L2, aspointer); // ... {cache} ... p 1479 lua_pushlightuserdata( L2, aspointer); // ... {cache} ... p
1350 1480
1351 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) ); 1481 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1));
1352 1482
1353 lua_pushvalue( L2, -1); // ... {cache} ... p p 1483 lua_pushvalue( L2, -1); // ... {cache} ... p p
1354 lua_rawget( L2, L2_cache_i); // ... {cache} ... p function|nil|true 1484 lua_rawget( L2, L2_cache_i); // ... {cache} ... p function|nil|true
1355 1485
1356 if( lua_isnil(L2,-1)) // function is unknown 1486 if( lua_isnil( L2, -1)) // function is unknown
1357 { 1487 {
1358 lua_pop( L2, 1); // ... {cache} ... p 1488 lua_pop( L2, 1); // ... {cache} ... p
1359 1489
@@ -1368,15 +1498,14 @@ static void push_cached_func( struct s_Universe* U, lua_State* L2, uint_t L2_cac
1368 lua_remove( L2, -2); // ... {cache} ... function 1498 lua_remove( L2, -2); // ... {cache} ... function
1369 } 1499 }
1370 STACK_END( L2, 1); 1500 STACK_END( L2, 1);
1501 ASSERT_L( lua_isfunction( L2, -1));
1371 } 1502 }
1372 else // function is native/LuaJIT: no need to cache 1503 else // function is native/LuaJIT: no need to cache
1373 { 1504 {
1374 lookup_native_func( U, L2, L, i, mode_, upName_); // ... {cache} ... function 1505 lookup_native_func( L2, L, i, mode_, upName_); // ... {cache} ... function
1506 // if the function was in fact a lookup sentinel, we can either get a function or a table here
1507 ASSERT_L( lua_isfunction( L2, -1) || lua_istable( L2, -1));
1375 } 1508 }
1376
1377 //
1378 // L2 [-1]: function
1379 ASSERT_L( lua_isfunction( L2, -1));
1380} 1509}
1381 1510
1382/* 1511/*
@@ -1393,25 +1522,23 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca
1393{ 1522{
1394 bool_t ret = TRUE; 1523 bool_t ret = TRUE;
1395 bool_t ignore = FALSE; 1524 bool_t ignore = FALSE;
1525 int val_type = lua_type( L, i);
1396 STACK_GROW( L2, 1); 1526 STACK_GROW( L2, 1);
1397 STACK_CHECK( L2); 1527 STACK_CHECK( L2);
1398 1528
1399 /* Skip the object if it has metatable with { __lanesignore = true } */ 1529 /* Skip the object if it has metatable with { __lanesignore = true } */
1400 if( lua_getmetatable( L, i)) // ... mt 1530 if( lua_getmetatable( L, i)) // ... mt
1401 { 1531 {
1402 lua_pushstring( L, "__lanesignore"); // ... mt "__lanesignore" 1532 lua_getfield( L, -1, "__lanesignore"); // ... mt ignore?
1403 lua_gettable( L, -2); // ... mt ignore?
1404
1405 if( lua_isboolean( L, -1) && lua_toboolean( L, -1)) 1533 if( lua_isboolean( L, -1) && lua_toboolean( L, -1))
1406 { 1534 {
1407 ignore = TRUE; 1535 val_type = LUA_TNIL;
1408 } 1536 }
1409
1410 lua_pop( L, 2); // ... 1537 lua_pop( L, 2); // ...
1411 } 1538 }
1412 1539
1413 /* Lets push nil to L2 if the object should be ignored */ 1540 /* Lets push nil to L2 if the object should be ignored */
1414 switch( ignore ? LUA_TNIL : lua_type( L, i)) 1541 switch( val_type)
1415 { 1542 {
1416 /* Basic types allowed both as values, and as table keys */ 1543 /* Basic types allowed both as values, and as table keys */
1417 1544
@@ -1425,7 +1552,7 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca
1425 if( lua_isinteger( L, i)) 1552 if( lua_isinteger( L, i))
1426 { 1553 {
1427 lua_Integer v = lua_tointeger( L, i); 1554 lua_Integer v = lua_tointeger( L, i);
1428 DEBUGSPEW_CODE( if( vt == VT_KEY) fprintf( stderr, INDENT_BEGIN "KEY: %d\n" INDENT_END, v)); 1555 DEBUGSPEW_CODE( if( vt == VT_KEY) fprintf( stderr, INDENT_BEGIN "KEY: " LUA_INTEGER_FMT "\n" INDENT_END, v));
1429 lua_pushinteger( L2, v); 1556 lua_pushinteger( L2, v);
1430 break; 1557 break;
1431 } 1558 }
@@ -1448,7 +1575,7 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca
1448 break; 1575 break;
1449 1576
1450 case LUA_TLIGHTUSERDATA: 1577 case LUA_TLIGHTUSERDATA:
1451 lua_pushlightuserdata( L2, lua_touserdata(L, i)); 1578 lua_pushlightuserdata( L2, lua_touserdata( L, i));
1452 break; 1579 break;
1453 1580
1454 /* The following types are not allowed as table keys */ 1581 /* The following types are not allowed as table keys */
@@ -1524,6 +1651,16 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca
1524 STACK_CHECK( L); 1651 STACK_CHECK( L);
1525 STACK_CHECK( L2); 1652 STACK_CHECK( L2);
1526 1653
1654 /*
1655 * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?)
1656 * Note that this table CAN be a module table, but we just didn't register it, in which case we'll send it through the table cloning mechanism
1657 */
1658 if( lookup_table( L2, L, i, mode_, upName_))
1659 {
1660 ASSERT_L( lua_istable( L2, -1) || (lua_tocfunction( L2, -1) == table_lookup_sentinel)); // from lookup datables // can also be table_lookup_sentinel if this is a table we know
1661 break;
1662 }
1663
1527 /* Check if we've already copied the same table from 'L' (during this transmission), and 1664 /* Check if we've already copied the same table from 'L' (during this transmission), and
1528 * reuse the old copy. This allows table upvalues shared by multiple 1665 * reuse the old copy. This allows table upvalues shared by multiple
1529 * local functions to point to the same table, also in the target. 1666 * local functions to point to the same table, also in the target.
@@ -1531,14 +1668,14 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca
1531 * to the same subtable. 1668 * to the same subtable.
1532 * 1669 *
1533 * Note: Even metatables need to go through this test; to detect 1670 * Note: Even metatables need to go through this test; to detect
1534 * loops s.a. those in required module tables (getmetatable(lanes).lanes == lanes) 1671 * loops such as those in required module tables (getmetatable(lanes).lanes == lanes)
1535 */ 1672 */
1536 if( push_cached_table( L2, L2_cache_i, L, i)) 1673 if( push_cached_table( L2, L2_cache_i, L, i))
1537 { 1674 {
1538 ASSERT_L( lua_istable( L2, -1)); // from cache 1675 ASSERT_L( lua_istable( L2, -1)); // from cache
1539 break; 1676 break;
1540 } 1677 }
1541 ASSERT_L( lua_istable( L2,-1)); 1678 ASSERT_L( lua_istable( L2, -1));
1542 1679
1543 STACK_GROW( L, 2); 1680 STACK_GROW( L, 2);
1544 STACK_GROW( L2, 2); 1681 STACK_GROW( L2, 2);
@@ -1546,11 +1683,10 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca
1546 lua_pushnil( L); // start iteration 1683 lua_pushnil( L); // start iteration
1547 while( lua_next( L, i)) 1684 while( lua_next( L, i))
1548 { 1685 {
1549 uint_t val_i = lua_gettop(L); 1686 uint_t val_i = lua_gettop( L);
1550 uint_t key_i = val_i - 1; 1687 uint_t key_i = val_i - 1;
1551 1688
1552 /* Only basic key types are copied over; others ignored 1689 // Only basic key types are copied over; others ignored
1553 */
1554 if( inter_copy_one_( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_)) 1690 if( inter_copy_one_( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_))
1555 { 1691 {
1556 char* valPath = (char*) upName_; 1692 char* valPath = (char*) upName_;
@@ -1613,8 +1749,8 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca
1613 { /* L2 did not know the metatable */ 1749 { /* L2 did not know the metatable */
1614 lua_pop( L2, 1); 1750 lua_pop( L2, 1);
1615 STACK_MID( L2, 2); 1751 STACK_MID( L2, 2);
1616 ASSERT_L( lua_istable(L,-1)); 1752 ASSERT_L( lua_istable( L,-1));
1617 if( inter_copy_one_( U, L2, L2_cache_i /*for function cacheing*/, L, lua_gettop(L) /*[-1]*/, VT_METATABLE, mode_, upName_)) 1753 if( inter_copy_one_( U, L2, L2_cache_i /*for function cacheing*/, L, lua_gettop( L) /*[-1]*/, VT_METATABLE, mode_, upName_))
1618 { 1754 {
1619 // 1755 //
1620 // L2 ([-3]: copied table) 1756 // L2 ([-3]: copied table)
@@ -1664,6 +1800,7 @@ static bool_t inter_copy_one_( struct s_Universe* U, lua_State* L2, uint_t L2_ca
1664 1800
1665 /* The following types cannot be copied */ 1801 /* The following types cannot be copied */
1666 1802
1803 case 10: // LuaJIT CDATA
1667 case LUA_TTHREAD: 1804 case LUA_TTHREAD:
1668 ret = FALSE; 1805 ret = FALSE;
1669 break; 1806 break;
diff --git a/src/tools.h b/src/tools.h
index a4bcf43..b869a16 100644
--- a/src/tools.h
+++ b/src/tools.h
@@ -17,9 +17,11 @@
17#endif 17#endif
18 18
19// For some reason, LuaJIT 64bits doesn't support lua_newstate() 19// For some reason, LuaJIT 64bits doesn't support lua_newstate()
20#if defined(LUA_LJDIR) && (defined(__x86_64__) || defined(_M_X64)) 20#if defined(LUA_JITLIBNAME) && (defined(__x86_64__) || defined(_M_X64))
21//#pragma message( "LuaJIT 64 bits detected: don't propagate allocf")
21#define PROPAGATE_ALLOCF 0 22#define PROPAGATE_ALLOCF 0
22#else // LuaJIT x64 23#else // LuaJIT x64
24//#pragma message( "PUC-Lua detected: propagate allocf")
23#define PROPAGATE_ALLOCF 1 25#define PROPAGATE_ALLOCF 1
24#endif // LuaJIT x64 26#endif // LuaJIT x64
25#if PROPAGATE_ALLOCF 27#if PROPAGATE_ALLOCF