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 |
