aboutsummaryrefslogtreecommitdiff
path: root/src/tools.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools.cpp')
-rw-r--r--src/tools.cpp2080
1 files changed, 2080 insertions, 0 deletions
diff --git a/src/tools.cpp b/src/tools.cpp
new file mode 100644
index 0000000..6f4a06a
--- /dev/null
+++ b/src/tools.cpp
@@ -0,0 +1,2080 @@
1/*
2 * TOOLS.C Copyright (c) 2002-10, Asko Kauppi
3 *
4 * Lua tools to support Lanes.
5*/
6
7/*
8===============================================================================
9
10Copyright (C) 2002-10 Asko Kauppi <akauppi@gmail.com>
11 2011-17 benoit Germain <bnt.germain@gmail.com>
12
13Permission is hereby granted, free of charge, to any person obtaining a copy
14of this software and associated documentation files (the "Software"), to deal
15in the Software without restriction, including without limitation the rights
16to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17copies of the Software, and to permit persons to whom the Software is
18furnished to do so, subject to the following conditions:
19
20The above copyright notice and this permission notice shall be included in
21all copies or substantial portions of the Software.
22
23THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29THE SOFTWARE.
30
31===============================================================================
32*/
33
34#include <stdio.h>
35#include <assert.h>
36#include <string.h>
37#include <ctype.h>
38#include <stdlib.h>
39#if !defined(__APPLE__)
40#include <malloc.h>
41#endif // __APPLE__
42
43#include "tools.h"
44#include "compat.h"
45#include "universe.h"
46#include "keeper.h"
47#include "lanes.h"
48#include "uniquekey.h"
49
50// functions implemented in deep.c
51extern bool_t copydeep( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_);
52extern void push_registry_subtable( lua_State* L, UniqueKey key_);
53
54DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+");
55
56
57// ################################################################################################
58
59/*
60 * Does what the original 'push_registry_subtable' function did, but adds an optional mode argument to it
61 */
62void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode_)
63{
64 STACK_GROW( L, 3);
65 STACK_CHECK( L, 0);
66
67 REGISTRY_GET( L, key_); // {}|nil
68 STACK_MID( L, 1);
69
70 if( lua_isnil( L, -1))
71 {
72 lua_pop( L, 1); //
73 lua_newtable( L); // {}
74 // _R[key_] = {}
75 REGISTRY_SET( L, key_, lua_pushvalue( L, -2)); // {}
76 STACK_MID( L, 1);
77
78 // Set its metatable if requested
79 if( mode_)
80 {
81 lua_newtable( L); // {} mt
82 lua_pushliteral( L, "__mode"); // {} mt "__mode"
83 lua_pushstring( L, mode_); // {} mt "__mode" mode
84 lua_rawset( L, -3); // {} mt
85 lua_setmetatable( L, -2); // {}
86 }
87 }
88 STACK_END( L, 1);
89 ASSERT_L( lua_istable( L, -1));
90}
91
92// ################################################################################################
93
94/*
95 * Push a registry subtable (keyed by unique 'key_') onto the stack.
96 * If the subtable does not exist, it is created and chained.
97 */
98void push_registry_subtable( lua_State* L, UniqueKey key_)
99{
100 push_registry_subtable_mode( L, key_, NULL);
101}
102
103// ################################################################################################
104
105/*---=== luaG_dump ===---*/
106#ifdef _DEBUG
107void luaG_dump( lua_State* L)
108{
109 int top = lua_gettop( L);
110 int i;
111
112 fprintf( stderr, "\n\tDEBUG STACK:\n");
113
114 if( top == 0)
115 fprintf( stderr, "\t(none)\n");
116
117 for( i = 1; i <= top; ++ i)
118 {
119 int type = lua_type( L, i);
120
121 fprintf( stderr, "\t[%d]= (%s) ", i, lua_typename( L, type));
122
123 // Print item contents here...
124 //
125 // Note: this requires 'tostring()' to be defined. If it is NOT,
126 // enable it for more debugging.
127 //
128 STACK_CHECK( L, 0);
129 STACK_GROW( L, 2);
130
131 lua_getglobal( L, "tostring");
132 //
133 // [-1]: tostring function, or nil
134
135 if( !lua_isfunction( L, -1))
136 {
137 fprintf( stderr, "('tostring' not available)");
138 }
139 else
140 {
141 lua_pushvalue( L, i);
142 lua_call( L, 1 /*args*/, 1 /*retvals*/);
143
144 // Don't trust the string contents
145 //
146 fprintf( stderr, "%s", lua_tostring( L, -1));
147 }
148 lua_pop( L, 1);
149 STACK_END( L, 0);
150 fprintf( stderr, "\n");
151 }
152 fprintf( stderr, "\n");
153}
154#endif // _DEBUG
155
156// ################################################################################################
157
158// same as PUC-Lua l_alloc
159static void* libc_lua_Alloc(void* ud, void* ptr, size_t osize, size_t nsize)
160{
161 (void)ud; (void)osize; /* not used */
162 if (nsize == 0)
163 {
164 free(ptr);
165 return NULL;
166 }
167 else
168 {
169 return realloc(ptr, nsize);
170 }
171}
172
173static void* protected_lua_Alloc( void *ud, void *ptr, size_t osize, size_t nsize)
174{
175 void* p;
176 ProtectedAllocator* s = (ProtectedAllocator*) ud;
177 MUTEX_LOCK( &s->lock);
178 p = s->definition.allocF( s->definition.allocUD, ptr, osize, nsize);
179 MUTEX_UNLOCK( &s->lock);
180 return p;
181}
182
183static int luaG_provide_protected_allocator( lua_State* L)
184{
185 Universe* U = universe_get( L);
186 AllocatorDefinition* const def = (AllocatorDefinition*) lua_newuserdatauv( L, sizeof(AllocatorDefinition), 0);
187 def->allocF = protected_lua_Alloc;
188 def->allocUD = &U->protected_allocator;
189 return 1;
190}
191
192// called once at the creation of the universe (therefore L is the master Lua state everything originates from)
193// Do I need to disable this when compiling for LuaJIT to prevent issues?
194void initialize_allocator_function( Universe* U, lua_State* L)
195{
196 STACK_CHECK( L, 0);
197 lua_getfield( L, -1, "allocator"); // settings allocator|nil|"protected"
198 if( !lua_isnil( L, -1))
199 {
200 // store C function pointer in an internal variable
201 U->provide_allocator = lua_tocfunction( L, -1); // settings allocator
202 if( U->provide_allocator != NULL)
203 {
204 // make sure the function doesn't have upvalues
205 char const* upname = lua_getupvalue( L, -1, 1); // settings allocator upval?
206 if( upname != NULL) // should be "" for C functions with upvalues if any
207 {
208 (void) luaL_error( L, "config.allocator() shouldn't have upvalues");
209 }
210 // remove this C function from the config table so that it doesn't cause problems
211 // when we transfer the config table in newly created Lua states
212 lua_pushnil( L); // settings allocator nil
213 lua_setfield( L, -3, "allocator"); // settings allocator
214 }
215 else if( lua_type( L, -1) == LUA_TSTRING) // should be "protected"
216 {
217 // initialize all we need for the protected allocator
218 MUTEX_INIT( &U->protected_allocator.lock); // the mutex
219 // and the original allocator to call from inside protection by the mutex
220 U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD);
221 // before a state is created, this function will be called to obtain the allocator
222 U->provide_allocator = luaG_provide_protected_allocator;
223
224 lua_setallocf( L, protected_lua_Alloc, &U->protected_allocator);
225 }
226 }
227 else
228 {
229 // initialize the mutex even if we are not going to use it, because cleanup_allocator_function will deinitialize it
230 MUTEX_INIT( &U->protected_allocator.lock);
231 // just grab whatever allocator was provided to lua_newstate
232 U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD);
233 }
234 lua_pop( L, 1); // settings
235 STACK_MID(L, 0);
236
237 lua_getfield( L, -1, "internal_allocator"); // settings "libc"|"allocator"
238 {
239 char const* allocator = lua_tostring( L, -1);
240 if (strcmp(allocator, "libc") == 0)
241 {
242 U->internal_allocator.allocF = libc_lua_Alloc;
243 U->internal_allocator.allocUD = NULL;
244 }
245 else
246 {
247 U->internal_allocator = U->protected_allocator.definition;
248 }
249 }
250 lua_pop( L, 1); // settings
251 STACK_END( L, 0);
252}
253
254void cleanup_allocator_function( Universe* U, lua_State* L)
255{
256 // remove the protected allocator, if any
257 if( U->protected_allocator.definition.allocF != NULL)
258 {
259 // install the non-protected allocator
260 lua_setallocf( L, U->protected_allocator.definition.allocF, U->protected_allocator.definition.allocUD);
261 // release the mutex
262 MUTEX_FREE( &U->protected_allocator.lock);
263 }
264}
265
266// ################################################################################################
267
268static int dummy_writer( lua_State* L, void const* p, size_t sz, void* ud)
269{
270 (void)L; (void)p; (void)sz; (void) ud; // unused
271 return 666;
272}
273
274
275/*
276 * differentiation between C, bytecode and JIT-fast functions
277 *
278 *
279 * +----------+------------+----------+
280 * | bytecode | C function | JIT-fast |
281 * +-----------------+----------+------------+----------+
282 * | lua_topointer | | | |
283 * +-----------------+----------+------------+----------+
284 * | lua_tocfunction | NULL | | NULL |
285 * +-----------------+----------+------------+----------+
286 * | lua_dump | 666 | 1 | 1 |
287 * +-----------------+----------+------------+----------+
288 */
289
290typedef enum
291{
292 FST_Bytecode,
293 FST_Native,
294 FST_FastJIT
295} FuncSubType;
296
297FuncSubType luaG_getfuncsubtype( lua_State *L, int _i)
298{
299 if( lua_tocfunction( L, _i))
300 {
301 return FST_Native;
302 }
303 {
304 int mustpush = 0, dumpres;
305 if( lua_absindex( L, _i) != lua_gettop( L))
306 {
307 lua_pushvalue( L, _i);
308 mustpush = 1;
309 }
310 // the provided writer fails with code 666
311 // therefore, anytime we get 666, this means that lua_dump() attempted a dump
312 // all other cases mean this is either a C or LuaJIT-fast function
313 dumpres = lua504_dump( L, dummy_writer, NULL, 0);
314 lua_pop( L, mustpush);
315 if( dumpres == 666)
316 {
317 return FST_Bytecode;
318 }
319 }
320 return FST_FastJIT;
321}
322
323static lua_CFunction luaG_tocfunction( lua_State *L, int _i, FuncSubType *_out)
324{
325 lua_CFunction p = lua_tocfunction( L, _i);
326 *_out = luaG_getfuncsubtype( L, _i);
327 return p;
328}
329
330// crc64/we of string "LOOKUPCACHE_REGKEY" generated at http://www.nitrxgen.net/hashgen/
331static DECLARE_CONST_UNIQUE_KEY( LOOKUPCACHE_REGKEY, 0x837a68dfc6fcb716);
332
333// inspired from tconcat() in ltablib.c
334static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length)
335{
336 int i = 1;
337 luaL_Buffer b;
338 STACK_CHECK( L, 0);
339 // Lua 5.4 pushes &b as light userdata on the stack. be aware of it...
340 luaL_buffinit( L, &b); // ... {} ... &b?
341 for( ; i < last; ++ i)
342 {
343 lua_rawgeti( L, t, i);
344 luaL_addvalue( &b);
345 luaL_addlstring(&b, "/", 1);
346 }
347 if( i == last) // add last value (if interval was not empty)
348 {
349 lua_rawgeti( L, t, i);
350 luaL_addvalue( &b);
351 }
352 // &b is popped at that point (-> replaced by the result)
353 luaL_pushresult( &b); // ... {} ... "<result>"
354 STACK_END( L, 1);
355 return lua_tolstring( L, -1, length);
356}
357
358/*
359 * receives 2 arguments: a name k and an object o
360 * add two entries ["fully.qualified.name"] = o
361 * and [o] = "fully.qualified.name"
362 * where <o> is either a table or a function
363 * if we already had an entry of type [o] = ..., replace the name if the new one is shorter
364 * pops the processed object from the stack
365 */
366static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, int _ctx_base, int _depth)
367{
368 // slot 1 in the stack contains the table that receives everything we found
369 int const dest = _ctx_base;
370 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i
371 int const fqn = _ctx_base + 1;
372
373 size_t prevNameLength, newNameLength;
374 char const* prevName;
375 DEBUGSPEW_CODE( char const *newName);
376 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END));
377 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
378
379 STACK_CHECK( L, 0);
380 // first, raise an error if the function is already known
381 lua_pushvalue( L, -1); // ... {bfc} k o o
382 lua_rawget( L, dest); // ... {bfc} k o name?
383 prevName = lua_tolstring( L, -1, &prevNameLength); // NULL if we got nil (first encounter of this object)
384 // push name in fqn stack (note that concatenation will crash if name is a not string or a number)
385 lua_pushvalue( L, -3); // ... {bfc} k o name? k
386 ASSERT_L( lua_type( L, -1) == LUA_TNUMBER || lua_type( L, -1) == LUA_TSTRING);
387 ++ _depth;
388 lua_rawseti( L, fqn, _depth); // ... {bfc} k o name?
389 // generate name
390 DEBUGSPEW_CODE( newName =) luaG_pushFQN( L, fqn, _depth, &newNameLength); // ... {bfc} k o name? "f.q.n"
391 // Lua 5.2 introduced a hash randomizer seed which causes table iteration to yield a different key order
392 // on different VMs even when the tables are populated the exact same way.
393 // When Lua is built with compatibility options (such as LUA_COMPAT_ALL),
394 // this causes several base libraries to register functions under multiple names.
395 // This, with the randomizer, can cause the first generated name of an object to be different on different VMs,
396 // which breaks function transfer.
397 // Also, nothing prevents any external module from exposing a given object under several names, so...
398 // Therefore, when we encounter an object for which a name was previously registered, we need to select the names
399 // based on some sorting order so that we end up with the same name in all databases whatever order the table walk yielded
400 if( prevName != NULL && (prevNameLength < newNameLength || lua_lessthan( L, -2, -1)))
401 {
402 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s' remained named '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -3)), newName, prevName));
403 // the previous name is 'smaller' than the one we just generated: keep it!
404 lua_pop( L, 3); // ... {bfc} k
405 }
406 else
407 {
408 // the name we generated is either the first one, or a better fit for our purposes
409 if( prevName)
410 {
411 // clear the previous name for the database to avoid clutter
412 lua_insert( L, -2); // ... {bfc} k o "f.q.n" prevName
413 // t[prevName] = nil
414 lua_pushnil( L); // ... {bfc} k o "f.q.n" prevName nil
415 lua_rawset( L, dest); // ... {bfc} k o "f.q.n"
416 }
417 else
418 {
419 lua_remove( L, -2); // ... {bfc} k o "f.q.n"
420 }
421 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s '%s'\n" INDENT_END, lua_typename( L, lua_type( L, -2)), newName));
422 // prepare the stack for database feed
423 lua_pushvalue( L, -1); // ... {bfc} k o "f.q.n" "f.q.n"
424 lua_pushvalue( L, -3); // ... {bfc} k o "f.q.n" "f.q.n" o
425 ASSERT_L( lua_rawequal( L, -1, -4));
426 ASSERT_L( lua_rawequal( L, -2, -3));
427 // t["f.q.n"] = o
428 lua_rawset( L, dest); // ... {bfc} k o "f.q.n"
429 // t[o] = "f.q.n"
430 lua_rawset( L, dest); // ... {bfc} k
431 // remove table name from fqn stack
432 lua_pushnil( L); // ... {bfc} k nil
433 lua_rawseti( L, fqn, _depth); // ... {bfc} k
434 }
435 -- _depth;
436 STACK_END( L, -1);
437 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
438}
439
440static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, int _ctx_base, int _i, int _depth)
441{
442 lua_Integer visit_count;
443 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i
444 int const fqn = _ctx_base + 1;
445 // slot 3 contains a cache that stores all already visited tables to avoid infinite recursion loops
446 int const cache = _ctx_base + 2;
447 // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search)
448 int const breadth_first_cache = lua_gettop( L) + 1;
449 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "populate_func_lookup_table_recur()\n" INDENT_END));
450 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
451
452 STACK_GROW( L, 6);
453 // slot _i contains a table where we search for functions (or a full userdata with a metatable)
454 STACK_CHECK( L, 0); // ... {_i}
455
456 // if object is a userdata, replace it by its metatable
457 if( lua_type( L, _i) == LUA_TUSERDATA)
458 {
459 lua_getmetatable( L, _i); // ... {_i} mt
460 lua_replace( L, _i); // ... {_i}
461 }
462
463 // if table is already visited, we are done
464 lua_pushvalue( L, _i); // ... {_i} {}
465 lua_rawget( L, cache); // ... {_i} nil|n
466 visit_count = lua_tointeger( L, -1); // 0 if nil, else n
467 lua_pop( L, 1); // ... {_i}
468 STACK_MID( L, 0);
469 if( visit_count > 0)
470 {
471 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END));
472 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
473 return;
474 }
475
476 // remember we visited this table (1-visit count)
477 lua_pushvalue( L, _i); // ... {_i} {}
478 lua_pushinteger( L, visit_count + 1); // ... {_i} {} 1
479 lua_rawset( L, cache); // ... {_i}
480 STACK_MID( L, 0);
481
482 // this table is at breadth_first_cache index
483 lua_newtable( L); // ... {_i} {bfc}
484 ASSERT_L( lua_gettop( L) == breadth_first_cache);
485 // iterate over all entries in the processed table
486 lua_pushnil( L); // ... {_i} {bfc} nil
487 while( lua_next( L, _i) != 0) // ... {_i} {bfc} k v
488 {
489 // just for debug, not actually needed
490 //char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string";
491 // subtable: process it recursively
492 if( lua_istable( L, -1)) // ... {_i} {bfc} k {}
493 {
494 // increment visit count to make sure we will actually scan it at this recursive level
495 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {}
496 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} {}
497 lua_rawget( L, cache); // ... {_i} {bfc} k {} {} n?
498 visit_count = lua_tointeger( L, -1) + 1; // 1 if we got nil, else n+1
499 lua_pop( L, 1); // ... {_i} {bfc} k {} {}
500 lua_pushinteger( L, visit_count); // ... {_i} {bfc} k {} {} n
501 lua_rawset( L, cache); // ... {_i} {bfc} k {}
502 // store the table in the breadth-first cache
503 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k
504 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k {}
505 lua_rawset( L, breadth_first_cache); // ... {_i} {bfc} k {}
506 // generate a name, and if we already had one name, keep whichever is the shorter
507 update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, _depth); // ... {_i} {bfc} k
508 }
509 else if( lua_isfunction( L, -1) && (luaG_getfuncsubtype( L, -1) != FST_Bytecode)) // ... {_i} {bfc} k func
510 {
511 // generate a name, and if we already had one name, keep whichever is the shorter
512 update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, _depth); // ... {_i} {bfc} k
513 }
514 else
515 {
516 lua_pop( L, 1); // ... {_i} {bfc} k
517 }
518 STACK_MID( L, 2);
519 }
520 // now process the tables we encountered at that depth
521 ++ _depth;
522 lua_pushnil( L); // ... {_i} {bfc} nil
523 while( lua_next( L, breadth_first_cache) != 0) // ... {_i} {bfc} k {}
524 {
525 DEBUGSPEW_CODE( char const* key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string");
526 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "table '%s'\n" INDENT_END, key));
527 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
528 // un-visit this table in case we do need to process it
529 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {}
530 lua_rawget( L, cache); // ... {_i} {bfc} k {} n
531 ASSERT_L( lua_type( L, -1) == LUA_TNUMBER);
532 visit_count = lua_tointeger( L, -1) - 1;
533 lua_pop( L, 1); // ... {_i} {bfc} k {}
534 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {}
535 if( visit_count > 0)
536 {
537 lua_pushinteger( L, visit_count); // ... {_i} {bfc} k {} {} n
538 }
539 else
540 {
541 lua_pushnil( L); // ... {_i} {bfc} k {} {} nil
542 }
543 lua_rawset( L, cache); // ... {_i} {bfc} k {}
544 // push table name in fqn stack (note that concatenation will crash if name is a not string!)
545 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k
546 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k {}
547 populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth);
548 lua_pop( L, 1); // ... {_i} {bfc} k
549 STACK_MID( L, 2);
550 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
551 }
552 // remove table name from fqn stack
553 lua_pushnil( L); // ... {_i} {bfc} nil
554 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc}
555 -- _depth;
556 // we are done with our cache
557 lua_pop( L, 1); // ... {_i}
558 STACK_END( L, 0);
559 // we are done // ... {_i} {bfc}
560 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
561}
562
563/*
564 * create a "fully.qualified.name" <-> function equivalence database
565 */
566void populate_func_lookup_table( lua_State* L, int _i, char const* name_)
567{
568 int const ctx_base = lua_gettop( L) + 1;
569 int const in_base = lua_absindex( L, _i);
570 int start_depth = 0;
571 DEBUGSPEW_CODE( Universe* U = universe_get( L));
572 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL"));
573 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
574 STACK_GROW( L, 3);
575 STACK_CHECK( L, 0);
576 REGISTRY_GET( L, LOOKUP_REGKEY); // {}
577 STACK_MID( L, 1);
578 ASSERT_L( lua_istable( L, -1));
579 if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function
580 {
581 name_ = name_ ? name_ : "NULL";
582 lua_pushvalue( L, in_base); // {} f
583 lua_pushstring( L, name_); // {} f _name
584 lua_rawset( L, -3); // {}
585 lua_pushstring( L, name_); // {} _name
586 lua_pushvalue( L, in_base); // {} _name f
587 lua_rawset( L, -3); // {}
588 lua_pop( L, 1); //
589 }
590 else if( lua_type( L, in_base) == LUA_TTABLE)
591 {
592 lua_newtable( L); // {} {fqn}
593 if( name_)
594 {
595 STACK_MID( L, 2);
596 lua_pushstring( L, name_); // {} {fqn} "name"
597 // generate a name, and if we already had one name, keep whichever is the shorter
598 lua_pushvalue( L, in_base); // {} {fqn} "name" t
599 update_lookup_entry( DEBUGSPEW_PARAM_COMMA( U) L, ctx_base, start_depth); // {} {fqn} "name"
600 // don't forget to store the name at the bottom of the fqn stack
601 ++ start_depth;
602 lua_rawseti( L, -2, start_depth); // {} {fqn}
603 STACK_MID( L, 2);
604 }
605 // retrieve the cache, create it if we haven't done it yet
606 REGISTRY_GET( L, LOOKUPCACHE_REGKEY); // {} {fqn} {cache}?
607 if( lua_isnil( L, -1))
608 {
609 lua_pop( L, 1); // {} {fqn}
610 lua_newtable( L); // {} {fqn} {cache}
611 REGISTRY_SET( L, LOOKUPCACHE_REGKEY, lua_pushvalue( L, -2));
612 STACK_MID( L, 3);
613 }
614 // process everything we find in that table, filling in lookup data for all functions and tables we see there
615 populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, ctx_base, in_base, start_depth);
616 lua_pop( L, 3);
617 }
618 else
619 {
620 lua_pop( L, 1); //
621 (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base)));
622 }
623 STACK_END( L, 0);
624 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
625}
626
627/*---=== Inter-state copying ===---*/
628
629// crc64/we of string "REG_MTID" generated at http://www.nitrxgen.net/hashgen/
630static DECLARE_CONST_UNIQUE_KEY( REG_MTID, 0x2e68f9b4751584dc);
631
632/*
633* Get a unique ID for metatable at [i].
634*/
635static lua_Integer get_mt_id( Universe* U, lua_State* L, int i)
636{
637 lua_Integer id;
638
639 i = lua_absindex( L, i);
640
641 STACK_GROW( L, 3);
642
643 STACK_CHECK( L, 0);
644 push_registry_subtable( L, REG_MTID); // ... _R[REG_MTID]
645 lua_pushvalue( L, i); // ... _R[REG_MTID] {mt}
646 lua_rawget( L, -2); // ... _R[REG_MTID] mtk?
647
648 id = lua_tointeger( L, -1); // 0 for nil
649 lua_pop( L, 1); // ... _R[REG_MTID]
650 STACK_MID( L, 1);
651
652 if( id == 0)
653 {
654 MUTEX_LOCK( &U->mtid_lock);
655 id = ++ U->last_mt_id;
656 MUTEX_UNLOCK( &U->mtid_lock);
657
658 /* Create two-way references: id_uint <-> table
659 */
660 lua_pushvalue( L, i); // ... _R[REG_MTID] {mt}
661 lua_pushinteger( L, id); // ... _R[REG_MTID] {mt} id
662 lua_rawset( L, -3); // ... _R[REG_MTID]
663
664 lua_pushinteger( L, id); // ... _R[REG_MTID] id
665 lua_pushvalue( L, i); // ... _R[REG_MTID] id {mt}
666 lua_rawset( L, -3); // ... _R[REG_MTID]
667 }
668 lua_pop( L, 1); // ...
669
670 STACK_END( L, 0);
671
672 return id;
673}
674
675// function sentinel used to transfer native functions from/to keeper states
676static int func_lookup_sentinel( lua_State* L)
677{
678 return luaL_error( L, "function lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
679}
680
681
682// function sentinel used to transfer native table from/to keeper states
683static int table_lookup_sentinel( lua_State* L)
684{
685 return luaL_error( L, "table lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
686}
687
688// function sentinel used to transfer cloned full userdata from/to keeper states
689static int userdata_clone_sentinel( lua_State* L)
690{
691 return luaL_error( L, "userdata clone sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
692}
693
694/*
695 * retrieve the name of a function/table in the lookup database
696 */
697static char const* find_lookup_name( lua_State* L, uint_t i, LookupMode mode_, char const* upName_, size_t* len_)
698{
699 DEBUGSPEW_CODE( Universe* const U = universe_get( L));
700 char const* fqn;
701 ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ...
702 STACK_CHECK( L, 0);
703 STACK_GROW( L, 3); // up to 3 slots are necessary on error
704 if( mode_ == eLM_FromKeeper)
705 {
706 lua_CFunction f = lua_tocfunction( L, i); // should *always* be func_lookup_sentinel or table_lookup_sentinel!
707 if( f == func_lookup_sentinel || f == table_lookup_sentinel || f == userdata_clone_sentinel)
708 {
709 lua_getupvalue( L, i, 1); // ... v ... "f.q.n"
710 }
711 else
712 {
713 // if this is not a sentinel, this is some user-created table we wanted to lookup
714 ASSERT_L( NULL == f && lua_istable( L, i));
715 // push anything that will convert to NULL string
716 lua_pushnil( L); // ... v ... nil
717 }
718 }
719 else
720 {
721 // fetch the name from the source state's lookup table
722 REGISTRY_GET( L, LOOKUP_REGKEY); // ... v ... {}
723 STACK_MID( L, 1);
724 ASSERT_L( lua_istable( L, -1));
725 lua_pushvalue( L, i); // ... v ... {} v
726 lua_rawget( L, -2); // ... v ... {} "f.q.n"
727 }
728 fqn = lua_tolstring( L, -1, len_);
729 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn));
730 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database
731 lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... v ...
732 STACK_MID( L, 0);
733 if( NULL == fqn && !lua_istable( L, i)) // raise an error if we try to send an unknown function (but not for tables)
734 {
735 char const *from, *typewhat, *what, *gotchaA, *gotchaB;
736 // try to discover the name of the function we want to send
737 lua_getglobal( L, "decoda_name"); // ... v ... decoda_name
738 from = lua_tostring( L, -1);
739 lua_pushcfunction( L, luaG_nameof); // ... v ... decoda_name luaG_nameof
740 lua_pushvalue( L, i); // ... v ... decoda_name luaG_nameof t
741 lua_call( L, 1, 2); // ... v ... decoda_name "type" "name"|nil
742 typewhat = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : luaL_typename( L, -2);
743 // second return value can be nil if the table was not found
744 // probable reason: the function was removed from the source Lua state before Lanes was required.
745 if( lua_isnil( L, -1))
746 {
747 gotchaA = " referenced by";
748 gotchaB = "\n(did you remove it from the source Lua state before requiring Lanes?)";
749 what = upName_;
750 }
751 else
752 {
753 gotchaA = "";
754 gotchaB = "";
755 what = (lua_type( L, -1) == LUA_TSTRING) ? lua_tostring( L, -1) : luaL_typename( L, -1);
756 }
757 (void) luaL_error( L, "%s%s '%s' not found in %s origin transfer database.%s", typewhat, gotchaA, what, from ? from : "main", gotchaB);
758 *len_ = 0;
759 return NULL;
760 }
761 STACK_END( L, 0);
762 return fqn;
763}
764
765
766/*
767 * Push a looked-up table, or nothing if we found nothing
768 */
769static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
770{
771 // get the name of the table we want to send
772 size_t len;
773 char const* fqn = find_lookup_name( L, i, mode_, upName_, &len);
774 if( NULL == fqn) // name not found, it is some user-created table
775 {
776 return FALSE;
777 }
778 // push the equivalent table in the destination's stack, retrieved from the lookup table
779 STACK_CHECK( L2, 0); // L // L2
780 STACK_GROW( L2, 3); // up to 3 slots are necessary on error
781 switch( mode_)
782 {
783 default: // shouldn't happen, in theory...
784 (void) luaL_error( L, "internal error: unknown lookup mode");
785 return FALSE;
786
787 case eLM_ToKeeper:
788 // push a sentinel closure that holds the lookup name as upvalue
789 lua_pushlstring( L2, fqn, len); // "f.q.n"
790 lua_pushcclosure( L2, table_lookup_sentinel, 1); // f
791 break;
792
793 case eLM_LaneBody:
794 case eLM_FromKeeper:
795 REGISTRY_GET( L2, LOOKUP_REGKEY); // {}
796 STACK_MID( L2, 1);
797 ASSERT_L( lua_istable( L2, -1));
798 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
799 lua_rawget( L2, -2); // {} t
800 // we accept destination lookup failures in the case of transfering the Lanes body function (this will result in the source table being cloned instead)
801 // but not when we extract something out of a keeper, as there is nothing to clone!
802 if( lua_isnil( L2, -1) && mode_ == eLM_LaneBody)
803 {
804 lua_pop( L2, 2); //
805 STACK_MID( L2, 0);
806 return FALSE;
807 }
808 else if( !lua_istable( L2, -1))
809 {
810 char const* from, *to;
811 lua_getglobal( L, "decoda_name"); // ... t ... decoda_name
812 from = lua_tostring( L, -1);
813 lua_pop( L, 1); // ... t ...
814 lua_getglobal( L2, "decoda_name"); // {} t decoda_name
815 to = lua_tostring( L2, -1);
816 lua_pop( L2, 1); // {} t
817 // 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
818 (void) luaL_error(
819 (mode_ == eLM_FromKeeper) ? L2 : L
820 , "INTERNAL ERROR IN %s: table '%s' not found in %s destination transfer database."
821 , from ? from : "main"
822 , fqn
823 , to ? to : "main"
824 );
825 return FALSE;
826 }
827 lua_remove( L2, -2); // t
828 break;
829 }
830 STACK_END( L2, 1);
831 return TRUE;
832}
833
834
835/*
836 * Check if we've already copied the same table from 'L', and
837 * reuse the old copy. This allows table upvalues shared by multiple
838 * local functions to point to the same table, also in the target.
839 *
840 * Always pushes a table to 'L2'.
841 *
842 * Returns TRUE if the table was cached (no need to fill it!); FALSE if
843 * it's a virgin.
844 */
845static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i)
846{
847 bool_t not_found_in_cache; // L2
848 DECLARE_CONST_UNIQUE_KEY( p, lua_topointer( L, i));
849
850 ASSERT_L( L2_cache_i != 0);
851 STACK_GROW( L2, 3);
852 STACK_CHECK( L2, 0);
853
854 // We don't need to use the from state ('L') in ID since the life span
855 // is only for the duration of a copy (both states are locked).
856 // push a light userdata uniquely representing the table
857 push_unique_key( L2, p); // ... p
858
859 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1));
860
861 lua_rawget( L2, L2_cache_i); // ... {cached|nil}
862 not_found_in_cache = lua_isnil( L2, -1);
863 if( not_found_in_cache)
864 {
865 lua_pop( L2, 1); // ...
866 lua_newtable( L2); // ... {}
867 push_unique_key( L2, p); // ... {} p
868 lua_pushvalue( L2, -2); // ... {} p {}
869 lua_rawset( L2, L2_cache_i); // ... {}
870 }
871 STACK_END( L2, 1);
872 ASSERT_L( lua_istable( L2, -1));
873 return !not_found_in_cache;
874}
875
876
877/*
878 * Return some name helping to identify an object
879 */
880static int discover_object_name_recur( lua_State* L, int shortest_, int depth_)
881{
882 int const what = 1; // o "r" {c} {fqn} ... {?}
883 int const result = 2;
884 int const cache = 3;
885 int const fqn = 4;
886 // no need to scan this table if the name we will discover is longer than one we already know
887 if( shortest_ <= depth_ + 1)
888 {
889 return shortest_;
890 }
891 STACK_GROW( L, 3);
892 STACK_CHECK( L, 0);
893 // stack top contains the table to search in
894 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?}
895 lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1
896 // if table is already visited, we are done
897 if( !lua_isnil( L, -1))
898 {
899 lua_pop( L, 1); // o "r" {c} {fqn} ... {?}
900 return shortest_;
901 }
902 // examined table is not in the cache, add it now
903 lua_pop( L, 1); // o "r" {c} {fqn} ... {?}
904 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?}
905 lua_pushinteger( L, 1); // o "r" {c} {fqn} ... {?} {?} 1
906 lua_rawset( L, cache); // o "r" {c} {fqn} ... {?}
907 // scan table contents
908 lua_pushnil( L); // o "r" {c} {fqn} ... {?} nil
909 while( lua_next( L, -2)) // o "r" {c} {fqn} ... {?} k v
910 {
911 //char const *const strKey = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : NULL; // only for debugging
912 //lua_Number const numKey = (lua_type( L, -2) == LUA_TNUMBER) ? lua_tonumber( L, -2) : -6666; // only for debugging
913 STACK_MID( L, 2);
914 // append key name to fqn stack
915 ++ depth_;
916 lua_pushvalue( L, -2); // o "r" {c} {fqn} ... {?} k v k
917 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v
918 if( lua_rawequal( L, -1, what)) // is it what we are looking for?
919 {
920 STACK_MID( L, 2);
921 // update shortest name
922 if( depth_ < shortest_)
923 {
924 shortest_ = depth_;
925 luaG_pushFQN( L, fqn, depth_, NULL); // o "r" {c} {fqn} ... {?} k v "fqn"
926 lua_replace( L, result); // o "r" {c} {fqn} ... {?} k v
927 }
928 // no need to search further at this level
929 lua_pop( L, 2); // o "r" {c} {fqn} ... {?}
930 STACK_MID( L, 0);
931 break;
932 }
933 switch( lua_type( L, -1)) // o "r" {c} {fqn} ... {?} k v
934 {
935 default: // nil, boolean, light userdata, number and string aren't identifiable
936 break;
937
938 case LUA_TTABLE: // o "r" {c} {fqn} ... {?} k {}
939 STACK_MID( L, 2);
940 shortest_ = discover_object_name_recur( L, shortest_, depth_);
941 // search in the table's metatable too
942 if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k {} {mt}
943 {
944 if( lua_istable( L, -1))
945 {
946 ++ depth_;
947 lua_pushliteral( L, "__metatable"); // o "r" {c} {fqn} ... {?} k {} {mt} "__metatable"
948 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k {} {mt}
949 shortest_ = discover_object_name_recur( L, shortest_, depth_);
950 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k {} {mt} nil
951 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k {} {mt}
952 -- depth_;
953 }
954 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k {}
955 }
956 STACK_MID( L, 2);
957 break;
958
959 case LUA_TTHREAD: // o "r" {c} {fqn} ... {?} k T
960 // TODO: explore the thread's stack frame looking for our culprit?
961 break;
962
963 case LUA_TUSERDATA: // o "r" {c} {fqn} ... {?} k U
964 STACK_MID( L, 2);
965 // search in the object's metatable (some modules are built that way)
966 if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k U {mt}
967 {
968 if( lua_istable( L, -1))
969 {
970 ++ depth_;
971 lua_pushliteral( L, "__metatable"); // o "r" {c} {fqn} ... {?} k U {mt} "__metatable"
972 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k U {mt}
973 shortest_ = discover_object_name_recur( L, shortest_, depth_);
974 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k U {mt} nil
975 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k U {mt}
976 -- depth_;
977 }
978 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U
979 }
980 STACK_MID( L, 2);
981 // search in the object's uservalues
982 {
983 int uvi = 1;
984 while( lua_getiuservalue( L, -1, uvi) != LUA_TNONE) // o "r" {c} {fqn} ... {?} k U {u}
985 {
986 if( lua_istable( L, -1)) // if it is a table, look inside
987 {
988 ++ depth_;
989 lua_pushliteral( L, "uservalue"); // o "r" {c} {fqn} ... {?} k v {u} "uservalue"
990 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u}
991 shortest_ = discover_object_name_recur( L, shortest_, depth_);
992 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k v {u} nil
993 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u}
994 -- depth_;
995 }
996 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U
997 ++ uvi;
998 }
999 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1000 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U
1001 }
1002 STACK_MID( L, 2);
1003 break;
1004 }
1005 // make ready for next iteration
1006 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k
1007 // remove name from fqn stack
1008 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k nil
1009 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k
1010 STACK_MID( L, 1);
1011 -- depth_;
1012 } // o "r" {c} {fqn} ... {?}
1013 STACK_MID( L, 0);
1014 // remove the visited table from the cache, in case a shorter path to the searched object exists
1015 lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?}
1016 lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil
1017 lua_rawset( L, cache); // o "r" {c} {fqn} ... {?}
1018 STACK_END( L, 0);
1019 return shortest_;
1020}
1021
1022
1023/*
1024 * "type", "name" = lanes.nameof( o)
1025 */
1026int luaG_nameof( lua_State* L)
1027{
1028 int what = lua_gettop( L);
1029 if( what > 1)
1030 {
1031 luaL_argerror( L, what, "too many arguments.");
1032 }
1033
1034 // nil, boolean, light userdata, number and string aren't identifiable
1035 if( lua_type( L, 1) < LUA_TTABLE)
1036 {
1037 lua_pushstring( L, luaL_typename( L, 1)); // o "type"
1038 lua_insert( L, -2); // "type" o
1039 return 2;
1040 }
1041
1042 STACK_GROW( L, 4);
1043 STACK_CHECK( L, 0);
1044 // this slot will contain the shortest name we found when we are done
1045 lua_pushnil( L); // o nil
1046 // push a cache that will contain all already visited tables
1047 lua_newtable( L); // o nil {c}
1048 // push a table whose contents are strings that, when concatenated, produce unique name
1049 lua_newtable( L); // o nil {c} {fqn}
1050 lua_pushliteral( L, "_G"); // o nil {c} {fqn} "_G"
1051 lua_rawseti( L, -2, 1); // o nil {c} {fqn}
1052 // this is where we start the search
1053 lua_pushglobaltable( L); // o nil {c} {fqn} _G
1054 (void) discover_object_name_recur( L, 6666, 1);
1055 if( lua_isnil( L, 2)) // try again with registry, just in case...
1056 {
1057 lua_pop( L, 1); // o nil {c} {fqn}
1058 lua_pushliteral( L, "_R"); // o nil {c} {fqn} "_R"
1059 lua_rawseti( L, -2, 1); // o nil {c} {fqn}
1060 lua_pushvalue( L, LUA_REGISTRYINDEX); // o nil {c} {fqn} _R
1061 (void) discover_object_name_recur( L, 6666, 1);
1062 }
1063 lua_pop( L, 3); // o "result"
1064 STACK_END( L, 1);
1065 lua_pushstring( L, luaL_typename( L, 1)); // o "result" "type"
1066 lua_replace( L, -3); // "type" "result"
1067 return 2;
1068}
1069
1070
1071/*
1072 * Push a looked-up native/LuaJIT function.
1073 */
1074static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
1075{
1076 // get the name of the function we want to send
1077 size_t len;
1078 char const* fqn = find_lookup_name( L, i, mode_, upName_, &len);
1079 // push the equivalent function in the destination's stack, retrieved from the lookup table
1080 STACK_CHECK( L2, 0); // L // L2
1081 STACK_GROW( L2, 3); // up to 3 slots are necessary on error
1082 switch( mode_)
1083 {
1084 default: // shouldn't happen, in theory...
1085 (void) luaL_error( L, "internal error: unknown lookup mode");
1086 return;
1087
1088 case eLM_ToKeeper:
1089 // push a sentinel closure that holds the lookup name as upvalue
1090 lua_pushlstring( L2, fqn, len); // "f.q.n"
1091 lua_pushcclosure( L2, func_lookup_sentinel, 1); // f
1092 break;
1093
1094 case eLM_LaneBody:
1095 case eLM_FromKeeper:
1096 REGISTRY_GET( L2, LOOKUP_REGKEY); // {}
1097 STACK_MID( L2, 1);
1098 ASSERT_L( lua_istable( L2, -1));
1099 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
1100 lua_rawget( L2, -2); // {} f
1101 // nil means we don't know how to transfer stuff: user should do something
1102 // anything other than function or table should not happen!
1103 if( !lua_isfunction( L2, -1) && !lua_istable( L2, -1))
1104 {
1105 char const* from, * to;
1106 lua_getglobal( L, "decoda_name"); // ... f ... decoda_name
1107 from = lua_tostring( L, -1);
1108 lua_pop( L, 1); // ... f ...
1109 lua_getglobal( L2, "decoda_name"); // {} f decoda_name
1110 to = lua_tostring( L2, -1);
1111 lua_pop( L2, 1); // {} f
1112 // 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
1113 (void) luaL_error(
1114 (mode_ == eLM_FromKeeper) ? L2 : L
1115 , "%s%s: function '%s' not found in %s destination transfer database."
1116 , lua_isnil( L2, -1) ? "" : "INTERNAL ERROR IN "
1117 , from ? from : "main"
1118 , fqn
1119 , to ? to : "main"
1120 );
1121 return;
1122 }
1123 lua_remove( L2, -2); // f
1124 break;
1125
1126 /* keep it in case I need it someday, who knows...
1127 case eLM_RawFunctions:
1128 {
1129 int n;
1130 char const* upname;
1131 lua_CFunction f = lua_tocfunction( L, i);
1132 // copy upvalues
1133 for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n)
1134 {
1135 luaG_inter_move( U, L, L2, 1, mode_); // [up[,up ...]]
1136 }
1137 lua_pushcclosure( L2, f, n); //
1138 }
1139 break;
1140 */
1141 }
1142 STACK_END( L2, 1);
1143}
1144
1145
1146/*
1147 * Copy a function over, which has not been found in the cache.
1148 * L2 has the cache key for this function at the top of the stack
1149*/
1150
1151#if USE_DEBUG_SPEW()
1152static char const* lua_type_names[] =
1153{
1154 "LUA_TNIL"
1155 , "LUA_TBOOLEAN"
1156 , "LUA_TLIGHTUSERDATA"
1157 , "LUA_TNUMBER"
1158 , "LUA_TSTRING"
1159 , "LUA_TTABLE"
1160 , "LUA_TFUNCTION"
1161 , "LUA_TUSERDATA"
1162 , "LUA_TTHREAD"
1163 , "<LUA_NUMTAGS>" // not really a type
1164 , "LUA_TJITCDATA" // LuaJIT specific
1165};
1166static char const* vt_names[] =
1167{
1168 "VT_NORMAL"
1169 , "VT_KEY"
1170 , "VT_METATABLE"
1171};
1172#endif // USE_DEBUG_SPEW()
1173
1174// Lua 5.4.3 style of dumping (see lstrlib.c)
1175// we have to do it that way because we can't unbalance the stack between buffer operations
1176// namely, this means we can't push a function on top of the stack *after* we initialize the buffer!
1177// luckily, this also works with earlier Lua versions
1178static int buf_writer( lua_State* L, void const* b, size_t size, void* ud)
1179{
1180 luaL_Buffer* B = (luaL_Buffer*) ud;
1181 if( !B->L)
1182 {
1183 luaL_buffinit( L, B);
1184 }
1185 luaL_addlstring( B, (char const*) b, size);
1186 return 0;
1187}
1188
1189static void copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
1190{
1191 int n, needToPush;
1192 luaL_Buffer B;
1193 B.L = NULL;
1194
1195 ASSERT_L( L2_cache_i != 0); // ... {cache} ... p
1196 STACK_GROW( L, 2);
1197 STACK_CHECK( L, 0);
1198
1199
1200 // 'lua_dump()' needs the function at top of stack
1201 // if already on top of the stack, no need to push again
1202 needToPush = (i != (uint_t)lua_gettop( L));
1203 if( needToPush)
1204 {
1205 lua_pushvalue( L, i); // ... f
1206 }
1207
1208 //
1209 // "value returned is the error code returned by the last call
1210 // to the writer" (and we only return 0)
1211 // not sure this could ever fail but for memory shortage reasons
1212 // last parameter is Lua 5.4-specific (no stripping)
1213 if( lua504_dump( L, buf_writer, &B, 0) != 0)
1214 {
1215 luaL_error( L, "internal error: function dump failed.");
1216 }
1217
1218 // pushes dumped string on 'L'
1219 luaL_pushresult( &B); // ... f b
1220
1221 // if not pushed, no need to pop
1222 if( needToPush)
1223 {
1224 lua_remove( L, -2); // ... b
1225 }
1226
1227 // transfer the bytecode, then the upvalues, to create a similar closure
1228 {
1229 char const* name = NULL;
1230
1231 #if LOG_FUNC_INFO
1232 // "To get information about a function you push it onto the
1233 // stack and start the what string with the character '>'."
1234 //
1235 {
1236 lua_Debug ar;
1237 lua_pushvalue( L, i); // ... b f
1238 // fills 'name' 'namewhat' and 'linedefined', pops function
1239 lua_getinfo( L, ">nS", &ar); // ... b
1240 name = ar.namewhat;
1241 fprintf( stderr, INDENT_BEGIN "FNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL
1242 }
1243 #endif // LOG_FUNC_INFO
1244 {
1245 size_t sz;
1246 char const* s = lua_tolstring( L, -1, &sz); // ... b
1247 ASSERT_L( s && sz);
1248 STACK_GROW( L2, 2);
1249 // Note: Line numbers seem to be taken precisely from the
1250 // original function. 'name' is not used since the chunk
1251 // is precompiled (it seems...).
1252 //
1253 // TBD: Can we get the function's original name through, as well?
1254 //
1255 if( luaL_loadbuffer( L2, s, sz, name) != 0) // ... {cache} ... p function
1256 {
1257 // chunk is precompiled so only LUA_ERRMEM can happen
1258 // "Otherwise, it pushes an error message"
1259 //
1260 STACK_GROW( L, 1);
1261 luaL_error( L, "%s: %s", upName_, lua_tostring( L2, -1));
1262 }
1263 // remove the dumped string
1264 lua_pop( L, 1); // ...
1265 // now set the cache as soon as we can.
1266 // this is necessary if one of the function's upvalues references it indirectly
1267 // we need to find it in the cache even if it isn't fully transfered yet
1268 lua_insert( L2, -2); // ... {cache} ... function p
1269 lua_pushvalue( L2, -2); // ... {cache} ... function p function
1270 // cache[p] = function
1271 lua_rawset( L2, L2_cache_i); // ... {cache} ... function
1272 }
1273 STACK_MID( L, 0);
1274
1275 /* push over any upvalues; references to this function will come from
1276 * cache so we don't end up in eternal loop.
1277 * Lua5.2 and Lua5.3: one of the upvalues is _ENV, which we don't want to copy!
1278 * instead, the function shall have LUA_RIDX_GLOBALS taken in the destination state!
1279 */
1280 {
1281 char const* upname;
1282#if LUA_VERSION_NUM >= 502
1283 // Starting with Lua 5.2, each Lua function gets its environment as one of its upvalues (named LUA_ENV, aka "_ENV" by default)
1284 // Generally this is LUA_RIDX_GLOBALS, which we don't want to copy from the source to the destination state...
1285 // -> if we encounter an upvalue equal to the global table in the source, bind it to the destination's global table
1286 lua_pushglobaltable( L); // ... _G
1287#endif // LUA_VERSION_NUM
1288 for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n)
1289 { // ... _G up[n]
1290 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "UPNAME[%d]: %s -> " INDENT_END, n, upname));
1291#if LUA_VERSION_NUM >= 502
1292 if( lua_rawequal( L, -1, -2)) // is the upvalue equal to the global table?
1293 {
1294 DEBUGSPEW_CODE( fprintf( stderr, "pushing destination global scope\n"));
1295 lua_pushglobaltable( L2); // ... {cache} ... function <upvalues>
1296 }
1297 else
1298#endif // LUA_VERSION_NUM
1299 {
1300 DEBUGSPEW_CODE( fprintf( stderr, "copying value\n"));
1301 if( !inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, mode_, upname)) // ... {cache} ... function <upvalues>
1302 {
1303 luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1));
1304 }
1305 }
1306 lua_pop( L, 1); // ... _G
1307 }
1308#if LUA_VERSION_NUM >= 502
1309 lua_pop( L, 1); // ...
1310#endif // LUA_VERSION_NUM
1311 }
1312 // L2: function + 'n' upvalues (>=0)
1313
1314 STACK_MID( L, 0);
1315
1316 // Set upvalues (originally set to 'nil' by 'lua_load')
1317 {
1318 int func_index = lua_gettop( L2) - n;
1319 for( ; n > 0; -- n)
1320 {
1321 char const* rc = lua_setupvalue( L2, func_index, n); // ... {cache} ... function
1322 //
1323 // "assigns the value at the top of the stack to the upvalue and returns its name.
1324 // It also pops the value from the stack."
1325
1326 ASSERT_L( rc); // not having enough slots?
1327 }
1328 // once all upvalues have been set we are left
1329 // with the function at the top of the stack // ... {cache} ... function
1330 }
1331 }
1332 STACK_END( L, 0);
1333}
1334
1335/*
1336 * Check if we've already copied the same function from 'L', and reuse the old
1337 * copy.
1338 *
1339 * Always pushes a function to 'L2'.
1340 */
1341static void copy_cached_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
1342{
1343 FuncSubType funcSubType;
1344 /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions
1345 if( funcSubType == FST_Bytecode)
1346 {
1347 void* const aspointer = (void*)lua_topointer( L, i);
1348 // TBD: Merge this and same code for tables
1349 ASSERT_L( L2_cache_i != 0);
1350
1351 STACK_GROW( L2, 2);
1352
1353 // L2_cache[id_str]= function
1354 //
1355 STACK_CHECK( L2, 0);
1356
1357 // We don't need to use the from state ('L') in ID since the life span
1358 // is only for the duration of a copy (both states are locked).
1359 //
1360
1361 // push a light userdata uniquely representing the function
1362 lua_pushlightuserdata( L2, aspointer); // ... {cache} ... p
1363
1364 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1));
1365
1366 lua_pushvalue( L2, -1); // ... {cache} ... p p
1367 lua_rawget( L2, L2_cache_i); // ... {cache} ... p function|nil|true
1368
1369 if( lua_isnil( L2, -1)) // function is unknown
1370 {
1371 lua_pop( L2, 1); // ... {cache} ... p
1372
1373 // Set to 'true' for the duration of creation; need to find self-references
1374 // via upvalues
1375 //
1376 // pushes a copy of the func, stores a reference in the cache
1377 copy_func( U, L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function
1378 }
1379 else // found function in the cache
1380 {
1381 lua_remove( L2, -2); // ... {cache} ... function
1382 }
1383 STACK_END( L2, 1);
1384 ASSERT_L( lua_isfunction( L2, -1));
1385 }
1386 else // function is native/LuaJIT: no need to cache
1387 {
1388 lookup_native_func( L2, L, i, mode_, upName_); // ... {cache} ... function
1389 // if the function was in fact a lookup sentinel, we can either get a function or a table here
1390 ASSERT_L( lua_isfunction( L2, -1) || lua_istable( L2, -1));
1391 }
1392}
1393
1394static bool_t push_cached_metatable( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_)
1395{
1396 STACK_CHECK( L, 0);
1397 if( lua_getmetatable( L, i)) // ... mt
1398 {
1399 lua_Integer const mt_id = get_mt_id( U, L, -1); // Unique id for the metatable
1400
1401 STACK_CHECK( L2, 0);
1402 STACK_GROW( L2, 4);
1403 // do we already know this metatable?
1404 push_registry_subtable( L2, REG_MTID); // _R[REG_MTID]
1405 lua_pushinteger( L2, mt_id); // _R[REG_MTID] id
1406 lua_rawget( L2, -2); // _R[REG_MTID] mt?
1407
1408 STACK_MID( L2, 2);
1409
1410 if( lua_isnil( L2, -1))
1411 { // L2 did not know the metatable
1412 lua_pop( L2, 1); // _R[REG_MTID]
1413 if( inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_METATABLE, mode_, upName_)) // _R[REG_MTID] mt
1414 {
1415 STACK_MID( L2, 2);
1416 // mt_id -> metatable
1417 lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt id
1418 lua_pushvalue( L2, -2); // _R[REG_MTID] mt id mt
1419 lua_rawset( L2, -4); // _R[REG_MTID] mt
1420
1421 // metatable -> mt_id
1422 lua_pushvalue( L2, -1); // _R[REG_MTID] mt mt
1423 lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt mt id
1424 lua_rawset( L2, -4); // _R[REG_MTID] mt
1425 }
1426 else
1427 {
1428 (void) luaL_error( L, "Error copying a metatable");
1429 }
1430 STACK_MID( L2, 2);
1431 }
1432 lua_remove( L2, -2); // mt
1433
1434 lua_pop( L, 1); // ...
1435 STACK_END( L2, 1);
1436 STACK_MID( L, 0);
1437 return TRUE;
1438 }
1439 STACK_END( L, 0);
1440 return FALSE;
1441}
1442
1443static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, enum e_vt vt, LookupMode mode_, char const* upName_)
1444{
1445 uint_t val_i = lua_gettop( L);
1446 uint_t key_i = val_i - 1;
1447
1448 // Only basic key types are copied over; others ignored
1449 if( inter_copy_one( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_))
1450 {
1451 char* valPath = (char*) upName_;
1452 if( U->verboseErrors)
1453 {
1454 // for debug purposes, let's try to build a useful name
1455 if( lua_type( L, key_i) == LUA_TSTRING)
1456 {
1457 char const* key = lua_tostring( L, key_i);
1458 size_t const keyRawLen = lua_rawlen( L, key_i);
1459 size_t const bufLen = strlen( upName_) + keyRawLen + 2;
1460 valPath = (char*) alloca( bufLen);
1461 sprintf( valPath, "%s.%*s", upName_, (int) keyRawLen, key);
1462 key = NULL;
1463 }
1464#if defined LUA_LNUM || LUA_VERSION_NUM >= 503
1465 else if( lua_isinteger( L, key_i))
1466 {
1467 lua_Integer key = lua_tointeger( L, key_i);
1468 valPath = (char*) alloca( strlen( upName_) + 32 + 3);
1469 sprintf( valPath, "%s[" LUA_INTEGER_FMT "]", upName_, key);
1470 }
1471#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503
1472 else if( lua_type( L, key_i) == LUA_TNUMBER)
1473 {
1474 lua_Number key = lua_tonumber( L, key_i);
1475 valPath = (char*) alloca( strlen( upName_) + 32 + 3);
1476 sprintf( valPath, "%s[" LUA_NUMBER_FMT "]", upName_, key);
1477 }
1478 else if( lua_type( L, key_i) == LUA_TLIGHTUSERDATA)
1479 {
1480 void* key = lua_touserdata( L, key_i);
1481 valPath = (char*) alloca( strlen( upName_) + 16 + 5);
1482 sprintf( valPath, "%s[U:%p]", upName_, key);
1483 }
1484 else if( lua_type( L, key_i) == LUA_TBOOLEAN)
1485 {
1486 int key = lua_toboolean( L, key_i);
1487 valPath = (char*) alloca( strlen( upName_) + 8);
1488 sprintf( valPath, "%s[%s]", upName_, key ? "true" : "false");
1489 }
1490 }
1491 /*
1492 * Contents of metatables are copied with cache checking;
1493 * important to detect loops.
1494 */
1495 if( inter_copy_one( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath))
1496 {
1497 ASSERT_L( lua_istable( L2, -3));
1498 lua_rawset( L2, -3); // add to table (pops key & val)
1499 }
1500 else
1501 {
1502 luaL_error( L, "Unable to copy %s entry '%s' because of value is of type '%s'", (vt == VT_NORMAL) ? "table" : "metatable", valPath, luaL_typename( L, val_i));
1503 }
1504 }
1505}
1506
1507/*
1508* The clone cache is a weak valued table listing all clones, indexed by their userdatapointer
1509* fnv164 of string "CLONABLES_CACHE_KEY" generated at https://www.pelock.com/products/hash-calculator
1510*/
1511static DECLARE_CONST_UNIQUE_KEY( CLONABLES_CACHE_KEY, 0xD04EE018B3DEE8F5);
1512
1513static bool_t copyclone( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t source_i_, LookupMode mode_, char const* upName_)
1514{
1515 void* const source = lua_touserdata( L, source_i_);
1516 source_i_ = lua_absindex( L, source_i_);
1517
1518 STACK_CHECK( L, 0); // L (source) // L2 (destination)
1519 STACK_CHECK( L2, 0);
1520
1521 // Check if the source was already cloned during this copy
1522 lua_pushlightuserdata( L2, source); // ... source
1523 lua_rawget( L2, L2_cache_i); // ... clone?
1524 if ( !lua_isnil( L2, -1))
1525 {
1526 STACK_MID( L2, 1);
1527 return TRUE;
1528 }
1529 else
1530 {
1531 lua_pop( L2, 1); // ...
1532 }
1533 STACK_MID( L2, 0);
1534
1535 // no metatable? -> not clonable
1536 if( !lua_getmetatable( L, source_i_)) // ... mt?
1537 {
1538 STACK_MID( L, 0);
1539 return FALSE;
1540 }
1541
1542 // no __lanesclone? -> not clonable
1543 lua_getfield( L, -1, "__lanesclone"); // ... mt __lanesclone?
1544 if( lua_isnil( L, -1))
1545 {
1546 lua_pop( L, 2); // ...
1547 STACK_MID( L, 0);
1548 return FALSE;
1549 }
1550
1551 // we need to copy over the uservalues of the userdata as well
1552 {
1553 int const mt = lua_absindex( L, -2); // ... mt __lanesclone
1554 size_t const userdata_size = (size_t) lua_rawlen( L, source_i_);
1555 void* clone = NULL;
1556 // extract all the uservalues, but don't transfer them yet
1557 int uvi = 0;
1558 while( lua_getiuservalue( L, source_i_, ++ uvi) != LUA_TNONE) {} // ... mt __lanesclone [uv]+ nil
1559 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1560 lua_pop( L, 1); // ... mt __lanesclone [uv]+
1561 -- uvi;
1562 // create the clone userdata with the required number of uservalue slots
1563 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... u
1564 // copy the metatable in the target state, and give it to the clone we put there
1565 if( inter_copy_one( U, L2, L2_cache_i, L, mt, VT_NORMAL, mode_, upName_)) // ... u mt|sentinel
1566 {
1567 if( eLM_ToKeeper == mode_) // ... u sentinel
1568 {
1569 ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel);
1570 // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn
1571 lua_getupvalue( L2, -1, 1); // ... u sentinel fqn
1572 lua_remove( L2, -2); // ... u fqn
1573 lua_insert( L2, -2); // ... fqn u
1574 lua_pushcclosure( L2, userdata_clone_sentinel, 2); // ... userdata_clone_sentinel
1575 }
1576 else // from keeper or direct // ... u mt
1577 {
1578 ASSERT_L( lua_istable( L2, -1));
1579 lua_setmetatable( L2, -2); // ... u
1580 }
1581 STACK_MID( L2, 1);
1582 }
1583 else
1584 {
1585 (void) luaL_error( L, "Error copying a metatable");
1586 }
1587 // first, add the entry in the cache (at this point it is either the actual userdata or the keeper sentinel
1588 lua_pushlightuserdata( L2, source); // ... u source
1589 lua_pushvalue( L2, -2); // ... u source u
1590 lua_rawset( L2, L2_cache_i); // ... u
1591 // make sure we have the userdata now
1592 if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel
1593 {
1594 lua_getupvalue( L2, -1, 2); // ... userdata_clone_sentinel u
1595 }
1596 // assign uservalues
1597 while( uvi > 0)
1598 {
1599 inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // ... u uv
1600 lua_pop( L, 1); // ... mt __lanesclone [uv]*
1601 // this pops the value from the stack
1602 lua_setiuservalue( L2, -2, uvi); // ... u
1603 -- uvi;
1604 }
1605 // when we are done, all uservalues are popped from the source stack, and we want only the single transferred value in the destination
1606 if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel u
1607 {
1608 lua_pop( L2, 1); // ... userdata_clone_sentinel
1609 }
1610 STACK_MID( L2, 1);
1611 STACK_MID( L, 2);
1612 // call cloning function in source state to perform the actual memory cloning
1613 lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone
1614 lua_pushlightuserdata( L, source); // ... mt __lanesclone clone source
1615 lua_pushinteger( L, userdata_size); // ... mt __lanesclone clone source size
1616 lua_call( L, 3, 0); // ... mt
1617 STACK_MID( L, 1);
1618 }
1619
1620 STACK_END( L2, 1);
1621 lua_pop( L, 1); // ...
1622 STACK_END( L, 0);
1623 return TRUE;
1624}
1625
1626static bool_t inter_copy_userdata( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1627{
1628 STACK_CHECK( L, 0);
1629 STACK_CHECK( L2, 0);
1630 if( vt == VT_KEY)
1631 {
1632 return FALSE;
1633 }
1634
1635 // try clonable userdata first
1636 if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_))
1637 {
1638 STACK_MID( L, 0);
1639 STACK_MID( L2, 1);
1640 return TRUE;
1641 }
1642
1643 STACK_MID( L, 0);
1644 STACK_MID( L2, 0);
1645
1646 // Allow only deep userdata entities to be copied across
1647 DEBUGSPEW_CODE( fprintf( stderr, "USERDATA\n"));
1648 if( copydeep( U, L2, L2_cache_i, L, i, mode_, upName_))
1649 {
1650 STACK_MID( L, 0);
1651 STACK_MID( L2, 1);
1652 return TRUE;
1653 }
1654
1655 STACK_MID( L, 0);
1656 STACK_MID( L2, 0);
1657
1658 // Not a deep or clonable full userdata
1659 if( U->demoteFullUserdata) // attempt demotion to light userdata
1660 {
1661 void* lud = lua_touserdata( L, i);
1662 lua_pushlightuserdata( L2, lud);
1663 }
1664 else // raise an error
1665 {
1666 (void) luaL_error( L, "can't copy non-deep full userdata across lanes");
1667 }
1668
1669 STACK_END( L2, 1);
1670 STACK_END( L, 0);
1671 return TRUE;
1672}
1673
1674static bool_t inter_copy_function( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t source_i_, enum e_vt vt, LookupMode mode_, char const* upName_)
1675{
1676 if( vt == VT_KEY)
1677 {
1678 return FALSE;
1679 }
1680
1681 STACK_CHECK( L, 0); // L (source) // L2 (destination)
1682 STACK_CHECK( L2, 0);
1683 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_));
1684
1685 if( lua_tocfunction( L, source_i_) == userdata_clone_sentinel) // we are actually copying a clonable full userdata from a keeper
1686 {
1687 // clone the full userdata again
1688 size_t userdata_size = 0;
1689 void* source;
1690 void* clone;
1691
1692 // let's see if we already restored this userdata
1693 lua_getupvalue( L, source_i_, 2); // ... u
1694 source = lua_touserdata( L, -1);
1695 lua_pushlightuserdata( L2, source); // ... source
1696 lua_rawget( L2, L2_cache_i); // ... u?
1697 if( !lua_isnil( L2, -1))
1698 {
1699 lua_pop( L, 1); // ...
1700 STACK_MID( L, 0);
1701 STACK_MID( L2, 1);
1702 return TRUE;
1703 }
1704 lua_pop( L2, 1); // ...
1705
1706 // this function has 2 upvalues: the fqn of its metatable, and the userdata itself
1707 lookup_table( L2, L, source_i_, mode_, upName_); // ... mt
1708 // originally 'source_i_' slot was the proxy closure, but from now on it indexes the actual userdata we extracted from it
1709 source_i_ = lua_gettop( L);
1710 source = lua_touserdata( L, -1);
1711 // get the number of bytes to allocate for the clone
1712 userdata_size = (size_t) lua_rawlen( L, -1);
1713 {
1714 // extract uservalues (don't transfer them yet)
1715 int uvi = 0;
1716 while( lua_getiuservalue( L, source_i_, ++ uvi) != LUA_TNONE) {} // ... u uv
1717 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1718 lua_pop( L, 1); // ... u [uv]*
1719 -- uvi;
1720 STACK_MID( L, uvi + 1);
1721 // create the clone userdata with the required number of uservalue slots
1722 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt u
1723 // add it in the cache
1724 lua_pushlightuserdata( L2, source); // ... mt u source
1725 lua_pushvalue( L2, -2); // ... mt u source u
1726 lua_rawset( L2, L2_cache_i); // ... mt u
1727 // set metatable
1728 lua_pushvalue( L2, -2); // ... mt u mt
1729 lua_setmetatable( L2, -2); // ... mt u
1730 // transfer and assign uservalues
1731 while( uvi > 0)
1732 {
1733 inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), vt, mode_, upName_); // ... mt u uv
1734 lua_pop( L, 1); // ... u [uv]*
1735 // this pops the value from the stack
1736 lua_setiuservalue( L2, -2, uvi); // ... mt u
1737 -- uvi;
1738 }
1739 // when we are done, all uservalues are popped from the stack, we can pop the source as well
1740 lua_pop( L, 1); // ...
1741 STACK_MID( L, 0);
1742 STACK_MID( L2, 2); // ... mt u
1743 }
1744 // perform the custom cloning part
1745 lua_insert( L2, -2); // ... u mt
1746 // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with
1747 lua_getfield(L2, -1, "__lanesclone"); // ... u mt __lanesclone
1748 lua_remove( L2, -2); // ... u __lanesclone
1749 lua_pushlightuserdata( L2, clone); // ... u __lanesclone clone
1750 lua_pushlightuserdata( L2, source); // ... u __lanesclone clone source
1751 lua_pushinteger( L2, userdata_size); // ... u __lanesclone clone source size
1752 // clone:__lanesclone(dest, source, size)
1753 lua_call( L2, 3, 0); // ... u
1754 }
1755 else // regular function
1756 {
1757 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_));
1758 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1759 copy_cached_func( U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f
1760 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1761 }
1762 STACK_END( L2, 1);
1763 STACK_END( L, 0);
1764 return TRUE;
1765}
1766
1767static bool_t inter_copy_table( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1768{
1769 if( vt == VT_KEY)
1770 {
1771 return FALSE;
1772 }
1773
1774 STACK_CHECK( L, 0);
1775 STACK_CHECK( L2, 0);
1776 DEBUGSPEW_CODE( fprintf( stderr, "TABLE %s\n", upName_));
1777
1778 /*
1779 * 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?)
1780 * 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
1781 */
1782 if( lookup_table( L2, L, i, mode_, upName_))
1783 {
1784 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
1785 return TRUE;
1786 }
1787
1788 /* Check if we've already copied the same table from 'L' (during this transmission), and
1789 * reuse the old copy. This allows table upvalues shared by multiple
1790 * local functions to point to the same table, also in the target.
1791 * Also, this takes care of cyclic tables and multiple references
1792 * to the same subtable.
1793 *
1794 * Note: Even metatables need to go through this test; to detect
1795 * loops such as those in required module tables (getmetatable(lanes).lanes == lanes)
1796 */
1797 if( push_cached_table( L2, L2_cache_i, L, i))
1798 {
1799 ASSERT_L( lua_istable( L2, -1)); // from cache
1800 return TRUE;
1801 }
1802 ASSERT_L( lua_istable( L2, -1));
1803
1804 STACK_GROW( L, 2);
1805 STACK_GROW( L2, 2);
1806
1807 lua_pushnil( L); // start iteration
1808 while( lua_next( L, i))
1809 {
1810 // need a function to prevent overflowing the stack with verboseErrors-induced alloca()
1811 inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_);
1812 lua_pop( L, 1); // pop value (next round)
1813 }
1814 STACK_MID( L, 0);
1815 STACK_MID( L2, 1);
1816
1817 // Metatables are expected to be immutable, and copied only once.
1818 if( push_cached_metatable( U, L2, L2_cache_i, L, i, mode_, upName_)) // ... t mt?
1819 {
1820 lua_setmetatable( L2, -2); // ... t
1821 }
1822 STACK_END( L2, 1);
1823 STACK_END( L, 0);
1824 return TRUE;
1825}
1826
1827/*
1828* Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove
1829* the original value.
1830*
1831* NOTE: Both the states must be solely in the current OS thread's possession.
1832*
1833* 'i' is an absolute index (no -1, ...)
1834*
1835* Returns TRUE if value was pushed, FALSE if its type is non-supported.
1836*/
1837bool_t inter_copy_one( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1838{
1839 bool_t ret = TRUE;
1840 int val_type = lua_type( L, i);
1841 static int const pod_mask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING);
1842 STACK_GROW( L2, 1);
1843 STACK_CHECK( L, 0); // L // L2
1844 STACK_CHECK( L2, 0); // L // L2
1845
1846 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END));
1847 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1848 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[vt]));
1849
1850 // Non-POD can be skipped if its metatable contains { __lanesignore = true }
1851 if( ((1 << val_type) & pod_mask) == 0)
1852 {
1853 if( lua_getmetatable( L, i)) // ... mt
1854 {
1855 lua_getfield( L, -1, "__lanesignore"); // ... mt ignore?
1856 if( lua_isboolean( L, -1) && lua_toboolean( L, -1))
1857 {
1858 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "__lanesignore -> LUA_TNIL\n" INDENT_END));
1859 val_type = LUA_TNIL;
1860 }
1861 lua_pop( L, 2); // ...
1862 }
1863 }
1864 STACK_MID( L, 0);
1865
1866 /* Lets push nil to L2 if the object should be ignored */
1867 switch( val_type)
1868 {
1869 /* Basic types allowed both as values, and as table keys */
1870
1871 case LUA_TBOOLEAN:
1872 {
1873 bool_t v = lua_toboolean( L, i);
1874 DEBUGSPEW_CODE( fprintf( stderr, "%s\n", v ? "true" : "false"));
1875 lua_pushboolean( L2, v);
1876 }
1877 break;
1878
1879 case LUA_TNUMBER:
1880 /* LNUM patch support (keeping integer accuracy) */
1881#if defined LUA_LNUM || LUA_VERSION_NUM >= 503
1882 if( lua_isinteger( L, i))
1883 {
1884 lua_Integer v = lua_tointeger( L, i);
1885 DEBUGSPEW_CODE( fprintf( stderr, LUA_INTEGER_FMT "\n", v));
1886 lua_pushinteger( L2, v);
1887 break;
1888 }
1889 else
1890#endif // defined LUA_LNUM || LUA_VERSION_NUM >= 503
1891 {
1892 lua_Number v = lua_tonumber( L, i);
1893 DEBUGSPEW_CODE( fprintf( stderr, LUA_NUMBER_FMT "\n", v));
1894 lua_pushnumber( L2, v);
1895 }
1896 break;
1897
1898 case LUA_TSTRING:
1899 {
1900 size_t len;
1901 char const* s = lua_tolstring( L, i, &len);
1902 DEBUGSPEW_CODE( fprintf( stderr, "'%s'\n", s));
1903 lua_pushlstring( L2, s, len);
1904 }
1905 break;
1906
1907 case LUA_TLIGHTUSERDATA:
1908 {
1909 void* p = lua_touserdata( L, i);
1910 DEBUGSPEW_CODE( fprintf( stderr, "%p\n", p));
1911 lua_pushlightuserdata( L2, p);
1912 }
1913 break;
1914
1915 /* The following types are not allowed as table keys */
1916
1917 case LUA_TUSERDATA:
1918 ret = inter_copy_userdata( U, L2, L2_cache_i, L, i, vt, mode_, upName_);
1919 break;
1920
1921 case LUA_TNIL:
1922 if( vt == VT_KEY)
1923 {
1924 ret = FALSE;
1925 break;
1926 }
1927 lua_pushnil( L2);
1928 break;
1929
1930 case LUA_TFUNCTION:
1931 ret = inter_copy_function( U, L2, L2_cache_i, L, i, vt, mode_, upName_);
1932 break;
1933
1934 case LUA_TTABLE:
1935 ret = inter_copy_table( U, L2, L2_cache_i, L, i, vt, mode_, upName_);
1936 break;
1937
1938 /* The following types cannot be copied */
1939
1940 case 10: // LuaJIT CDATA
1941 case LUA_TTHREAD:
1942 ret = FALSE;
1943 break;
1944 }
1945
1946 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1947
1948 STACK_END( L2, ret ? 1 : 0);
1949 STACK_END( L, 0);
1950 return ret;
1951}
1952
1953/*
1954* Akin to 'lua_xmove' but copies values between _any_ Lua states.
1955*
1956* NOTE: Both the states must be solely in the current OS thread's posession.
1957*
1958* Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'.
1959*/
1960int luaG_inter_copy( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_)
1961{
1962 uint_t top_L = lua_gettop( L); // ... {}n
1963 uint_t top_L2 = lua_gettop( L2); // ...
1964 uint_t i, j;
1965 char tmpBuf[16];
1966 char const* pBuf = U->verboseErrors ? tmpBuf : "?";
1967 bool_t copyok = TRUE;
1968
1969 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy()\n" INDENT_END));
1970 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1971
1972 if( n > top_L)
1973 {
1974 // requesting to copy more than is available?
1975 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "nothing to copy()\n" INDENT_END));
1976 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1977 return -1;
1978 }
1979
1980 STACK_CHECK( L2, 0);
1981 STACK_GROW( L2, n + 1);
1982
1983 /*
1984 * Make a cache table for the duration of this copy. Collects tables and
1985 * function entries, avoiding the same entries to be passed on as multiple
1986 * copies. ESSENTIAL i.e. for handling upvalue tables in the right manner!
1987 */
1988 lua_newtable( L2); // ... cache
1989
1990 STACK_CHECK( L, 0);
1991 for( i = top_L - n + 1, j = 1; i <= top_L; ++ i, ++ j)
1992 {
1993 if( U->verboseErrors)
1994 {
1995 sprintf( tmpBuf, "arg_%d", j);
1996 }
1997 copyok = inter_copy_one( U, L2, top_L2 + 1, L, i, VT_NORMAL, mode_, pBuf); // ... cache {}n
1998 if( !copyok)
1999 {
2000 break;
2001 }
2002 }
2003 STACK_END( L, 0);
2004
2005 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
2006
2007 if( copyok)
2008 {
2009 STACK_MID( L2, n + 1);
2010 // Remove the cache table. Persistent caching would cause i.e. multiple
2011 // messages passed in the same table to use the same table also in receiving end.
2012 lua_remove( L2, top_L2 + 1);
2013 return 0;
2014 }
2015
2016 // error -> pop everything from the target state stack
2017 lua_settop( L2, top_L2);
2018 STACK_END( L2, 0);
2019 return -2;
2020}
2021
2022
2023int luaG_inter_move( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupMode mode_)
2024{
2025 int ret = luaG_inter_copy( U, L, L2, n, mode_);
2026 lua_pop( L, (int) n);
2027 return ret;
2028}
2029
2030int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int package_idx_, LookupMode mode_)
2031{
2032 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END));
2033 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
2034 // package
2035 STACK_CHECK( L, 0);
2036 STACK_CHECK( L2, 0);
2037 package_idx_ = lua_absindex( L, package_idx_);
2038 if( lua_type( L, package_idx_) != LUA_TTABLE)
2039 {
2040 lua_pushfstring( L, "expected package as table, got %s", luaL_typename( L, package_idx_));
2041 STACK_MID( L, 1);
2042 // raise the error when copying from lane to lane, else just leave it on the stack to be raised later
2043 return ( mode_ == eLM_LaneBody) ? lua_error( L) : 1;
2044 }
2045 lua_getglobal( L2, "package");
2046 if( !lua_isnil( L2, -1)) // package library not loaded: do nothing
2047 {
2048 int i;
2049 // package.loaders is renamed package.searchers in Lua 5.2
2050 // but don't copy it anyway, as the function names change depending on the slot index!
2051 // users should provide an on_state_create function to setup custom loaders instead
2052 // don't copy package.preload in keeper states (they don't know how to translate functions)
2053 char const* entries[] = { "path", "cpath", (mode_ == eLM_LaneBody) ? "preload" : NULL/*, (LUA_VERSION_NUM == 501) ? "loaders" : "searchers"*/, NULL};
2054 for( i = 0; entries[i]; ++ i)
2055 {
2056 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "package.%s\n" INDENT_END, entries[i]));
2057 lua_getfield( L, package_idx_, entries[i]);
2058 if( lua_isnil( L, -1))
2059 {
2060 lua_pop( L, 1);
2061 }
2062 else
2063 {
2064 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
2065 luaG_inter_move( U, L, L2, 1, mode_); // moves the entry to L2
2066 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
2067 lua_setfield( L2, -2, entries[i]); // set package[entries[i]]
2068 }
2069 }
2070 }
2071 else
2072 {
2073 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END));
2074 }
2075 lua_pop( L2, 1);
2076 STACK_END( L2, 0);
2077 STACK_END( L, 0);
2078 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
2079 return 0;
2080}