aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2018-11-27 17:58:32 +0100
committerBenoit Germain <bnt.germain@gmail.com>2018-11-27 17:58:32 +0100
commit8d097de830d8daf1411cc54ba267f21ecfc3204d (patch)
tree2b5c2ba1268f7f9ecdde09c96dd9c311c2338e58 /src
parent3aed735e5523af04ff24fd73c4b38944d3ab283d (diff)
downloadlanes-8d097de830d8daf1411cc54ba267f21ecfc3204d.tar.gz
lanes-8d097de830d8daf1411cc54ba267f21ecfc3204d.tar.bz2
lanes-8d097de830d8daf1411cc54ba267f21ecfc3204d.zip
Lua 5.4 support
Diffstat (limited to 'src')
-rw-r--r--src/compat.c33
-rw-r--r--src/compat.h30
-rw-r--r--src/deep.c2
-rw-r--r--src/keeper.c13
-rw-r--r--src/lanes.c11
-rw-r--r--src/tools.c91
-rw-r--r--src/universe.c2
7 files changed, 149 insertions, 33 deletions
diff --git a/src/compat.c b/src/compat.c
index c5e29f5..9f36090 100644
--- a/src/compat.c
+++ b/src/compat.c
@@ -4,6 +4,7 @@
4 * ############################################################################################### 4 * ###############################################################################################
5 */ 5 */
6#include "compat.h" 6#include "compat.h"
7#include "macros_and_utils.h"
7 8
8/* 9/*
9** Copied from Lua 5.2 loadlib.c 10** Copied from Lua 5.2 loadlib.c
@@ -42,3 +43,35 @@ void luaL_requiref (lua_State *L, const char *modname, lua_CFunction openf, int
42} 43}
43#endif // LUA_VERSION_NUM 44#endif // LUA_VERSION_NUM
44 45
46#if LUA_VERSION_NUM < 504
47
48void* lua_newuserdatauv( lua_State* L, size_t sz, int nuvalue)
49{
50 ASSERT_L( nuvalue <= 1);
51 return lua_newuserdata( L, sz);
52}
53
54int lua_getiuservalue( lua_State* L, int idx, int n)
55{
56 if( n > 1)
57 {
58 lua_pushnil( L);
59 return LUA_TNONE;
60 }
61 lua_getuservalue( L, idx);
62 return lua_type( L, -1);
63}
64
65int lua_setiuservalue( lua_State* L, int idx, int n)
66{
67 if( n > 1)
68 {
69 lua_pop( L, 1);
70 return 0;
71 }
72 (void) lua_setuservalue( L, idx);
73 return 1; // I guess anything non-0 is ok
74}
75
76#endif // LUA_VERSION_NUM
77
diff --git a/src/compat.h b/src/compat.h
index 998edef..eaa9f85 100644
--- a/src/compat.h
+++ b/src/compat.h
@@ -5,7 +5,8 @@
5#include "lualib.h" 5#include "lualib.h"
6#include "lauxlib.h" 6#include "lauxlib.h"
7 7
8// code is now preferring Lua 5.3 API 8// code is now preferring Lua 5.4 API
9
9// add some Lua 5.3-style API when building for Lua 5.1 10// add some Lua 5.3-style API when building for Lua 5.1
10#if LUA_VERSION_NUM == 501 11#if LUA_VERSION_NUM == 501
11#define lua501_equal lua_equal 12#define lua501_equal lua_equal
@@ -18,7 +19,8 @@
18#define LUA_OK 0 19#define LUA_OK 0
19#define LUA_ERRGCMM 666 // doesn't exist in Lua 5.1, we don't care about the actual value 20#define LUA_ERRGCMM 666 // doesn't exist in Lua 5.1, we don't care about the actual value
20void luaL_requiref (lua_State* L, const char* modname, lua_CFunction openf, int glb); // implementation copied from Lua 5.2 sources 21void luaL_requiref (lua_State* L, const char* modname, lua_CFunction openf, int glb); // implementation copied from Lua 5.2 sources
21#define lua503_dump( L, writer, data, strip) lua_dump( L, writer, data) 22#define lua504_dump( L, writer, data, strip) lua_dump( L, writer, data)
23#define LUA_LOADED_TABLE "_LOADED" // // doesn't exist in Lua 5.1
22#endif // LUA_VERSION_NUM == 501 24#endif // LUA_VERSION_NUM == 501
23 25
24// wrap Lua 5.2 calls under Lua 5.1 API when it is simpler that way 26// wrap Lua 5.2 calls under Lua 5.1 API when it is simpler that way
@@ -30,7 +32,8 @@ void luaL_requiref (lua_State* L, const char* modname, lua_CFunction openf, int
30#define lua_lessthan( L, a, b) lua_compare( L, a, b, LUA_OPLT) 32#define lua_lessthan( L, a, b) lua_compare( L, a, b, LUA_OPLT)
31#endif // lua_lessthan 33#endif // lua_lessthan
32#define luaG_registerlibfuncs( L, _funcs) luaL_setfuncs( L, _funcs, 0) 34#define luaG_registerlibfuncs( L, _funcs) luaL_setfuncs( L, _funcs, 0)
33#define lua503_dump( L, writer, data, strip) lua_dump( L, writer, data) 35#define lua504_dump( L, writer, data, strip) lua_dump( L, writer, data)
36#define LUA_LOADED_TABLE "_LOADED" // // doesn't exist in Lua 5.2
34#endif // LUA_VERSION_NUM == 502 37#endif // LUA_VERSION_NUM == 502
35 38
36// wrap Lua 5.3 calls under Lua 5.1 API when it is simpler that way 39// wrap Lua 5.3 calls under Lua 5.1 API when it is simpler that way
@@ -42,8 +45,27 @@ void luaL_requiref (lua_State* L, const char* modname, lua_CFunction openf, int
42#define lua_lessthan( L, a, b) lua_compare( L, a, b, LUA_OPLT) 45#define lua_lessthan( L, a, b) lua_compare( L, a, b, LUA_OPLT)
43#endif // lua_lessthan 46#endif // lua_lessthan
44#define luaG_registerlibfuncs( L, _funcs) luaL_setfuncs( L, _funcs, 0) 47#define luaG_registerlibfuncs( L, _funcs) luaL_setfuncs( L, _funcs, 0)
45#define lua503_dump lua_dump 48#define lua504_dump lua_dump
46#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) 49#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
47#endif // LUA_VERSION_NUM == 503 50#endif // LUA_VERSION_NUM == 503
48 51
52#if LUA_VERSION_NUM < 504
53void *lua_newuserdatauv( lua_State* L, size_t sz, int nuvalue);
54int lua_getiuservalue( lua_State* L, int idx, int n);
55int lua_setiuservalue( lua_State* L, int idx, int n);
56#endif // LUA_VERSION_NUM < 504
57
58// wrap Lua 5.4 calls under Lua 5.1 API when it is simpler that way
59#if LUA_VERSION_NUM == 504
60#ifndef lua501_equal // already defined when compatibility is active in luaconf.h
61#define lua501_equal( L, a, b) lua_compare( L, a, b, LUA_OPEQ)
62#endif // lua501_equal
63#ifndef lua_lessthan // already defined when compatibility is active in luaconf.h
64#define lua_lessthan( L, a, b) lua_compare( L, a, b, LUA_OPLT)
65#endif // lua_lessthan
66#define luaG_registerlibfuncs( L, _funcs) luaL_setfuncs( L, _funcs, 0)
67#define lua504_dump lua_dump
68#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d)))
69#endif // LUA_VERSION_NUM == 504
70
49#endif // __COMPAT_H__ 71#endif // __COMPAT_H__
diff --git a/src/deep.c b/src/deep.c
index fd92e0c..fadb895 100644
--- a/src/deep.c
+++ b/src/deep.c
@@ -283,7 +283,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, Lo
283 STACK_GROW( L, 7); 283 STACK_GROW( L, 7);
284 STACK_CHECK( L, 0); 284 STACK_CHECK( L, 0);
285 285
286 proxy = lua_newuserdata( L, sizeof(DeepPrelude*)); // DPC proxy 286 proxy = lua_newuserdatauv( L, sizeof(DeepPrelude*), 0); // DPC proxy
287 ASSERT_L( proxy); 287 ASSERT_L( proxy);
288 *proxy = prelude; 288 *proxy = prelude;
289 289
diff --git a/src/keeper.c b/src/keeper.c
index 7eda598..05e9a02 100644
--- a/src/keeper.c
+++ b/src/keeper.c
@@ -65,6 +65,8 @@ typedef struct
65 lua_Integer limit; 65 lua_Integer limit;
66} keeper_fifo; 66} keeper_fifo;
67 67
68static int const CONTENTS_TABLE = 1;
69
68// replaces the fifo ud by its uservalue on the stack 70// replaces the fifo ud by its uservalue on the stack
69static keeper_fifo* prepare_fifo_access( lua_State* L, int idx_) 71static keeper_fifo* prepare_fifo_access( lua_State* L, int idx_)
70{ 72{
@@ -74,7 +76,7 @@ static keeper_fifo* prepare_fifo_access( lua_State* L, int idx_)
74 idx_ = lua_absindex( L, idx_); 76 idx_ = lua_absindex( L, idx_);
75 STACK_GROW( L, 1); 77 STACK_GROW( L, 1);
76 // we can replace the fifo userdata in the stack without fear of it being GCed, there are other references around 78 // we can replace the fifo userdata in the stack without fear of it being GCed, there are other references around
77 lua_getuservalue( L, idx_); 79 lua_getiuservalue( L, idx_, CONTENTS_TABLE);
78 lua_replace( L, idx_); 80 lua_replace( L, idx_);
79 } 81 }
80 return fifo; 82 return fifo;
@@ -86,12 +88,13 @@ static void fifo_new( lua_State* L)
86{ 88{
87 keeper_fifo* fifo; 89 keeper_fifo* fifo;
88 STACK_GROW( L, 2); 90 STACK_GROW( L, 2);
89 fifo = (keeper_fifo*) lua_newuserdata( L, sizeof( keeper_fifo)); 91 // a fifo full userdata has one uservalue, the table that holds the actual fifo contents
92 fifo = (keeper_fifo*)lua_newuserdatauv( L, sizeof( keeper_fifo), 1);
90 fifo->first = 1; 93 fifo->first = 1;
91 fifo->count = 0; 94 fifo->count = 0;
92 fifo->limit = -1; 95 fifo->limit = -1;
93 lua_newtable( L); 96 lua_newtable( L);
94 lua_setuservalue( L, -2); 97 lua_setiuservalue( L, -2, CONTENTS_TABLE);
95} 98}
96 99
97// in: expect fifo ... on top of the stack 100// in: expect fifo ... on top of the stack
@@ -422,7 +425,7 @@ int keepercall_set( lua_State* L)
422 should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit); 425 should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit);
423 lua_remove( L, -2); // fifos fifo 426 lua_remove( L, -2); // fifos fifo
424 lua_newtable( L); // fifos fifo {} 427 lua_newtable( L); // fifos fifo {}
425 lua_setuservalue( L, -2); // fifos fifo 428 lua_setiuservalue( L, -2, CONTENTS_TABLE); // fifos fifo
426 fifo->first = 1; 429 fifo->first = 1;
427 fifo->count = 0; 430 fifo->count = 0;
428 } 431 }
@@ -450,7 +453,7 @@ int keepercall_set( lua_State* L)
450 should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit) && (count < fifo->limit); 453 should_wake_writers = (fifo->limit > 0) && (fifo->count >= fifo->limit) && (count < fifo->limit);
451 // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged! 454 // empty the fifo for the specified key: replace uservalue with a virgin table, reset counters, but leave limit unchanged!
452 lua_newtable( L); // fifos key [val [, ...]] fifo {} 455 lua_newtable( L); // fifos key [val [, ...]] fifo {}
453 lua_setuservalue( L, -2); // fifos key [val [, ...]] fifo 456 lua_setiuservalue( L, -2, CONTENTS_TABLE); // fifos key [val [, ...]] fifo
454 fifo->first = 1; 457 fifo->first = 1;
455 fifo->count = 0; 458 fifo->count = 0;
456 } 459 }
diff --git a/src/lanes.c b/src/lanes.c
index 2ad9bd9..90da9bf 100644
--- a/src/lanes.c
+++ b/src/lanes.c
@@ -114,7 +114,7 @@ static void securize_debug_threadname( lua_State* L, Lane* s)
114{ 114{
115 STACK_CHECK( L, 0); 115 STACK_CHECK( L, 0);
116 STACK_GROW( L, 3); 116 STACK_GROW( L, 3);
117 lua_getuservalue( L, 1); 117 lua_getiuservalue( L, 1, 1);
118 lua_newtable( L); 118 lua_newtable( L);
119 // Lua 5.1 can't do 's->debug_name = lua_pushstring( L, s->debug_name);' 119 // Lua 5.1 can't do 's->debug_name = lua_pushstring( L, s->debug_name);'
120 lua_pushstring( L, s->debug_name); 120 lua_pushstring( L, s->debug_name);
@@ -1376,7 +1376,8 @@ LUAG_FUNC( lane_new)
1376 1376
1377 // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) 1377 // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread)
1378 // 1378 //
1379 ud = lua_newuserdata( L, sizeof( Lane*)); // func libs cancelstep priority globals package required gc_cb lane 1379 // a Lane full userdata needs a single uservalue
1380 ud = lua_newuserdatauv( L, sizeof( Lane*), 1); // func libs cancelstep priority globals package required gc_cb lane
1380 s = *ud = (Lane*) malloc( sizeof( Lane)); 1381 s = *ud = (Lane*) malloc( sizeof( Lane));
1381 if( s == NULL) 1382 if( s == NULL)
1382 { 1383 {
@@ -1422,7 +1423,7 @@ LUAG_FUNC( lane_new)
1422 lua_rawset( L, -3); // func libs cancelstep priority globals package required gc_cb lane uv 1423 lua_rawset( L, -3); // func libs cancelstep priority globals package required gc_cb lane uv
1423 } 1424 }
1424 1425
1425 lua_setuservalue( L, -2); // func libs cancelstep priority globals package required gc_cb lane 1426 lua_setiuservalue( L, -2, 1); // func libs cancelstep priority globals package required gc_cb lane
1426 1427
1427 // Store 's' in the lane's registry, for 'cancel_test()' (even if 'cs'==0 we still do cancel tests at pending send/receive). 1428 // Store 's' in the lane's registry, for 'cancel_test()' (even if 'cs'==0 we still do cancel tests at pending send/receive).
1428 REGISTRY_SET( L2, CANCEL_TEST_KEY, lua_pushlightuserdata( L2, s)); // func [... args ...] 1429 REGISTRY_SET( L2, CANCEL_TEST_KEY, lua_pushlightuserdata( L2, s)); // func [... args ...]
@@ -1461,7 +1462,7 @@ LUAG_FUNC( thread_gc)
1461 Lane* s = lua_toLane( L, 1); // ud 1462 Lane* s = lua_toLane( L, 1); // ud
1462 1463
1463 // if there a gc callback? 1464 // if there a gc callback?
1464 lua_getuservalue( L, 1); // ud uservalue 1465 lua_getiuservalue( L, 1, 1); // ud uservalue
1465 push_unique_key( L, GCCB_KEY); // ud uservalue __gc 1466 push_unique_key( L, GCCB_KEY); // ud uservalue __gc
1466 lua_rawget( L, -2); // ud uservalue gc_cb|nil 1467 lua_rawget( L, -2); // ud uservalue gc_cb|nil
1467 if( !lua_isnil( L, -1)) 1468 if( !lua_isnil( L, -1))
@@ -1724,7 +1725,7 @@ LUAG_FUNC( thread_index)
1724 // first, check that we don't already have an environment that holds the requested value 1725 // first, check that we don't already have an environment that holds the requested value
1725 { 1726 {
1726 // If key is found in the uservalue, return it 1727 // If key is found in the uservalue, return it
1727 lua_getuservalue( L, UD); 1728 lua_getiuservalue( L, UD, 1);
1728 lua_pushvalue( L, KEY); 1729 lua_pushvalue( L, KEY);
1729 lua_rawget( L, USR); 1730 lua_rawget( L, USR);
1730 if( !lua_isnil( L, -1)) 1731 if( !lua_isnil( L, -1))
diff --git a/src/tools.c b/src/tools.c
index 8885dea..4a0aec6 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -120,7 +120,7 @@ static void* protected_lua_Alloc( void *ud, void *ptr, size_t osize, size_t nsiz
120static int luaG_provide_protected_allocator( lua_State* L) 120static int luaG_provide_protected_allocator( lua_State* L)
121{ 121{
122 Universe* U = universe_get( L); 122 Universe* U = universe_get( L);
123 AllocatorDefinition* def = lua_newuserdata( L, sizeof(AllocatorDefinition)); 123 AllocatorDefinition* def = lua_newuserdatauv( L, sizeof(AllocatorDefinition), 0);
124 def->allocF = protected_lua_Alloc; 124 def->allocF = protected_lua_Alloc;
125 def->allocUD = &U->protected_allocator; 125 def->allocUD = &U->protected_allocator;
126 return 1; 126 return 1;
@@ -356,7 +356,7 @@ FuncSubType luaG_getfuncsubtype( lua_State *L, int _i)
356 // the provided writer fails with code 666 356 // the provided writer fails with code 666
357 // therefore, anytime we get 666, this means that lua_dump() attempted a dump 357 // therefore, anytime we get 666, this means that lua_dump() attempted a dump
358 // all other cases mean this is either a C or LuaJIT-fast function 358 // all other cases mean this is either a C or LuaJIT-fast function
359 dumpres = lua503_dump( L, dummy_writer, NULL, 0); 359 dumpres = lua504_dump( L, dummy_writer, NULL, 0);
360 lua_pop( L, mustpush); 360 lua_pop( L, mustpush);
361 if( dumpres == 666) 361 if( dumpres == 666)
362 { 362 {
@@ -1223,19 +1223,27 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_)
1223 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U 1223 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U
1224 } 1224 }
1225 STACK_MID( L, 2); 1225 STACK_MID( L, 2);
1226 // search in the object's uservalue if it is a table 1226 // search in the object's uservalues
1227 lua_getuservalue( L, -1); // o "r" {c} {fqn} ... {?} k U {u}
1228 if( lua_istable( L, -1))
1229 { 1227 {
1230 ++ depth_; 1228 int uvi = 1;
1231 lua_pushliteral( L, "uservalue"); // o "r" {c} {fqn} ... {?} k v {u} "uservalue" 1229 while( lua_getiuservalue( L, -1, uvi) != LUA_TNONE) // o "r" {c} {fqn} ... {?} k U {u}
1232 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u} 1230 {
1233 shortest_ = discover_object_name_recur( L, shortest_, depth_); 1231 if( lua_istable( L, -1)) // if it is a table, look inside
1234 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k v {u} nil 1232 {
1235 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u} 1233 ++ depth_;
1236 -- depth_; 1234 lua_pushliteral( L, "uservalue"); // o "r" {c} {fqn} ... {?} k v {u} "uservalue"
1235 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u}
1236 shortest_ = discover_object_name_recur( L, shortest_, depth_);
1237 lua_pushnil( L); // o "r" {c} {fqn} ... {?} k v {u} nil
1238 lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v {u}
1239 -- depth_;
1240 }
1241 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U
1242 ++ uvi;
1243 }
1244 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1245 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U
1237 } 1246 }
1238 lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U
1239 STACK_MID( L, 2); 1247 STACK_MID( L, 2);
1240 break; 1248 break;
1241 } 1249 }
@@ -1436,7 +1444,7 @@ static void inter_copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_
1436 // "value returned is the error code returned by the last call 1444 // "value returned is the error code returned by the last call
1437 // to the writer" (and we only return 0) 1445 // to the writer" (and we only return 0)
1438 // not sure this could ever fail but for memory shortage reasons 1446 // not sure this could ever fail but for memory shortage reasons
1439 if( lua503_dump( L, buf_writer, &b, 0) != 0) 1447 if( lua504_dump( L, buf_writer, &b, 0) != 0)
1440 { 1448 {
1441 luaL_error( L, "internal error: function dump failed."); 1449 luaL_error( L, "internal error: function dump failed.");
1442 } 1450 }
@@ -1846,7 +1854,32 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu
1846 STACK_MID( L, 3); 1854 STACK_MID( L, 3);
1847 userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size 1855 userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size
1848 lua_pop( L, 1); // ... mt __lanesclone 1856 lua_pop( L, 1); // ... mt __lanesclone
1849 clone = lua_newuserdata( L2, userdata_size); // ... u 1857 // we need to copy over the uservalues of the userdata as well
1858 lua_pushnil( L2); // ... nil
1859 {
1860 int const clone_i = lua_gettop( L2);
1861 int uvi = 0;
1862 while( lua_getiuservalue( L, i, uvi + 1) != LUA_TNONE) // ... mt __lanesclone uv
1863 {
1864 luaG_inter_move( U, L, L2, 1, mode_); // ... mt __lanesclone // ... nil [uv]+
1865 ++ uvi;
1866 }
1867 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1868 lua_pop( L, 1); // ... mt __lanesclone
1869 // create the clone userdata with the required number of uservalue slots
1870 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... nil [uv]+ u
1871 lua_replace( L2, clone_i); // ... u [uv]+
1872 // assign uservalues
1873 while( uvi > 0)
1874 {
1875 // this pops the value from the stack
1876 lua_setiuservalue( L2, clone_i, uvi); // ... u [uv]+
1877 -- uvi;
1878 }
1879 // when we are done, all uservalues are popped from the stack
1880 STACK_MID( L2, 1); // ... u
1881 }
1882 STACK_MID( L, 2); // ... mt __lanesclone
1850 // call cloning function in source state to perform the actual memory cloning 1883 // call cloning function in source state to perform the actual memory cloning
1851 lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone 1884 lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone
1852 lua_pushlightuserdata( L, source); // ... mt __lanesclone source 1885 lua_pushlightuserdata( L, source); // ... mt __lanesclone source
@@ -1920,13 +1953,37 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu
1920 source = lua_touserdata( L, -1); 1953 source = lua_touserdata( L, -1);
1921 lookup_table( L2, L, i, mode_, upName_); // ... u // ... mt 1954 lookup_table( L2, L, i, mode_, upName_); // ... u // ... mt
1922 // __lanesclone should always exist because we woudln't be restoring data from a userdata_clone_sentinel closure to begin with 1955 // __lanesclone should always exist because we woudln't be restoring data from a userdata_clone_sentinel closure to begin with
1923 lua_getfield( L2, -1, "__lanesclone"); // // ... mt __lanesclone 1956 lua_getfield( L2, -1, "__lanesclone"); // ... mt __lanesclone
1924 lua_pushvalue( L2, -1); // ... mt __lanesclone __lanesclone 1957 lua_pushvalue( L2, -1); // ... mt __lanesclone __lanesclone
1925 // call the cloning function with 0 arguments, should return the number of bytes to allocate for the clone 1958 // call the cloning function with 0 arguments, should return the number of bytes to allocate for the clone
1926 lua_call( L2, 0, 1); // ... mt __lanesclone size 1959 lua_call( L2, 0, 1); // ... mt __lanesclone size
1927 userdata_size = (size_t) lua_tointeger( L2, -1); // ... mt __lanesclone size 1960 userdata_size = (size_t) lua_tointeger( L2, -1); // ... mt __lanesclone size
1928 lua_pop( L2, 1); // ... mt __lanesclone 1961 lua_pop( L2, 1); // ... mt __lanesclone
1929 clone = lua_newuserdata( L2, userdata_size); // ... mt __lanesclone u 1962 lua_pushnil( L2); // ... mt __lanesclone nil
1963 {
1964 int const clone_i = lua_gettop( L2);
1965 int uvi = 0;
1966 while( lua_getiuservalue( L, i, uvi + 1) != LUA_TNONE) // ... u uv
1967 {
1968 luaG_inter_move( U, L, L2, 1, mode_); // ... u // ... mt __lanesclone nil [uv]+
1969 ++ uvi;
1970 }
1971 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1972 lua_pop( L, 1); // ... u
1973 // create the clone userdata with the required number of uservalue slots
1974 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt __lanesclone nil [uv]+ u
1975 lua_replace( L2, clone_i); // ... mt __lanesclone u [uv]+
1976 // assign uservalues
1977 while( uvi > 0)
1978 {
1979 // this pops the value from the stack
1980 lua_setiuservalue( L2, clone_i, uvi); // ... mt __lanesclone u [uv]+
1981 -- uvi;
1982 }
1983 // when we are done, all uservalues are popped from the stack
1984 STACK_MID( L2, 3); // ... mt __lanesclone u
1985 }
1986 STACK_MID( L, 1); // u
1930 lua_insert( L2, -3); // ... u mt __lanesclone 1987 lua_insert( L2, -3); // ... u mt __lanesclone
1931 lua_pushlightuserdata( L2, clone); // ... u mt __lanesclone clone 1988 lua_pushlightuserdata( L2, clone); // ... u mt __lanesclone clone
1932 lua_pushlightuserdata( L2, source); // ... u mt __lanesclone clone source 1989 lua_pushlightuserdata( L2, source); // ... u mt __lanesclone clone source
diff --git a/src/universe.c b/src/universe.c
index d531bf2..e1cd38f 100644
--- a/src/universe.c
+++ b/src/universe.c
@@ -43,7 +43,7 @@ static DECLARE_CONST_UNIQUE_KEY( UNIVERSE_REGKEY, 0x9f877b2cf078f17f);
43 43
44Universe* universe_create( lua_State* L) 44Universe* universe_create( lua_State* L)
45{ 45{
46 Universe* U = (Universe*) lua_newuserdata( L, sizeof(Universe)); // universe 46 Universe* U = (Universe*) lua_newuserdatauv( L, sizeof(Universe), 0); // universe
47 memset( U, 0, sizeof( Universe)); 47 memset( U, 0, sizeof( Universe));
48 STACK_CHECK( L, 1); 48 STACK_CHECK( L, 1);
49 REGISTRY_SET( L, UNIVERSE_REGKEY, lua_pushvalue(L, -2)); // universe 49 REGISTRY_SET( L, UNIVERSE_REGKEY, lua_pushvalue(L, -2)); // universe