diff options
author | Benoit Germain <bnt.germain@gmail.com> | 2018-11-27 17:58:32 +0100 |
---|---|---|
committer | Benoit Germain <bnt.germain@gmail.com> | 2018-11-27 17:58:32 +0100 |
commit | 8d097de830d8daf1411cc54ba267f21ecfc3204d (patch) | |
tree | 2b5c2ba1268f7f9ecdde09c96dd9c311c2338e58 /src | |
parent | 3aed735e5523af04ff24fd73c4b38944d3ab283d (diff) | |
download | lanes-8d097de830d8daf1411cc54ba267f21ecfc3204d.tar.gz lanes-8d097de830d8daf1411cc54ba267f21ecfc3204d.tar.bz2 lanes-8d097de830d8daf1411cc54ba267f21ecfc3204d.zip |
Lua 5.4 support
Diffstat (limited to 'src')
-rw-r--r-- | src/compat.c | 33 | ||||
-rw-r--r-- | src/compat.h | 30 | ||||
-rw-r--r-- | src/deep.c | 2 | ||||
-rw-r--r-- | src/keeper.c | 13 | ||||
-rw-r--r-- | src/lanes.c | 11 | ||||
-rw-r--r-- | src/tools.c | 91 | ||||
-rw-r--r-- | src/universe.c | 2 |
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 | |||
48 | void* lua_newuserdatauv( lua_State* L, size_t sz, int nuvalue) | ||
49 | { | ||
50 | ASSERT_L( nuvalue <= 1); | ||
51 | return lua_newuserdata( L, sz); | ||
52 | } | ||
53 | |||
54 | int 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 | |||
65 | int 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 |
20 | void luaL_requiref (lua_State* L, const char* modname, lua_CFunction openf, int glb); // implementation copied from Lua 5.2 sources | 21 | void 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 | ||
53 | void *lua_newuserdatauv( lua_State* L, size_t sz, int nuvalue); | ||
54 | int lua_getiuservalue( lua_State* L, int idx, int n); | ||
55 | int 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__ |
@@ -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 | ||
68 | static 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 |
69 | static keeper_fifo* prepare_fifo_access( lua_State* L, int idx_) | 71 | static 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 | |||
120 | static int luaG_provide_protected_allocator( lua_State* L) | 120 | static 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 | ||
44 | Universe* universe_create( lua_State* L) | 44 | Universe* 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 |