diff options
Diffstat (limited to 'src/tools.c')
-rw-r--r-- | src/tools.c | 91 |
1 files changed, 74 insertions, 17 deletions
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 |