aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2018-11-28 17:00:45 +0100
committerBenoit Germain <bnt.germain@gmail.com>2018-11-28 17:00:45 +0100
commitf8a18ec679f0fc4627e95b893bc0d3560052dc64 (patch)
tree74df382a5a4bafc5a2ed27725f72cf1339580f29 /src
parent8d097de830d8daf1411cc54ba267f21ecfc3204d (diff)
downloadlanes-f8a18ec679f0fc4627e95b893bc0d3560052dc64.tar.gz
lanes-f8a18ec679f0fc4627e95b893bc0d3560052dc64.tar.bz2
lanes-f8a18ec679f0fc4627e95b893bc0d3560052dc64.zip
Split a megafunction in smaller parts
Diffstat (limited to 'src')
-rw-r--r--src/tools.c493
1 files changed, 259 insertions, 234 deletions
diff --git a/src/tools.c b/src/tools.c
index 4a0aec6..4e893f3 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1398,7 +1398,7 @@ enum e_vt
1398 VT_KEY, 1398 VT_KEY,
1399 VT_METATABLE 1399 VT_METATABLE
1400}; 1400};
1401static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt value_type, LookupMode mode_, char const* upName_); 1401static bool_t inter_copy_one( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt value_type, LookupMode mode_, char const* upName_);
1402 1402
1403#if USE_DEBUG_SPEW 1403#if USE_DEBUG_SPEW
1404static char const* lua_type_names[] = 1404static char const* lua_type_names[] =
@@ -1423,7 +1423,7 @@ static char const* vt_names[] =
1423}; 1423};
1424#endif // USE_DEBUG_SPEW 1424#endif // USE_DEBUG_SPEW
1425 1425
1426static void inter_copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) 1426static void copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
1427{ 1427{
1428 int n, needToPush; 1428 int n, needToPush;
1429 luaL_Buffer b; 1429 luaL_Buffer b;
@@ -1532,7 +1532,7 @@ static void inter_copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_
1532#endif // LUA_VERSION_NUM 1532#endif // LUA_VERSION_NUM
1533 { 1533 {
1534 DEBUGSPEW_CODE( fprintf( stderr, "copying value\n")); 1534 DEBUGSPEW_CODE( fprintf( stderr, "copying value\n"));
1535 if( !inter_copy_one_( U, L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, mode_, upname)) // ... {cache} ... function <upvalues> 1535 if( !inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, mode_, upname)) // ... {cache} ... function <upvalues>
1536 { 1536 {
1537 luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1)); 1537 luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1));
1538 } 1538 }
@@ -1572,7 +1572,7 @@ static void inter_copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_
1572 * 1572 *
1573 * Always pushes a function to 'L2'. 1573 * Always pushes a function to 'L2'.
1574 */ 1574 */
1575static void push_cached_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) 1575static void copy_cached_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_)
1576{ 1576{
1577 FuncSubType funcSubType; 1577 FuncSubType funcSubType;
1578 /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions 1578 /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions
@@ -1608,7 +1608,7 @@ static void push_cached_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua
1608 // via upvalues 1608 // via upvalues
1609 // 1609 //
1610 // pushes a copy of the func, stores a reference in the cache 1610 // pushes a copy of the func, stores a reference in the cache
1611 inter_copy_func( U, L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function 1611 copy_func( U, L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function
1612 } 1612 }
1613 else // found function in the cache 1613 else // found function in the cache
1614 { 1614 {
@@ -1643,7 +1643,7 @@ static bool_t push_cached_metatable( Universe* U, lua_State* L2, uint_t L2_cache
1643 if( lua_isnil( L2, -1)) 1643 if( lua_isnil( L2, -1))
1644 { // L2 did not know the metatable 1644 { // L2 did not know the metatable
1645 lua_pop( L2, 1); // rst 1645 lua_pop( L2, 1); // rst
1646 if( inter_copy_one_( U, L2, L2_cache_i, L, lua_gettop( L), VT_METATABLE, mode_, upName_)) // rst mt 1646 if( inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_METATABLE, mode_, upName_)) // rst mt
1647 { 1647 {
1648 STACK_MID( L2, 2); 1648 STACK_MID( L2, 2);
1649 // mt_id -> metatable 1649 // mt_id -> metatable
@@ -1677,7 +1677,7 @@ static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache
1677 uint_t key_i = val_i - 1; 1677 uint_t key_i = val_i - 1;
1678 1678
1679 // Only basic key types are copied over; others ignored 1679 // Only basic key types are copied over; others ignored
1680 if( inter_copy_one_( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_)) 1680 if( inter_copy_one( U, L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_))
1681 { 1681 {
1682 char* valPath = (char*) upName_; 1682 char* valPath = (char*) upName_;
1683 if( U->verboseErrors) 1683 if( U->verboseErrors)
@@ -1723,7 +1723,7 @@ static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache
1723 * Contents of metatables are copied with cache checking; 1723 * Contents of metatables are copied with cache checking;
1724 * important to detect loops. 1724 * important to detect loops.
1725 */ 1725 */
1726 if( inter_copy_one_( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath)) 1726 if( inter_copy_one( U, L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath))
1727 { 1727 {
1728 ASSERT_L( lua_istable( L2, -3)); 1728 ASSERT_L( lua_istable( L2, -3));
1729 lua_rawset( L2, -3); // add to table (pops key & val) 1729 lua_rawset( L2, -3); // add to table (pops key & val)
@@ -1735,6 +1735,251 @@ static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache
1735 } 1735 }
1736} 1736}
1737 1737
1738static bool_t inter_copy_userdata( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1739{
1740 STACK_CHECK( L, 0);
1741 STACK_CHECK( L2, 0);
1742 if( vt == VT_KEY)
1743 {
1744 return FALSE;
1745 }
1746 // Allow only deep userdata entities to be copied across
1747 DEBUGSPEW_CODE( fprintf( stderr, "USERDATA\n"));
1748 if( copydeep( U, L, L2, i, mode_))
1749 {
1750 return TRUE;
1751 }
1752
1753 if( !lua_getmetatable( L, i)) // ... mt?
1754 {
1755 return FALSE;
1756 }
1757
1758 lua_getfield( L, -1, "__lanesclone"); // ... mt __lanesclone?
1759 if( lua_isnil( L, -1))
1760 {
1761 lua_pop( L, 2); // ...
1762 return FALSE;
1763 }
1764
1765 {
1766 size_t userdata_size = 0;
1767 void* const source = lua_touserdata( L, i);
1768 void* clone = NULL;
1769 lua_pushvalue( L, -1); // ... mt __lanesclone __lanesclone
1770 // call the cloning function with 0 arguments, should return the number of bytes to allocate for the clone
1771 lua_call( L, 0, 1); // ... mt __lanesclone size
1772 STACK_MID( L, 3);
1773 userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size
1774 lua_pop( L, 1); // ... mt __lanesclone
1775 // we need to copy over the uservalues of the userdata as well
1776 lua_pushnil( L2); // ... nil
1777 {
1778 int const clone_i = lua_gettop( L2);
1779 int uvi = 0;
1780 while( lua_getiuservalue( L, i, uvi + 1) != LUA_TNONE) // ... mt __lanesclone uv
1781 {
1782 luaG_inter_move( U, L, L2, 1, mode_); // ... mt __lanesclone // ... nil [uv]+
1783 ++ uvi;
1784 }
1785 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1786 lua_pop( L, 1); // ... mt __lanesclone
1787 // create the clone userdata with the required number of uservalue slots
1788 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... nil [uv]+ u
1789 lua_replace( L2, clone_i); // ... u [uv]+
1790 // assign uservalues
1791 while( uvi > 0)
1792 {
1793 // this pops the value from the stack
1794 lua_setiuservalue( L2, clone_i, uvi); // ... u [uv]+
1795 -- uvi;
1796 }
1797 // when we are done, all uservalues are popped from the stack
1798 STACK_MID( L2, 1); // ... u
1799 }
1800 STACK_MID( L, 2); // ... mt __lanesclone
1801 // call cloning function in source state to perform the actual memory cloning
1802 lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone
1803 lua_pushlightuserdata( L, source); // ... mt __lanesclone source
1804 lua_call( L, 2, 0); // ... mt
1805 STACK_MID( L, 1);
1806 // copy the metatable in the target state
1807 if( inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_)) // ... u mt?
1808 {
1809 lua_pop( L, 1); // ...
1810 STACK_MID( L, 0);
1811 // when writing to a keeper state, we have here a sentinel function with the metatable's fqn as upvalue
1812 if( eLM_ToKeeper == mode_) // ... u sentinel
1813 {
1814 ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel);
1815 // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn
1816 lua_getupvalue( L2, -1, 1); // ... u sentinel fqn
1817 lua_remove( L2, -2); // ... u fqn
1818 lua_insert( L2, -2); // ... fqn u
1819 lua_pushcclosure( L2, userdata_clone_sentinel, 2); // ... userdata_clone_sentinel
1820 }
1821 else // from keeper or direct, we have the userdata and the metatable
1822 {
1823 ASSERT_L( lua_istable( L2, -1));
1824 lua_setmetatable( L2, -2); // ... u
1825 }
1826 return TRUE;
1827 }
1828 else
1829 {
1830 (void) luaL_error( L, "Error copying a metatable");
1831 }
1832 }
1833
1834 // Not a deep or clonable full userdata
1835 if( U->demoteFullUserdata) // attempt demotion to light userdata
1836 {
1837 void* lud = lua_touserdata( L, i);
1838 lua_pushlightuserdata( L2, lud);
1839 }
1840 else // raise an error
1841 {
1842 (void) luaL_error( L, "can't copy non-deep full userdata across lanes");
1843 }
1844 STACK_END( L2, 1);
1845 STACK_END( L, 0);
1846 return TRUE;
1847}
1848
1849static bool_t inter_copy_function( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1850{
1851 if( vt == VT_KEY)
1852 {
1853 return FALSE;
1854 }
1855
1856 STACK_CHECK( L, 0);
1857 STACK_CHECK( L2, 0);
1858 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_));
1859
1860 if( lua_tocfunction( L, i) == userdata_clone_sentinel) // we are actually copying a clonable full userdata
1861 {
1862 // clone the full userdata again
1863 size_t userdata_size = 0;
1864 void* source;
1865 void* clone;
1866 // this function has 2 upvalues: the fqn of its metatable, and the userdata itself
1867 lua_getupvalue( L, i, 2); // ... u
1868 source = lua_touserdata( L, -1);
1869 lookup_table( L2, L, i, mode_, upName_); // ... u // ... mt
1870 // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with
1871 lua_getfield( L2, -1, "__lanesclone"); // ... mt __lanesclone
1872 lua_pushvalue( L2, -1); // ... mt __lanesclone __lanesclone
1873 // call the cloning function with 0 arguments, should return the number of bytes to allocate for the clone
1874 lua_call( L2, 0, 1); // ... mt __lanesclone size
1875 userdata_size = (size_t) lua_tointeger( L2, -1); // ... mt __lanesclone size
1876 lua_pop( L2, 1); // ... mt __lanesclone
1877 lua_pushnil( L2); // ... mt __lanesclone nil
1878 {
1879 int const clone_i = lua_gettop( L2);
1880 int uvi = 0;
1881 while( lua_getiuservalue( L, i, uvi + 1) != LUA_TNONE) // ... u uv
1882 {
1883 luaG_inter_move( U, L, L2, 1, mode_); // ... u // ... mt __lanesclone nil [uv]+
1884 ++ uvi;
1885 }
1886 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1887 lua_pop( L, 1); // ... u
1888 // create the clone userdata with the required number of uservalue slots
1889 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt __lanesclone nil [uv]+ u
1890 lua_replace( L2, clone_i); // ... mt __lanesclone u [uv]+
1891 // assign uservalues
1892 while( uvi > 0)
1893 {
1894 // this pops the value from the stack
1895 lua_setiuservalue( L2, clone_i, uvi); // ... mt __lanesclone u [uv]+
1896 -- uvi;
1897 }
1898 // when we are done, all uservalues are popped from the stack
1899 STACK_MID( L2, 3); // ... mt __lanesclone u
1900 }
1901 STACK_MID( L, 1); // u
1902 lua_insert( L2, -3); // ... u mt __lanesclone
1903 lua_pushlightuserdata( L2, clone); // ... u mt __lanesclone clone
1904 lua_pushlightuserdata( L2, source); // ... u mt __lanesclone clone source
1905 lua_call( L2, 2, 0); // ... u mt
1906 lua_setmetatable( L2, -2); // ... u
1907 lua_pop( L, 1); // ...
1908 }
1909 else
1910 {
1911 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_));
1912 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1913 STACK_CHECK( L2, 0);
1914 copy_cached_func( U, L2, L2_cache_i, L, i, mode_, upName_);
1915 STACK_END( L2, 1);
1916 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1917 }
1918 STACK_END( L2, 1);
1919 STACK_END( L, 0);
1920 return TRUE;
1921}
1922
1923static bool_t inter_copy_table( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1924{
1925 if( vt == VT_KEY)
1926 {
1927 return FALSE;
1928 }
1929
1930 STACK_CHECK( L, 0);
1931 STACK_CHECK( L2, 0);
1932 DEBUGSPEW_CODE( fprintf( stderr, "TABLE %s\n", upName_));
1933
1934 /*
1935 * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?)
1936 * Note that this table CAN be a module table, but we just didn't register it, in which case we'll send it through the table cloning mechanism
1937 */
1938 if( lookup_table( L2, L, i, mode_, upName_))
1939 {
1940 ASSERT_L( lua_istable( L2, -1) || (lua_tocfunction( L2, -1) == table_lookup_sentinel)); // from lookup datables // can also be table_lookup_sentinel if this is a table we know
1941 return TRUE;
1942 }
1943
1944 /* Check if we've already copied the same table from 'L' (during this transmission), and
1945 * reuse the old copy. This allows table upvalues shared by multiple
1946 * local functions to point to the same table, also in the target.
1947 * Also, this takes care of cyclic tables and multiple references
1948 * to the same subtable.
1949 *
1950 * Note: Even metatables need to go through this test; to detect
1951 * loops such as those in required module tables (getmetatable(lanes).lanes == lanes)
1952 */
1953 if( push_cached_table( L2, L2_cache_i, L, i))
1954 {
1955 ASSERT_L( lua_istable( L2, -1)); // from cache
1956 return TRUE;
1957 }
1958 ASSERT_L( lua_istable( L2, -1));
1959
1960 STACK_GROW( L, 2);
1961 STACK_GROW( L2, 2);
1962
1963 lua_pushnil( L); // start iteration
1964 while( lua_next( L, i))
1965 {
1966 // need a function to prevent overflowing the stack with verboseErrors-induced alloca()
1967 inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_);
1968 lua_pop( L, 1); // pop value (next round)
1969 }
1970 STACK_MID( L, 0);
1971 STACK_MID( L2, 1);
1972
1973 // Metatables are expected to be immutable, and copied only once.
1974 if( push_cached_metatable( U, L2, L2_cache_i, L, i, mode_, upName_)) // ... t mt?
1975 {
1976 lua_setmetatable( L2, -2); // ... t
1977 }
1978 STACK_END( L2, 1);
1979 STACK_END( L, 0);
1980 return TRUE;
1981}
1982
1738/* 1983/*
1739* Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove 1984* Copies a value from 'L' state (at index 'i') to 'L2' state. Does not remove
1740* the original value. 1985* the original value.
@@ -1745,7 +1990,7 @@ static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache
1745* 1990*
1746* Returns TRUE if value was pushed, FALSE if its type is non-supported. 1991* Returns TRUE if value was pushed, FALSE if its type is non-supported.
1747*/ 1992*/
1748static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_) 1993static bool_t inter_copy_one( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, LookupMode mode_, char const* upName_)
1749{ 1994{
1750 bool_t ret = TRUE; 1995 bool_t ret = TRUE;
1751 int val_type = lua_type( L, i); 1996 int val_type = lua_type( L, i);
@@ -1753,7 +1998,7 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu
1753 STACK_CHECK( L, 0); // L // L2 1998 STACK_CHECK( L, 0); // L // L2
1754 STACK_CHECK( L2, 0); // L // L2 1999 STACK_CHECK( L2, 0); // L // L2
1755 2000
1756 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one_()\n" INDENT_END)); 2001 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END));
1757 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 2002 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1758 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[vt])); 2003 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%s %s: " INDENT_END, lua_type_names[val_type], vt_names[vt]));
1759 2004
@@ -1822,108 +2067,7 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu
1822 /* The following types are not allowed as table keys */ 2067 /* The following types are not allowed as table keys */
1823 2068
1824 case LUA_TUSERDATA: 2069 case LUA_TUSERDATA:
1825 if( vt == VT_KEY) 2070 ret = inter_copy_userdata( U, L2, L2_cache_i, L, i, vt, mode_, upName_);
1826 {
1827 ret = FALSE;
1828 break;
1829 }
1830 // Allow only deep userdata entities to be copied across
1831 DEBUGSPEW_CODE( fprintf( stderr, "USERDATA\n"));
1832 if( copydeep( U, L, L2, i, mode_))
1833 {
1834 break;
1835 }
1836 STACK_MID( L, 0);
1837
1838 if( lua_getmetatable( L, i)) // ... mt?
1839 {
1840 lua_getfield( L, -1, "__lanesclone"); // ... mt __lanesclone?
1841 if( lua_isnil( L, -1))
1842 {
1843 lua_pop( L, 2); // ...
1844 ret = FALSE;
1845 }
1846 else
1847 {
1848 size_t userdata_size = 0;
1849 void* const source = lua_touserdata( L, i);
1850 void* clone = NULL;
1851 lua_pushvalue( L, -1); // ... mt __lanesclone __lanesclone
1852 // call the cloning function with 0 arguments, should return the number of bytes to allocate for the clone
1853 lua_call( L, 0, 1); // ... mt __lanesclone size
1854 STACK_MID( L, 3);
1855 userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size
1856 lua_pop( L, 1); // ... mt __lanesclone
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
1883 // call cloning function in source state to perform the actual memory cloning
1884 lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone
1885 lua_pushlightuserdata( L, source); // ... mt __lanesclone source
1886 lua_call( L, 2, 0); // ... mt
1887 STACK_MID( L, 1);
1888 // copy the metatable in the target state
1889 if( inter_copy_one_( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_)) // ... u mt?
1890 {
1891 lua_pop( L, 1); // ...
1892 STACK_MID( L, 0);
1893 // when writing to a keeper state, we have here a sentinel function with the metatable's fqn as upvalue
1894 if( eLM_ToKeeper == mode_) // ... u sentinel
1895 {
1896 ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel);
1897 // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn
1898 lua_getupvalue( L2, -1, 1); // ... u sentinel fqn
1899 lua_remove( L2, -2); // ... u fqn
1900 lua_insert( L2, -2); // ... fqn u
1901 lua_pushcclosure( L2, userdata_clone_sentinel, 2); // ... userdata_clone_sentinel
1902 }
1903 else // from keeper or direct, we have the userdata and the metatable
1904 {
1905 ASSERT_L( lua_istable( L2, -1));
1906 lua_setmetatable( L2, -2); // ... u
1907 }
1908 }
1909 else
1910 {
1911 (void) luaL_error( L, "Error copying a metatable");
1912 }
1913 }
1914 break;
1915 }
1916
1917 // Not a deep or clonable full userdata
1918 if( U->demoteFullUserdata) // attempt demotion to light userdata
1919 {
1920 void* lud = lua_touserdata( L, i);
1921 lua_pushlightuserdata( L2, lud);
1922 }
1923 else // raise an error
1924 {
1925 (void) luaL_error( L, "can't copy non-deep full userdata across lanes");
1926 }
1927 break; 2071 break;
1928 2072
1929 case LUA_TNIL: 2073 case LUA_TNIL:
@@ -1936,130 +2080,11 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu
1936 break; 2080 break;
1937 2081
1938 case LUA_TFUNCTION: 2082 case LUA_TFUNCTION:
1939 if( vt == VT_KEY) 2083 ret = inter_copy_function( U, L2, L2_cache_i, L, i, vt, mode_, upName_);
1940 {
1941 ret = FALSE;
1942 break;
1943 }
1944
1945 if( lua_tocfunction( L, i) == userdata_clone_sentinel) // we are actually copying a clonable full userdata
1946 {
1947 // clone the full userdata again
1948 size_t userdata_size = 0;
1949 void* source;
1950 void* clone;
1951 // this function has 2 upvalues: the fqn of its metatable, and the userdata itself
1952 lua_getupvalue( L, i, 2); // ... u
1953 source = lua_touserdata( L, -1);
1954 lookup_table( L2, L, i, mode_, upName_); // ... u // ... mt
1955 // __lanesclone should always exist because we woudln't be restoring data from a userdata_clone_sentinel closure to begin with
1956 lua_getfield( L2, -1, "__lanesclone"); // ... mt __lanesclone
1957 lua_pushvalue( L2, -1); // ... mt __lanesclone __lanesclone
1958 // call the cloning function with 0 arguments, should return the number of bytes to allocate for the clone
1959 lua_call( L2, 0, 1); // ... mt __lanesclone size
1960 userdata_size = (size_t) lua_tointeger( L2, -1); // ... mt __lanesclone size
1961 lua_pop( L2, 1); // ... mt __lanesclone
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
1987 lua_insert( L2, -3); // ... u mt __lanesclone
1988 lua_pushlightuserdata( L2, clone); // ... u mt __lanesclone clone
1989 lua_pushlightuserdata( L2, source); // ... u mt __lanesclone clone source
1990 lua_call( L2, 2, 0); // ... u mt
1991 lua_setmetatable( L2, -2); // ... u
1992 lua_pop( L, 1); // ...
1993 }
1994 else
1995 {
1996 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_));
1997 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1998 STACK_CHECK( L2, 0);
1999 push_cached_func( U, L2, L2_cache_i, L, i, mode_, upName_);
2000 STACK_END( L2, 1);
2001 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
2002 }
2003 break; 2084 break;
2004 2085
2005 case LUA_TTABLE: 2086 case LUA_TTABLE:
2006 if( vt == VT_KEY) 2087 ret = inter_copy_table( U, L2, L2_cache_i, L, i, vt, mode_, upName_);
2007 {
2008 ret = FALSE;
2009 break;
2010 }
2011 {
2012 STACK_CHECK( L, 0);
2013 STACK_CHECK( L2, 0);
2014 DEBUGSPEW_CODE( fprintf( stderr, "TABLE %s\n", upName_));
2015
2016 /*
2017 * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?)
2018 * Note that this table CAN be a module table, but we just didn't register it, in which case we'll send it through the table cloning mechanism
2019 */
2020 if( lookup_table( L2, L, i, mode_, upName_))
2021 {
2022 ASSERT_L( lua_istable( L2, -1) || (lua_tocfunction( L2, -1) == table_lookup_sentinel)); // from lookup datables // can also be table_lookup_sentinel if this is a table we know
2023 break;
2024 }
2025
2026 /* Check if we've already copied the same table from 'L' (during this transmission), and
2027 * reuse the old copy. This allows table upvalues shared by multiple
2028 * local functions to point to the same table, also in the target.
2029 * Also, this takes care of cyclic tables and multiple references
2030 * to the same subtable.
2031 *
2032 * Note: Even metatables need to go through this test; to detect
2033 * loops such as those in required module tables (getmetatable(lanes).lanes == lanes)
2034 */
2035 if( push_cached_table( L2, L2_cache_i, L, i))
2036 {
2037 ASSERT_L( lua_istable( L2, -1)); // from cache
2038 break;
2039 }
2040 ASSERT_L( lua_istable( L2, -1));
2041
2042 STACK_GROW( L, 2);
2043 STACK_GROW( L2, 2);
2044
2045 lua_pushnil( L); // start iteration
2046 while( lua_next( L, i))
2047 {
2048 // need a function to prevent overflowing the stack with verboseErrors-induced alloca()
2049 inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_);
2050 lua_pop( L, 1); // pop value (next round)
2051 }
2052 STACK_MID( L, 0);
2053 STACK_MID( L2, 1);
2054
2055 // Metatables are expected to be immutable, and copied only once.
2056 if( push_cached_metatable( U, L2, L2_cache_i, L, i, mode_, upName_)) // ... t mt?
2057 {
2058 lua_setmetatable( L2, -2); // ... t
2059 }
2060 STACK_END( L2, 1);
2061 STACK_END( L, 0);
2062 }
2063 break; 2088 break;
2064 2089
2065 /* The following types cannot be copied */ 2090 /* The following types cannot be copied */
@@ -2119,7 +2144,7 @@ int luaG_inter_copy( Universe* U, lua_State* L, lua_State* L2, uint_t n, LookupM
2119 { 2144 {
2120 sprintf( tmpBuf, "arg_%d", j); 2145 sprintf( tmpBuf, "arg_%d", j);
2121 } 2146 }
2122 copyok = inter_copy_one_( U, L2, top_L2 + 1, L, i, VT_NORMAL, mode_, pBuf); 2147 copyok = inter_copy_one( U, L2, top_L2 + 1, L, i, VT_NORMAL, mode_, pBuf);
2123 if( !copyok) 2148 if( !copyok)
2124 { 2149 {
2125 break; 2150 break;