diff options
author | Benoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m> | 2018-11-07 19:16:36 +0100 |
---|---|---|
committer | Benoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m> | 2018-11-07 19:16:36 +0100 |
commit | a142eb1e1ee81919d10b55bb7fa2e33636098d85 (patch) | |
tree | 21ef5c830ce4b4e845454af4274beabd073cc720 /src | |
parent | 91155c74fc10fa98ad6257d5309bfd13d4a61cf0 (diff) | |
download | lanes-a142eb1e1ee81919d10b55bb7fa2e33636098d85.tar.gz lanes-a142eb1e1ee81919d10b55bb7fa2e33636098d85.tar.bz2 lanes-a142eb1e1ee81919d10b55bb7fa2e33636098d85.zip |
__lanesclone mechanism should actually work now
Diffstat (limited to 'src')
-rw-r--r-- | src/lanes.c | 1 | ||||
-rw-r--r-- | src/tools.c | 89 |
2 files changed, 74 insertions, 16 deletions
diff --git a/src/lanes.c b/src/lanes.c index d4b4c73..c3e64fb 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
@@ -2289,6 +2289,7 @@ LUAG_FUNC( lane_new) | |||
2289 | // require the module in the target state, and populate the lookup table there too | 2289 | // require the module in the target state, and populate the lookup table there too |
2290 | size_t len; | 2290 | size_t len; |
2291 | char const* name = lua_tolstring( L, -1, &len); | 2291 | char const* name = lua_tolstring( L, -1, &len); |
2292 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: require '%s'\n" INDENT_END, name)); | ||
2292 | 2293 | ||
2293 | // require the module in the target lane | 2294 | // require the module in the target lane |
2294 | lua_getglobal( L2, "require"); // require()? | 2295 | lua_getglobal( L2, "require"); // require()? |
diff --git a/src/tools.c b/src/tools.c index 2f9de7b..8e886b5 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -825,6 +825,12 @@ static int table_lookup_sentinel( lua_State* L) | |||
825 | return luaL_error( L, "table lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); | 825 | return luaL_error( L, "table lookup sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); |
826 | } | 826 | } |
827 | 827 | ||
828 | // function sentinel used to transfer cloned full userdata from/to keeper states | ||
829 | static int userdata_clone_sentinel( lua_State* L) | ||
830 | { | ||
831 | return luaL_error( L, "userdata clone sentinel for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1))); | ||
832 | } | ||
833 | |||
828 | /* | 834 | /* |
829 | * retrieve the name of a function/table in the lookup database | 835 | * retrieve the name of a function/table in the lookup database |
830 | */ | 836 | */ |
@@ -838,7 +844,7 @@ static char const* find_lookup_name( lua_State* L, uint_t i, LookupMode mode_, c | |||
838 | if( mode_ == eLM_FromKeeper) | 844 | if( mode_ == eLM_FromKeeper) |
839 | { | 845 | { |
840 | lua_CFunction f = lua_tocfunction( L, i); // should *always* be func_lookup_sentinel or table_lookup_sentinel! | 846 | lua_CFunction f = lua_tocfunction( L, i); // should *always* be func_lookup_sentinel or table_lookup_sentinel! |
841 | if( f == func_lookup_sentinel || f == table_lookup_sentinel) | 847 | if( f == func_lookup_sentinel || f == table_lookup_sentinel || f == userdata_clone_sentinel) |
842 | { | 848 | { |
843 | lua_getupvalue( L, i, 1); // ... v ... "f.q.n" | 849 | lua_getupvalue( L, i, 1); // ... v ... "f.q.n" |
844 | } | 850 | } |
@@ -1594,6 +1600,7 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu | |||
1594 | bool_t ignore = FALSE; | 1600 | bool_t ignore = FALSE; |
1595 | int val_type = lua_type( L, i); | 1601 | int val_type = lua_type( L, i); |
1596 | STACK_GROW( L2, 1); | 1602 | STACK_GROW( L2, 1); |
1603 | STACK_CHECK( L); // L // L2 | ||
1597 | STACK_CHECK( L2); // L // L2 | 1604 | STACK_CHECK( L2); // L // L2 |
1598 | 1605 | ||
1599 | /* Skip the object if it has metatable with { __lanesignore = true } */ | 1606 | /* Skip the object if it has metatable with { __lanesignore = true } */ |
@@ -1662,30 +1669,53 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu | |||
1662 | { | 1669 | { |
1663 | break; | 1670 | break; |
1664 | } | 1671 | } |
1672 | STACK_MID( L, 0); | ||
1665 | 1673 | ||
1666 | if( lua_getmetatable( L, i)) // ... mt? | 1674 | if( lua_getmetatable( L, i)) // ... mt? |
1667 | { | 1675 | { |
1668 | lua_getfield( L, -1, "__lanesclone"); // ... mt clone? | 1676 | lua_getfield( L, -1, "__lanesclone"); // ... mt __lanesclone? |
1669 | if( !lua_isnil( L, -1)) | 1677 | if( lua_isnil( L, -1)) |
1678 | { | ||
1679 | lua_pop( L, 2); // ... | ||
1680 | } | ||
1681 | else | ||
1670 | { | 1682 | { |
1683 | FuncSubType fst; | ||
1684 | lua_CFunction cloneFunc = luaG_tocfunction( L, -1, &fst); | ||
1685 | size_t userdata_size = 0; | ||
1671 | void* const source = lua_touserdata( L, i); | 1686 | void* const source = lua_touserdata( L, i); |
1687 | void* clone = NULL; | ||
1688 | lua_pushvalue( L, -1); // ... mt __lanesclone __lanesclone | ||
1689 | // call the cloning function with 0 arguments, should return the number of bytes to allocate for the clone | ||
1690 | lua_call( L, 0, 1); // ... mt __lanesclone size | ||
1691 | STACK_MID( L, 3); | ||
1692 | userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size | ||
1693 | lua_pop( L, 1); // ... mt __lanesclone | ||
1694 | clone = lua_newuserdata( L2, userdata_size); // ... u | ||
1695 | // call cloning function in source state to perform the actual memory cloning | ||
1696 | lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone | ||
1697 | lua_pushlightuserdata( L, source); // ... mt __lanesclone source | ||
1698 | lua_call( L, 2, 0); // ... mt | ||
1699 | STACK_MID( L, 1); | ||
1672 | // copy the metatable in the target state | 1700 | // copy the metatable in the target state |
1673 | if( push_cached_metatable( U, L2, L2_cache_i, L, i, mode_, upName_)) // ... mt? | 1701 | if( inter_copy_one_( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_)) // ... u mt? |
1674 | { | 1702 | { |
1675 | // retrieve cloning function | 1703 | lua_pop( L, 1); // ... |
1676 | lua_getfield( L2, -1, "__lanesclone"); // ... mt clone | 1704 | STACK_MID( L, 0); |
1677 | lua_pushlightuserdata( L2, source); // ... mt clone p | 1705 | // when writing to a keeper state, we have here a sentinel function with the metatable's fqn as upvalue |
1678 | // cloning function should create a new full userdata without a metatable | 1706 | if( eLM_ToKeeper == mode_) // ... u sentinel |
1679 | if( lua_pcall( L2, 1, 1, 0) == LUA_OK) // ... mt u | ||
1680 | { | 1707 | { |
1681 | lua_insert( L2, -2); // ... u mt | 1708 | ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel); |
1682 | lua_setmetatable( L2, -2); // ... u | 1709 | // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn |
1710 | lua_getupvalue( L2, -1, 1); // ... u sentinel fqn | ||
1711 | lua_remove( L2, -2); // ... u fqn | ||
1712 | lua_insert( L2, -2); // ... fqn u | ||
1713 | lua_pushcclosure( L2, userdata_clone_sentinel, 2); // ... userdata_clone_sentinel | ||
1683 | } | 1714 | } |
1684 | else // ... mt err | 1715 | else // from keeper or direct, we have the userdata and the metatable |
1685 | { | 1716 | { |
1686 | // propagate any error to the source state | 1717 | ASSERT_L( lua_istable( L2, -1)); |
1687 | char const* errmsg = lua_tostring( L2, -1); | 1718 | lua_setmetatable( L2, -2); // ... u |
1688 | (void) luaL_error( L, "can't copy non-deep full userdata across lanes: %s", errmsg); | ||
1689 | } | 1719 | } |
1690 | } | 1720 | } |
1691 | else | 1721 | else |
@@ -1693,7 +1723,6 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu | |||
1693 | (void) luaL_error( L, "Error copying a metatable"); | 1723 | (void) luaL_error( L, "Error copying a metatable"); |
1694 | } | 1724 | } |
1695 | } | 1725 | } |
1696 | lua_pop( L, 2); // ... | ||
1697 | break; | 1726 | break; |
1698 | } | 1727 | } |
1699 | 1728 | ||
@@ -1724,6 +1753,33 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu | |||
1724 | ret = FALSE; | 1753 | ret = FALSE; |
1725 | break; | 1754 | break; |
1726 | } | 1755 | } |
1756 | |||
1757 | if( lua_tocfunction( L, i) == userdata_clone_sentinel) // we are actually copying a clonable full userdata | ||
1758 | { | ||
1759 | // clone the full userdata again | ||
1760 | size_t userdata_size = 0; | ||
1761 | void* source; | ||
1762 | void* clone; | ||
1763 | // this function has 2 upvalues: the fqn of its metatable, and the userdata itself | ||
1764 | lua_getupvalue( L, i, 2); // ... u | ||
1765 | source = lua_touserdata( L, -1); | ||
1766 | lookup_table( L2, L, i, mode_, upName_); // ... u // ... mt | ||
1767 | // __lanesclone should always exist because we woudln't be restoring data from a userdata_clone_sentinel closure to begin with | ||
1768 | lua_getfield( L2, -1, "__lanesclone"); // // ... mt __lanesclone | ||
1769 | lua_pushvalue( L2, -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( L2, 0, 1); // ... mt __lanesclone size | ||
1772 | userdata_size = (size_t) lua_tointeger( L2, -1); // ... mt __lanesclone size | ||
1773 | lua_pop( L2, 1); // ... mt __lanesclone | ||
1774 | clone = lua_newuserdata( L2, userdata_size); // ... mt __lanesclone u | ||
1775 | lua_insert( L2, -3); // ... u mt __lanesclone | ||
1776 | lua_pushlightuserdata( L2, clone); // ... u mt __lanesclone clone | ||
1777 | lua_pushlightuserdata( L2, source); // ... u mt __lanesclone clone source | ||
1778 | lua_call( L2, 2, 0); // ... u mt | ||
1779 | lua_setmetatable( L2, -2); // ... u | ||
1780 | lua_pop( L, 1); // ... | ||
1781 | } | ||
1782 | else | ||
1727 | { | 1783 | { |
1728 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "FUNCTION %s\n" INDENT_END, upName_)); | 1784 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "FUNCTION %s\n" INDENT_END, upName_)); |
1729 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1785 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
@@ -1802,6 +1858,7 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu | |||
1802 | } | 1858 | } |
1803 | 1859 | ||
1804 | STACK_END( L2, ret ? 1 : 0); | 1860 | STACK_END( L2, ret ? 1 : 0); |
1861 | STACK_END( L, 0); | ||
1805 | return ret; | 1862 | return ret; |
1806 | } | 1863 | } |
1807 | 1864 | ||