summaryrefslogtreecommitdiff
path: root/src/tools.c
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2011-11-05 17:31:02 +0100
committerBenoit Germain <bnt.germain@gmail.com>2011-11-05 17:31:02 +0100
commit053f7cff3c95acb915e6babfd306971f11bb7986 (patch)
treeee38c60b1119d34eb96aea1105ef033e851d266e /src/tools.c
parent717eadee9c3644fabb32c7ee59949f2846143690 (diff)
downloadlanes-053f7cff3c95acb915e6babfd306971f11bb7986.tar.gz
lanes-053f7cff3c95acb915e6babfd306971f11bb7986.tar.bz2
lanes-053f7cff3c95acb915e6babfd306971f11bb7986.zip
* process exit change: close everything at GC when main state closes, not when atexit() handlers are processed
* Lua 5.2-style module: * module() is no longer used to implement lanes.lua * a global "lanes" variable is no longer created when the module is required * the Lanes module table is returned instead * Lanes must be initialized before used: * the first occurence of 'require "lanes"' produces a minimal interface that only contains a configure() function * the remainder of the interface is made available once this function is called * subsequent calls to configure() do nothing * configure() controls the number of keeper states and the startup of timers * LuaJIT 2 compatibility * non-Lua functions are no longer copied by creating a C closure from a C pointer, but through 2-way lookup tables * this means that if a lane function body pulls non-Lua functions, the lane generator description must contain the list of libraries and modules that exports them * introduces a change in configuration .globals management: contents are copied *after* std libs are loaded * new .required configuration entry to list modules that must be require()'ed before lane body is transferred * lane:cancel() wakes up waiting lindas like what is done at lane shutdown
Diffstat (limited to 'src/tools.c')
-rw-r--r--src/tools.c649
1 files changed, 498 insertions, 151 deletions
diff --git a/src/tools.c b/src/tools.c
index f9854db..b412e84 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -31,6 +31,7 @@ THE SOFTWARE.
31*/ 31*/
32 32
33#include "tools.h" 33#include "tools.h"
34#include "keeper.h"
34 35
35#include "lualib.h" 36#include "lualib.h"
36#include "lauxlib.h" 37#include "lauxlib.h"
@@ -66,7 +67,7 @@ void luaG_dump( lua_State* L ) {
66 // enable it for more debugging. 67 // enable it for more debugging.
67 // 68 //
68 STACK_CHECK(L) 69 STACK_CHECK(L)
69 STACK_GROW( L, 2 ) 70 STACK_GROW( L, 2);
70 71
71 lua_getglobal( L, "tostring" ); 72 lua_getglobal( L, "tostring" );
72 // 73 //
@@ -108,21 +109,302 @@ static const luaL_Reg libs[] = {
108 109
109static bool_t openlib( lua_State *L, const char *name, size_t len ) { 110static bool_t openlib( lua_State *L, const char *name, size_t len ) {
110 111
111 unsigned i; 112 unsigned i;
112 bool_t all= strncmp( name, "*", len ) == 0; 113 bool_t all= strncmp( name, "*", len ) == 0;
113 114
114 for( i=0; libs[i].name; i++ ) { 115 for( i=0; libs[i].name; i++ )
115 if (all || (strncmp(name, libs[i].name, len) ==0)) { 116 {
116 if (libs[i].func) { 117 if (all || (strncmp(name, libs[i].name, len) ==0))
117 STACK_GROW(L,2); 118 {
118 lua_pushcfunction( L, libs[i].func ); 119 if (libs[i].func)
119 lua_pushstring( L, libs[i].name ); 120 {
120 lua_call( L, 1, 0 ); 121 STACK_GROW(L,1);
121 } 122 STACK_CHECK(L)
122 if (!all) return TRUE; 123 lua_pushcfunction( L, libs[i].func);
123 } 124 // pushes the module table on the stack
124 } 125 lua_call( L, 0, 1);
125 return all; 126 populate_func_lookup_table( L, -1, libs[i].name);
127 // remove the module when we are done
128 lua_pop( L, 1);
129 STACK_END(L, 0)
130 }
131 if (!all) return TRUE;
132 }
133 }
134 return all;
135}
136
137static int dummy_writer(lua_State *L, const void* p, size_t sz, void* ud)
138{
139 return 666;
140}
141
142
143/*
144 * differentiation between C, bytecode and JIT-fast functions
145 *
146 *
147 * +----------+------------+----------+
148 * | bytecode | C function | JIT-fast |
149 * +-----------------+----------+------------+----------+
150 * | lua_topointer | | | |
151 * +-----------------+----------+------------+----------+
152 * | lua_tocfunction | NULL | | NULL |
153 * +-----------------+----------+------------+----------+
154 * | lua_dump | 666 | 1 | 1 |
155 * +-----------------+----------+------------+----------+
156 */
157
158typedef enum
159{
160 FST_Bytecode,
161 FST_Native,
162 FST_FastJIT
163} FuncSubType;
164
165FuncSubType luaG_getfuncsubtype( lua_State *L, int _i)
166{
167 if( lua_tocfunction( L, _i))
168 {
169 return FST_Native;
170 }
171 {
172 int mustpush = 0, dumpres;
173 if( STACK_ABS( L, _i) != lua_gettop( L))
174 {
175 lua_pushvalue( L, _i);
176 mustpush = 1;
177 }
178 // the provided writer fails with code 666
179 // therefore, anytime we get 666, this means that lua_dump() attempted a dump
180 // all other cases mean this is either a C or LuaJIT-fast function
181 dumpres = lua_dump( L, dummy_writer, NULL);
182 lua_pop( L, mustpush);
183 if( dumpres == 666)
184 {
185 return FST_Bytecode;
186 }
187 }
188 return FST_FastJIT;
189}
190
191static lua_CFunction luaG_tocfunction( lua_State *L, int _i, FuncSubType *_out)
192{
193 lua_CFunction p = lua_tocfunction( L, _i);
194 *_out = luaG_getfuncsubtype( L, _i);
195 return p;
196}
197
198
199#define LOOKUP_KEY "ddea37aa-50c7-4d3f-8e0b-fb7a9d62bac5"
200#define LOOKUP_KEY_CACHE "d1059270-4976-4193-a55b-c952db5ab7cd"
201
202
203// inspired from tconcat() in ltablib.c
204static char const * luaG_pushFQN(lua_State *L, int t, int last)
205{
206 int i = 1;
207 luaL_Buffer b;
208 STACK_CHECK( L)
209 luaL_buffinit(L, &b);
210 for( ; i < last; i++)
211 {
212 lua_rawgeti( L, t, i);
213 luaL_addvalue( &b);
214 luaL_addlstring(&b, ".", 1);
215 }
216 if (i == last) /* add last value (if interval was not empty) */
217 {
218 lua_rawgeti( L, t, i);
219 luaL_addvalue( &b);
220 }
221 luaL_pushresult( &b);
222 STACK_END( L, 1)
223 return lua_tostring( L, -1);
224}
225
226
227static void populate_func_lookup_table_recur( lua_State *L, int _ctx_base, int _i, int _depth)
228{
229 lua_Integer visit_count;
230 // slot 1 in the stack contains the table that receives everything we found
231 int const dest = _ctx_base;
232 // slot 2 contains a table that, when concatenated, produces the fully qualified name of scanned elements in the table provided at slot _i
233 int const fqn = _ctx_base + 1;
234 // slot 3 contains a cache that stores all already visited tables to avoid infinite recursion loops
235 int const cache = _ctx_base + 2;
236 // we need to remember subtables to process them after functions encountered at the current depth (breadth-first search)
237 int const breadth_first_cache = lua_gettop( L) + 1;
238
239 STACK_GROW( L, 6);
240 // slot _i contains a table where we search for functions
241 STACK_CHECK( L) // ... {_i}
242
243 // if table is already visited, we are done
244 lua_pushvalue( L, _i); // ... {_i} {}
245 lua_rawget( L, cache); // ... {_i} nil|n
246 visit_count = lua_tointeger( L, -1); // 0 if nil, else n
247 lua_pop( L, 1); // ... {_i}
248 STACK_MID( L, 0)
249 if( visit_count > 0)
250 {
251 return;
252 }
253
254 // remember we visited this table (1-visit count)
255 lua_pushvalue( L, _i); // ... {_i} {}
256 lua_pushinteger( L, visit_count + 1); // ... {_i} {} 1
257 lua_rawset( L, cache); // ... {_i}
258 STACK_MID( L, 0)
259
260 // this table is at breadth_first_cache index
261 lua_newtable( L); // ... {_i} {bfc}
262 ASSERT_L( lua_gettop( L) == breadth_first_cache);
263 // iterate over all entries in the processed table
264 lua_pushnil( L); // ... {_i} {bfc} nil
265 while( lua_next( L, _i) != 0) // ... {_i} {bfc} k v
266 {
267 // just for debug, not actually needed
268 //char const * key = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : "not a string";
269 // subtable: process it recursively
270 if( lua_istable( L, -1)) // ... {_i} {bfc} k {}
271 {
272 // increment visit count to make sure we will actually scan it at this recursive level
273 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {}
274 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {} {}
275 lua_rawget( L, cache); // ... {_i} {bfc} k {} {} n?
276 visit_count = lua_tointeger( L, -1) + 1; // 1 if we got nil, else n+1
277 lua_pop( L, 1); // ... {_i} {bfc} k {} {}
278 lua_pushinteger( L, visit_count); // ... {_i} {bfc} k {} {} n
279 lua_rawset( L, cache); // ... {_i} {bfc} k {}
280 // store the table in the breadth-first cache
281 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k
282 lua_insert( L, -2); // ... {_i} {bfc} k k {}
283 lua_rawset( L, breadth_first_cache); // ... {_i} {bfc} k
284 STACK_MID( L, 2)
285 }
286 else if( lua_isfunction( L, -1)) // ... {_i} {bfc} k func
287 {
288 if( luaG_getfuncsubtype( L, -1) != FST_Bytecode)
289 {
290 char const *fqnString;
291 bool_t not_registered;
292 // first, skip everything if the function is already known
293 lua_pushvalue( L, -1); // ... {_i} {bfc} k func func
294 lua_rawget( L, dest); // ... {_i} {bfc} k func name?
295 not_registered = lua_isnil( L, -1);
296 lua_pop( L, 1); // ... {_i} {bfc} k func
297 if( not_registered)
298 {
299 ++ _depth;
300 // push function name in fqn stack (note that concatenation will crash if name is a not string!)
301 lua_pushvalue( L, -2); // ... {_i} {bfc} k func k
302 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k func
303 // generate name
304 fqnString = luaG_pushFQN( L, fqn, _depth); // ... {_i} {bfc} k func "f.q.n"
305 //puts( fqnString);
306 // prepare the stack for database feed
307 lua_pushvalue( L, -1); // ... {_i} {bfc} k func "f.q.n" "f.q.n"
308 lua_pushvalue( L, -3); // ... {_i} {bfc} k func "f.q.n" "f.q.n" func
309 // t["f.q.n"] = func
310 lua_rawset( L, dest); // ... {_i} {bfc} k func "f.q.n"
311 // t[func] = "f.q.n"
312 lua_rawset( L, dest); // ... {_i} {bfc} k
313 // remove table name from fqn stack
314 lua_pushnil( L); // ... {_i} {bfc} k nil
315 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k
316 -- _depth;
317 }
318 else
319 {
320 lua_pop( L, 1); // ... {_i} {bfc} k
321 }
322 }
323 else
324 {
325 lua_pop( L, 1); // ... {_i} {bfc} k
326 }
327 }
328 else
329 {
330 lua_pop( L, 1); // ... {_i} {bfc} k
331 }
332 STACK_MID( L, 2)
333 }
334 // now process the tables we encountered at that depth
335 ++ _depth;
336 lua_pushnil( L); // ... {_i} {bfc} nil
337 while( lua_next( L, breadth_first_cache) != 0) // ... {_i} {bfc} k {}
338 {
339 // un-visit this table in case we do need to process it
340 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {}
341 lua_rawget( L, cache); // ... {_i} {bfc} k {} n
342 ASSERT_L( lua_type( L, -1) == LUA_TNUMBER);
343 visit_count = lua_tointeger( L, -1) - 1;
344 lua_pop( L, 1); // ... {_i} {bfc} k {}
345 lua_pushvalue( L, -1); // ... {_i} {bfc} k {} {}
346 if( visit_count > 0)
347 {
348 lua_pushinteger( L, visit_count); // ... {_i} {bfc} k {} {} n
349 }
350 else
351 {
352 lua_pushnil( L); // ... {_i} {bfc} k {} {} nil
353 }
354 lua_rawset( L, cache); // ... {_i} {bfc} k {}
355 // push table name in fqn stack (note that concatenation will crash if name is a not string!)
356 lua_pushvalue( L, -2); // ... {_i} {bfc} k {} k
357 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k {}
358 populate_func_lookup_table_recur( L, _ctx_base, lua_gettop( L), _depth); // ... {_i} {bfc} k {}
359 lua_pop( L, 1); // ... {_i} {bfc} k
360 STACK_MID( L, 2)
361 }
362 // remove table name from fqn stack
363 lua_pushnil( L); // ... {_i} {bfc} nil
364 lua_rawseti( L, fqn, _depth); // ... {_i} {bfc}
365 -- _depth;
366 // we are done with our cache
367 lua_pop( L, 1); // ... {_i}
368 STACK_END( L, 0)
369 // we are done // ... {_i} {bfc}
370}
371
372/*
373 * create a "fully.qualified.name" <-> function equivalence dabase
374 */
375void populate_func_lookup_table( lua_State *L, int _i, char const *_name)
376{
377 int const ctx_base = lua_gettop( L) + 1;
378 int const in_base = STACK_ABS( L, _i);
379 int const start_depth = _name ? 1 : 0;
380 //printf( "%p: populate_func_lookup_table('%s')\n", L, _name ? _name : "NULL");
381 STACK_GROW( L, 3);
382 STACK_CHECK( L)
383 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}?
384 if( lua_isnil( L, -1)) // nil
385 {
386 lua_pop( L, 1); //
387 lua_newtable( L); // {}
388 lua_pushvalue( L, -1); // {} {}
389 lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}
390 }
391 lua_newtable( L); // {} {fqn}
392 if( _name)
393 {
394 lua_pushstring( L, _name); // {} {fqn} "name"
395 lua_rawseti( L, -2, start_depth); // {} {fqn}
396 }
397 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY_CACHE); // {} {fqn} {cache}?
398 if( lua_isnil( L, -1))
399 {
400 lua_pop( L, 1); // {} {fqn}
401 lua_newtable( L); // {} {fqn} {cache}
402 lua_pushvalue( L, -1); // {} {fqn} {cache} {cache}
403 lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY_CACHE); // {} {fqn} {cache}
404 }
405 populate_func_lookup_table_recur( L, ctx_base, in_base, start_depth); // {...} {fqn} {cache}
406 lua_pop( L, 3);
407 STACK_END( L, 0)
126} 408}
127 409
128/* 410/*
@@ -139,33 +421,39 @@ static bool_t openlib( lua_State *L, const char *name, size_t len ) {
139*/ 421*/
140#define is_name_char(c) (isalpha(c) || (c)=='*') 422#define is_name_char(c) (isalpha(c) || (c)=='*')
141 423
142const char *luaG_openlibs( lua_State *L, const char *libs ) { 424const char *luaG_openlibs( lua_State *L, const char *libs)
143 const char *p; 425{
144 unsigned len; 426 const char *p;
427 unsigned len;
145 428
146 if (!libs) return NULL; // no libs, not even 'base' 429 if (!libs) return NULL; // no libs, not even 'base'
147 430
148 // 'lua.c' stops GC during initialization so perhaps its a good idea. :) 431 // 'lua.c' stops GC during initialization so perhaps its a good idea. :)
149 // 432 //
150 lua_gc(L, LUA_GCSTOP, 0); 433 lua_gc( L, LUA_GCSTOP, 0);
151 434
152 // Anything causes 'base' to be taken in 435 // Anything causes 'base' to be taken in
153 // 436 //
154 STACK_GROW(L,2); 437 STACK_GROW(L,2);
155 lua_pushcfunction( L, luaopen_base ); 438 STACK_CHECK(L)
156 lua_pushliteral( L, "" ); 439 lua_pushcfunction( L, luaopen_base);
157 lua_call( L, 1, 0 ); 440 lua_call( L, 0, 1);
158 441 // after opening base, register the functions they exported in our name<->function database
159 for( p= libs; *p; p+=len ) { 442 populate_func_lookup_table( L, LUA_GLOBALSINDEX, NULL);
160 len=0; 443 lua_pop( L, 1);
161 while (*p && !is_name_char(*p)) p++; // bypass delimiters 444 STACK_MID( L, 0);
162 while (is_name_char(p[len])) len++; // bypass name 445 for( p= libs; *p; p+=len )
163 if (len && (!openlib( L, p, len ))) 446 {
164 break; 447 len=0;
165 } 448 while (*p && !is_name_char(*p)) p++; // bypass delimiters
166 lua_gc(L, LUA_GCRESTART, 0); 449 while (is_name_char(p[len])) len++; // bypass name
450 if (len && (!openlib( L, p, len )))
451 break;
452 }
453 STACK_END(L,0)
454 lua_gc(L, LUA_GCRESTART, 0);
167 455
168 return *p ? p : NULL; 456 return *p ? p : NULL;
169} 457}
170 458
171 459
@@ -284,7 +572,7 @@ luaG_IdFunction get_idfunc( lua_State *L, int index )
284{ 572{
285 luaG_IdFunction ret; 573 luaG_IdFunction ret;
286 574
287 index= STACK_ABS(L,index); 575 index = STACK_ABS( L, index);
288 576
289 STACK_GROW(L,1); 577 STACK_GROW(L,1);
290 578
@@ -696,7 +984,7 @@ uint_t get_mt_id( lua_State *L, int i ) {
696 static uint_t last_id= 0; 984 static uint_t last_id= 0;
697 uint_t id; 985 uint_t id;
698 986
699 i= STACK_ABS(L,i); 987 i = STACK_ABS( L, i);
700 988
701 STACK_GROW(L,3); 989 STACK_GROW(L,3);
702 990
@@ -819,8 +1107,8 @@ static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uin
819 1107
820static void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) 1108static void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i )
821{ 1109{
1110 void * const aspointer = (void*)lua_topointer( L, i );
822 // TBD: Merge this and same code for tables 1111 // TBD: Merge this and same code for tables
823
824 ASSERT_L( L2_cache_i != 0 ); 1112 ASSERT_L( L2_cache_i != 0 );
825 1113
826 STACK_GROW(L2,3); 1114 STACK_GROW(L2,3);
@@ -832,7 +1120,7 @@ static void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, ui
832 // We don't need to use the from state ('L') in ID since the life span 1120 // We don't need to use the from state ('L') in ID since the life span
833 // is only for the duration of a copy (both states are locked). 1121 // is only for the duration of a copy (both states are locked).
834 // 1122 //
835 lua_pushlightuserdata( L2, (void*)lua_topointer( L, i )); // push a light userdata uniquely representing the function 1123 lua_pushlightuserdata( L2, aspointer); // push a light userdata uniquely representing the function
836 1124
837 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) ); 1125 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
838 1126
@@ -886,9 +1174,46 @@ static void push_cached_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, ui
886 // 1174 //
887 // L2 [-1]: function 1175 // L2 [-1]: function
888 1176
889 ASSERT_L( lua_isfunction(L2,-1) ); 1177 ASSERT_L( lua_isfunction(L2,-1));
890} 1178}
891 1179
1180/*
1181* Push a looked-up native/LuaJIT function.
1182*/
1183static void lookup_native_func( lua_State *L2, lua_State *L, uint_t i)
1184{
1185 char const *fqn;
1186 size_t len;
1187 _ASSERT_L( L, lua_isfunction( L, i));
1188 STACK_CHECK( L)
1189 STACK_CHECK( L2)
1190 // fetch the name from the source state's lookup table
1191 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}
1192 _ASSERT_L( L, lua_istable( L, -1));
1193 lua_pushvalue( L, i); // {} f
1194 lua_rawget( L, -2); // {} "f.q.n"
1195 fqn = lua_tolstring( L, -1, &len);
1196 if( !fqn)
1197 {
1198 luaL_error( L, "function not found in origin transfer database.");
1199 }
1200 // push the equivalent function in the destination's stack, retrieved from the lookup table
1201 lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}
1202 _ASSERT_L( L2, lua_istable( L2, -1));
1203 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
1204 lua_pop( L, 2); //
1205 lua_rawget( L2, -2); // {} f
1206 if( !lua_isfunction( L2, -1))
1207 {
1208 // yarglah: luaL_error formatting doesn't support string width modifier!
1209 char message[256];
1210 sprintf( message, "function %*s not found in destination transfer database.", len, fqn);
1211 luaL_error( L, message);
1212 }
1213 lua_remove( L2, -2); // f
1214 STACK_END( L2, 1)
1215 STACK_END( L, 0)
1216}
892 1217
893#define LOG_FUNC_INFO 0 1218#define LOG_FUNC_INFO 0
894 1219
@@ -900,114 +1225,132 @@ enum e_vt {
900}; 1225};
901static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i, enum e_vt value_type ); 1226static bool_t inter_copy_one_( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i, enum e_vt value_type );
902 1227
903static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i ) { 1228static void inter_copy_func( lua_State *L2, uint_t L2_cache_i, lua_State *L, uint_t i )
904 1229{
905 lua_CFunction cfunc= lua_tocfunction( L,i ); 1230 FuncSubType funcSubType;
906 unsigned n; 1231 lua_CFunction cfunc = luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions
907 1232 i = STACK_ABS( L, i);
908 ASSERT_L( L2_cache_i != 0 );
909
910 STACK_GROW(L,2);
911
912 STACK_CHECK(L)
913 if (!cfunc) { // Lua function
914 luaL_Buffer b;
915 const char *s;
916 size_t sz;
917 int tmp;
918 const char *name= NULL;
919 int linedefined = 0;
920 1233
921#if LOG_FUNC_INFO 1234 ASSERT_L( L2_cache_i != 0 );
922 // "To get information about a function you push it onto the 1235 STACK_GROW(L,2);
923 // stack and start the what string with the character '>'." 1236 STACK_CHECK(L)
924 //
925 { lua_Debug ar;
926 lua_pushvalue( L, i );
927 lua_getinfo(L, ">nS", &ar); // fills 'name' 'namewhat' and 'linedefined', pops function
928 name= ar.namewhat;
929 linedefined = ar.linedefined;
930 fprintf( stderr, "NAME: %s @ %d\n", ar.short_src, linedefined); // just gives NULL
931 }
932#endif // LOG_FUNC_INFO
933 // 'lua_dump()' needs the function at top of stack
934 //
935 if (i!=-1) lua_pushvalue( L, i );
936 1237
937 luaL_buffinit(L,&b); 1238 if( funcSubType == FST_Bytecode)
938 tmp= lua_dump(L, buf_writer, &b); 1239 {
939 ASSERT_L(tmp==0); 1240 unsigned n;
940 // 1241 luaL_Buffer b;
941 // "value returned is the error code returned by the last call 1242 // 'lua_dump()' needs the function at top of stack
942 // to the writer" (and we only return 0) 1243 // if already on top of the stack, no need to push again
1244 int needToPush = (i != lua_gettop( L));
1245 if( needToPush)
1246 lua_pushvalue( L, i);
1247
1248 luaL_buffinit( L, &b);
1249 //
1250 // "value returned is the error code returned by the last call
1251 // to the writer" (and we only return 0)
1252 // not sure this could ever fail but for memory shortage reasons
1253 if( lua_dump( L, buf_writer, &b) != 0)
1254 {
1255 luaL_error( L, "internal error: function dump failed.");
1256 }
943 1257
944 luaL_pushresult(&b); // pushes dumped string on 'L' 1258 luaL_pushresult( &b); // pushes dumped string on 'L'
945 s= lua_tolstring(L,-1,&sz);
946 ASSERT_L( s && sz );
947 1259
948 if (i!=-1) lua_remove( L, -2 ); 1260 // if not pushed, no need to pop
1261 if( needToPush)
1262 {
1263 lua_remove( L, -2);
1264 }
949 1265
950 // Note: Line numbers seem to be taken precisely from the 1266 // transfer the bytecode, then the upvalues, to create a similar closure
951 // original function. 'name' is not used since the chunk 1267 {
952 // is precompiled (it seems...). 1268 const char *name= NULL;
953 // 1269
954 // TBD: Can we get the function's original name through, as well? 1270 #if LOG_FUNC_INFO
955 // 1271 // "To get information about a function you push it onto the
956 if (luaL_loadbuffer(L2, s, sz, name) != 0) { 1272 // stack and start the what string with the character '>'."
957 // chunk is precompiled so only LUA_ERRMEM can happen 1273 //
958 // "Otherwise, it pushes an error message" 1274 {
959 // 1275 lua_Debug ar;
960 STACK_GROW( L,1 ); 1276 lua_pushvalue( L, i );
961 luaL_error( L, "%s", lua_tostring(L2,-1) ); 1277 lua_getinfo(L, ">nS", &ar); // fills 'name' 'namewhat' and 'linedefined', pops function
962 } 1278 name= ar.namewhat;
963 lua_pop(L,1); // remove the dumped string 1279 fprintf( stderr, "NAME: %s @ %d\n", ar.short_src, ar.linedefined); // just gives NULL
964 STACK_MID(L,0) 1280 }
965 } 1281 #endif // LOG_FUNC_INFO
1282 {
1283 const char *s;
1284 size_t sz;
1285 s = lua_tolstring( L, -1, &sz);
1286 ASSERT_L( s && sz);
1287
1288 // Note: Line numbers seem to be taken precisely from the
1289 // original function. 'name' is not used since the chunk
1290 // is precompiled (it seems...).
1291 //
1292 // TBD: Can we get the function's original name through, as well?
1293 //
1294 if (luaL_loadbuffer(L2, s, sz, name) != 0)
1295 {
1296 // chunk is precompiled so only LUA_ERRMEM can happen
1297 // "Otherwise, it pushes an error message"
1298 //
1299 STACK_GROW( L,1);
1300 luaL_error( L, "%s", lua_tostring(L2,-1));
1301 }
1302 lua_pop( L, 1); // remove the dumped string
1303 }
1304 STACK_MID( L, 0)
1305
1306 /* push over any upvalues; references to this function will come from
1307 * cache so we don't end up in eternal loop.
1308 */
1309 for( n=0; lua_getupvalue( L, i, 1+n ) != NULL; n++ )
1310 {
1311 if ((!cfunc) && lua_equal(L,i,-1))
1312 {
1313 /* Lua closure that has a (recursive) upvalue to itself
1314 */
1315 lua_pushvalue( L2, -((int)n)-1 );
1316 }
1317 else
1318 {
1319 if( !inter_copy_one_( L2, L2_cache_i, L, lua_gettop(L), VT_NORMAL))
1320 luaL_error( L, "Cannot copy upvalue type '%s'", luaG_typename( L, -1));
1321 }
1322 lua_pop( L, 1);
1323 }
1324 // L2: function + 'n' upvalues (>=0)
1325
1326 STACK_MID(L,0)
1327
1328 // Set upvalues (originally set to 'nil' by 'lua_load')
1329 {
1330 int func_index = lua_gettop( L2) - n;
1331 for( ; n > 0; -- n)
1332 {
1333 char const *rc = lua_setupvalue( L2, func_index, n);
1334 //
1335 // "assigns the value at the top of the stack to the upvalue and returns its name.
1336 // It also pops the value from the stack."
1337
1338 ASSERT_L(rc); // not having enough slots?
1339 }
1340 }
1341 }
1342 }
1343 else // C function OR LuaJIT fast function!!!
1344 {
966#if LOG_FUNC_INFO 1345#if LOG_FUNC_INFO
967 else 1346 fprintf( stderr, "NAME: [C] function %p \n", cfunc);
968 {
969 fprintf( stderr, "NAME: [C] function %p \n", cfunc);
970 }
971#endif // LOG_FUNC_INFO 1347#endif // LOG_FUNC_INFO
972 1348 // No need to transfer upvalues for C/JIT functions since they weren't actually copied, only looked up
973 /* push over any upvalues; references to this function will come from 1349 lookup_native_func( L2, L, i);
974 * cache so we don't end up in eternal loop. 1350 }
975 */ 1351 STACK_END(L,0)
976 for( n=0; lua_getupvalue( L, i, 1+n ) != NULL; n++ ) {
977 if ((!cfunc) && lua_equal(L,i,-1)) {
978 /* Lua closure that has a (recursive) upvalue to itself
979 */
980 lua_pushvalue( L2, -((int)n)-1 );
981 } else {
982 if (!inter_copy_one_( L2, L2_cache_i, L, lua_gettop(L), VT_NORMAL ))
983 luaL_error( L, "Cannot copy upvalue type '%s'", luaG_typename(L,-1) );
984 }
985 lua_pop(L,1);
986 }
987 // L2: function + 'n' upvalues (>=0)
988
989 STACK_MID(L,0)
990
991 if (cfunc) {
992 lua_pushcclosure( L2, cfunc, n ); // eats up upvalues
993 } else {
994 // Set upvalues (originally set to 'nil' by 'lua_load')
995 //
996 int func_index= lua_gettop(L2)-n;
997
998 for( ; n>0; n-- ) {
999 const char *rc= lua_setupvalue( L2, func_index, n );
1000 //
1001 // "assigns the value at the top of the stack to the upvalue and returns its name.
1002 // It also pops the value from the stack."
1003
1004 ASSERT_L(rc); // not having enough slots?
1005 }
1006 }
1007 STACK_END(L,0)
1008} 1352}
1009 1353
1010
1011/* 1354/*
1012* Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove 1355* Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove
1013* the original value. 1356* the original value.
@@ -1300,32 +1643,36 @@ MUTEX_T require_cs;
1300// 1643//
1301// Upvalues: [1]: original 'require' function 1644// Upvalues: [1]: original 'require' function
1302// 1645//
1303static int new_require( lua_State *L ) 1646static int new_require( lua_State *L)
1304{ 1647{
1305 int rc; 1648 int rc, i;
1306 int args= lua_gettop(L); 1649 int args = lua_gettop( L);
1650 //char const *modname = luaL_checkstring( L, 1);
1307 1651
1308 STACK_GROW(L,1); 1652 STACK_GROW( L, args + 1);
1309 STACK_CHECK(L) 1653 STACK_CHECK( L)
1654
1655 lua_pushvalue( L, lua_upvalueindex(1));
1656 for( i = 1; i <= args; ++ i)
1657 lua_pushvalue( L, i);
1310 1658
1311 // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would 1659 // Using 'lua_pcall()' to catch errors; otherwise a failing 'require' would
1312 // leave us locked, blocking any future 'require' calls from other lanes. 1660 // leave us locked, blocking any future 'require' calls from other lanes.
1313 // 1661 //
1314 MUTEX_LOCK( &require_cs); 1662 MUTEX_LOCK( &require_cs);
1315 { 1663 {
1316 lua_pushvalue( L, lua_upvalueindex(1) ); 1664 rc = lua_pcall( L, args, 1 /*retvals*/, 0 /*errfunc*/ );
1317 lua_insert( L, 1 );
1318
1319 rc= lua_pcall( L, args, 1 /*retvals*/, 0 /*errfunc*/ );
1320 // 1665 //
1321 // LUA_ERRRUN / LUA_ERRMEM 1666 // LUA_ERRRUN / LUA_ERRMEM
1322 } 1667 }
1323 MUTEX_UNLOCK( &require_cs); 1668 MUTEX_UNLOCK( &require_cs);
1324 1669
1670 // the required module (or an error message) is left on the stack as returned value by original require function
1671 STACK_END( L, 1)
1672
1325 if (rc) 1673 if (rc)
1326 lua_error(L); // error message already at [-1] 1674 lua_error(L); // error message already at [-1]
1327 1675
1328 STACK_END(L,0)
1329 return 1; 1676 return 1;
1330} 1677}
1331 1678