aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit 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
committerBenoit 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
commita142eb1e1ee81919d10b55bb7fa2e33636098d85 (patch)
tree21ef5c830ce4b4e845454af4274beabd073cc720 /src
parent91155c74fc10fa98ad6257d5309bfd13d4a61cf0 (diff)
downloadlanes-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.c1
-rw-r--r--src/tools.c89
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
829static 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