aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenoit Germain <bnt.germain@gmail.com>2022-02-08 10:39:48 +0100
committerBenoit Germain <bnt.germain@gmail.com>2022-02-08 10:39:48 +0100
commit2c0000d5169cacf950d06637ada1a371cf382896 (patch)
treeedfe62d964b98cc745d867f09feac2df2eab758f /src
parent54152c35e76acd1f21b477caf0a4403128032039 (diff)
downloadlanes-2c0000d5169cacf950d06637ada1a371cf382896.tar.gz
lanes-2c0000d5169cacf950d06637ada1a371cf382896.tar.bz2
lanes-2c0000d5169cacf950d06637ada1a371cf382896.zip
__lanesclone is now called only once with 3 parameters dest, source, size -> BREAKS CUSTOM DEEP USERDATA API
Diffstat (limited to 'src')
-rw-r--r--src/lanes.h4
-rw-r--r--src/tools.c220
2 files changed, 106 insertions, 118 deletions
diff --git a/src/lanes.h b/src/lanes.h
index 4c7cc5b..20524e6 100644
--- a/src/lanes.h
+++ b/src/lanes.h
@@ -11,8 +11,8 @@
11#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC) 11#endif // (defined PLATFORM_WIN32) || (defined PLATFORM_POCKETPC)
12 12
13#define LANES_VERSION_MAJOR 3 13#define LANES_VERSION_MAJOR 3
14#define LANES_VERSION_MINOR 15 14#define LANES_VERSION_MINOR 16
15#define LANES_VERSION_PATCH 2 15#define LANES_VERSION_PATCH 0
16 16
17#define LANES_MIN_VERSION_REQUIRED(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR>MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR>MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH>=PATCH)))) 17#define LANES_MIN_VERSION_REQUIRED(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR>MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR>MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH>=PATCH))))
18#define LANES_VERSION_LESS_THAN(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR<MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR<MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH<PATCH)))) 18#define LANES_VERSION_LESS_THAN(MAJOR, MINOR, PATCH) ((LANES_VERSION_MAJOR<MAJOR) || (LANES_VERSION_MAJOR==MAJOR && (LANES_VERSION_MINOR<MINOR || (LANES_VERSION_MINOR==MINOR && LANES_VERSION_PATCH<PATCH))))
diff --git a/src/tools.c b/src/tools.c
index e72d441..a297913 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -1479,16 +1479,17 @@ static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache
1479*/ 1479*/
1480static DECLARE_CONST_UNIQUE_KEY( CLONABLES_CACHE_KEY, 0xD04EE018B3DEE8F5); 1480static DECLARE_CONST_UNIQUE_KEY( CLONABLES_CACHE_KEY, 0xD04EE018B3DEE8F5);
1481 1481
1482static bool_t copyclone( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) 1482static bool_t copyclone( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t source_i_, LookupMode mode_, char const* upName_)
1483{ 1483{
1484 void* const source = lua_touserdata( L, i); 1484 void* const source = lua_touserdata( L, source_i_);
1485 source_i_ = lua_absindex( L, source_i_);
1485 1486
1486 STACK_CHECK( L, 0); 1487 STACK_CHECK( L, 0); // L (source) // L2 (destination)
1487 STACK_CHECK( L2, 0); 1488 STACK_CHECK( L2, 0);
1488 1489
1489 // Check if the source was already cloned during this copy 1490 // Check if the source was already cloned during this copy
1490 lua_pushlightuserdata( L2, source); // ... source 1491 lua_pushlightuserdata( L2, source); // ... source
1491 lua_rawget( L2, L2_cache_i); // ... clone? 1492 lua_rawget( L2, L2_cache_i); // ... clone?
1492 if ( !lua_isnil( L2, -1)) 1493 if ( !lua_isnil( L2, -1))
1493 { 1494 {
1494 STACK_MID( L2, 1); 1495 STACK_MID( L2, 1);
@@ -1496,107 +1497,97 @@ static bool_t copyclone( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_Stat
1496 } 1497 }
1497 else 1498 else
1498 { 1499 {
1499 lua_pop( L2, 1); // ... 1500 lua_pop( L2, 1); // ...
1500 } 1501 }
1501 STACK_MID( L2, 0); 1502 STACK_MID( L2, 0);
1502 1503
1503 // no metatable? -> not clonable 1504 // no metatable? -> not clonable
1504 if( !lua_getmetatable( L, i)) // ... mt? 1505 if( !lua_getmetatable( L, source_i_)) // ... mt?
1505 { 1506 {
1506 STACK_MID( L, 0); 1507 STACK_MID( L, 0);
1507 return FALSE; 1508 return FALSE;
1508 } 1509 }
1509 1510
1510 // no __lanesclone? -> not clonable 1511 // no __lanesclone? -> not clonable
1511 lua_getfield( L, -1, "__lanesclone"); // ... mt __lanesclone? 1512 lua_getfield( L, -1, "__lanesclone"); // ... mt __lanesclone?
1512 if( lua_isnil( L, -1)) 1513 if( lua_isnil( L, -1))
1513 { 1514 {
1514 lua_pop( L, 2); // ... 1515 lua_pop( L, 2); // ...
1515 STACK_MID( L, 0); 1516 STACK_MID( L, 0);
1516 return FALSE; 1517 return FALSE;
1517 } 1518 }
1518 1519
1520 // we need to copy over the uservalues of the userdata as well
1519 { 1521 {
1520 int const mt = lua_absindex( L, -2); 1522 int const mt = lua_absindex( L, -2); // ... mt __lanesclone
1521 size_t userdata_size = 0; 1523 size_t const userdata_size = (size_t) lua_rawlen( L, source_i_);
1522 void* clone = NULL; 1524 void* clone = NULL;
1523 lua_pushvalue( L, -1); // ... mt __lanesclone __lanesclone 1525 // extract all the uservalues, but don't transfer them yet
1524 // call the cloning function with 1 argument, should return the number of bytes to allocate for the clone 1526 int uvi = 0;
1525 lua_pushlightuserdata( L, source); // ... mt __lanesclone __lanesclone source 1527 while( lua_getiuservalue( L, source_i_, ++ uvi) != LUA_TNONE) {} // ... mt __lanesclone [uv]+ nil
1526 lua_call( L, 1, 1); // ... mt __lanesclone size 1528 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1527 STACK_MID( L, 3); 1529 lua_pop( L, 1); // ... mt __lanesclone [uv]+
1528 userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size 1530 -- uvi;
1529 lua_pop( L, 1); // ... mt __lanesclone 1531 // create the clone userdata with the required number of uservalue slots
1530 // we need to copy over the uservalues of the userdata as well 1532 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... u
1533 // copy the metatable in the target state, and give it to the clone we put there
1534 if( inter_copy_one( U, L2, L2_cache_i, L, mt, VT_NORMAL, mode_, upName_)) // ... u mt|sentinel
1531 { 1535 {
1532 // extract all the uservalues, but don't transfer them yet 1536 if( eLM_ToKeeper == mode_) // ... u sentinel
1533 int uvi = 0;
1534 while( lua_getiuservalue( L, i, uvi + 1) != LUA_TNONE) // ... mt __lanesclone [uv]+ nil
1535 { 1537 {
1536 ++ uvi; 1538 ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel);
1539 // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn
1540 lua_getupvalue( L2, -1, 1); // ... u sentinel fqn
1541 lua_remove( L2, -2); // ... u fqn
1542 lua_insert( L2, -2); // ... fqn u
1543 lua_pushcclosure( L2, userdata_clone_sentinel, 2); // ... userdata_clone_sentinel
1537 } 1544 }
1538 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now 1545 else // from keeper or direct // ... u mt
1539 lua_pop( L, 1); // ... mt __lanesclone [uv]+
1540 // create the clone userdata with the required number of uservalue slots
1541 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... u
1542 // copy the metatable in the target state, and give it to the clone we put there
1543 if( inter_copy_one( U, L2, L2_cache_i, L, mt, VT_NORMAL, mode_, upName_)) // ... u mt|sentinel
1544 { 1546 {
1545 if( eLM_ToKeeper == mode_) // ... u sentinel 1547 ASSERT_L( lua_istable( L2, -1));
1546 { 1548 lua_setmetatable( L2, -2); // ... u
1547 ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel);
1548 // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn
1549 lua_getupvalue( L2, -1, 1); // ... u sentinel fqn
1550 lua_remove( L2, -2); // ... u fqn
1551 lua_insert( L2, -2); // ... fqn u
1552 lua_pushcclosure( L2, userdata_clone_sentinel, 2); // ... userdata_clone_sentinel
1553 }
1554 else // from keeper or direct // ... u mt
1555 {
1556 ASSERT_L( lua_istable( L2, -1));
1557 lua_setmetatable( L2, -2); // ... u
1558 }
1559 STACK_MID( L2, 1);
1560 }
1561 else
1562 {
1563 (void) luaL_error( L, "Error copying a metatable");
1564 }
1565 // first, add the entry in the cache (at this point it is either the actual userdata or the keeper sentinel
1566 lua_pushlightuserdata( L2, source); // ... u source
1567 lua_pushvalue( L2, -2); // ... u source u
1568 lua_rawset( L2, L2_cache_i); // ... u
1569 // make sure we have the userdata now
1570 if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel
1571 {
1572 lua_getupvalue( L2, -1, 2); // ... userdata_clone_sentinel u
1573 }
1574 // assign uservalues
1575 while( uvi > 0)
1576 {
1577 inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // ... u uv
1578 lua_pop( L, 1); // ... mt __lanesclone [uv]*
1579 // this pops the value from the stack
1580 lua_setiuservalue( L2, -2, uvi); // ... u
1581 -- uvi;
1582 }
1583 // when we are done, all uservalues are popped from the source stack, and we want only the single transferred value in the destination
1584 if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel u
1585 {
1586 lua_pop( L2, 1); // ... userdata_clone_sentinel
1587 } 1549 }
1588 STACK_MID( L2, 1); 1550 STACK_MID( L2, 1);
1589 STACK_MID( L, 2);
1590 // call cloning function in source state to perform the actual memory cloning
1591 lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone
1592 lua_pushlightuserdata( L, source); // ... mt __lanesclone clone source
1593 lua_call( L, 2, 0); // ... mt
1594 STACK_MID( L, 1);
1595 } 1551 }
1552 else
1553 {
1554 (void) luaL_error( L, "Error copying a metatable");
1555 }
1556 // first, add the entry in the cache (at this point it is either the actual userdata or the keeper sentinel
1557 lua_pushlightuserdata( L2, source); // ... u source
1558 lua_pushvalue( L2, -2); // ... u source u
1559 lua_rawset( L2, L2_cache_i); // ... u
1560 // make sure we have the userdata now
1561 if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel
1562 {
1563 lua_getupvalue( L2, -1, 2); // ... userdata_clone_sentinel u
1564 }
1565 // assign uservalues
1566 while( uvi > 0)
1567 {
1568 inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // ... u uv
1569 lua_pop( L, 1); // ... mt __lanesclone [uv]*
1570 // this pops the value from the stack
1571 lua_setiuservalue( L2, -2, uvi); // ... u
1572 -- uvi;
1573 }
1574 // when we are done, all uservalues are popped from the source stack, and we want only the single transferred value in the destination
1575 if( eLM_ToKeeper == mode_) // ... userdata_clone_sentinel u
1576 {
1577 lua_pop( L2, 1); // ... userdata_clone_sentinel
1578 }
1579 STACK_MID( L2, 1);
1580 STACK_MID( L, 2);
1581 // call cloning function in source state to perform the actual memory cloning
1582 lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone
1583 lua_pushlightuserdata( L, source); // ... mt __lanesclone clone source
1584 lua_pushinteger( L, userdata_size); // ... mt __lanesclone clone source size
1585 lua_call( L, 3, 0); // ... mt
1586 STACK_MID( L, 1);
1596 } 1587 }
1597 1588
1598 STACK_END( L2, 1); 1589 STACK_END( L2, 1);
1599 lua_pop( L, 1); // ... 1590 lua_pop( L, 1); // ...
1600 STACK_END( L, 0); 1591 STACK_END( L, 0);
1601 return TRUE; 1592 return TRUE;
1602} 1593}
@@ -1649,18 +1640,18 @@ static bool_t inter_copy_userdata( Universe* U, lua_State* L2, uint_t L2_cache_i
1649 return TRUE; 1640 return TRUE;
1650} 1641}
1651 1642
1652static 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_) 1643static bool_t inter_copy_function( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t source_i_, enum e_vt vt, LookupMode mode_, char const* upName_)
1653{ 1644{
1654 if( vt == VT_KEY) 1645 if( vt == VT_KEY)
1655 { 1646 {
1656 return FALSE; 1647 return FALSE;
1657 } 1648 }
1658 1649
1659 STACK_CHECK( L, 0); 1650 STACK_CHECK( L, 0); // L (source) // L2 (destination)
1660 STACK_CHECK( L2, 0); 1651 STACK_CHECK( L2, 0);
1661 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); 1652 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_));
1662 1653
1663 if( lua_tocfunction( L, i) == userdata_clone_sentinel) // we are actually copying a clonable full userdata from a keeper 1654 if( lua_tocfunction( L, source_i_) == userdata_clone_sentinel) // we are actually copying a clonable full userdata from a keeper
1664 { 1655 {
1665 // clone the full userdata again 1656 // clone the full userdata again
1666 size_t userdata_size = 0; 1657 size_t userdata_size = 0;
@@ -1668,10 +1659,10 @@ static bool_t inter_copy_function( Universe* U, lua_State* L2, uint_t L2_cache_i
1668 void* clone; 1659 void* clone;
1669 1660
1670 // let's see if we already restored this userdata 1661 // let's see if we already restored this userdata
1671 lua_getupvalue( L, i, 2); // ... u 1662 lua_getupvalue( L, source_i_, 2); // ... u
1672 source = lua_touserdata( L, -1); 1663 source = lua_touserdata( L, -1);
1673 lua_pushlightuserdata( L2, source); // ... source 1664 lua_pushlightuserdata( L2, source); // ... source
1674 lua_rawget( L2, L2_cache_i); // ... u? 1665 lua_rawget( L2, L2_cache_i); // ... u?
1675 if( !lua_isnil( L2, -1)) 1666 if( !lua_isnil( L2, -1))
1676 { 1667 {
1677 lua_pop( L, 1); // ... 1668 lua_pop( L, 1); // ...
@@ -1679,66 +1670,63 @@ static bool_t inter_copy_function( Universe* U, lua_State* L2, uint_t L2_cache_i
1679 STACK_MID( L2, 1); 1670 STACK_MID( L2, 1);
1680 return TRUE; 1671 return TRUE;
1681 } 1672 }
1682 lua_pop( L2, 1); // ... 1673 lua_pop( L2, 1); // ...
1683 1674
1684 // this function has 2 upvalues: the fqn of its metatable, and the userdata itself 1675 // this function has 2 upvalues: the fqn of its metatable, and the userdata itself
1685 lookup_table( L2, L, i, mode_, upName_); // ... mt 1676 lookup_table( L2, L, source_i_, mode_, upName_); // ... mt
1686 // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with 1677 // originally 'i' slot was the proxy closure, but from now on it indexes the actual userdata we extracted from it
1687 lua_getfield( L2, -1, "__lanesclone"); // ... mt __lanesclone 1678 source_i_ = lua_gettop( L);
1688 lua_pushvalue( L2, -1); // ... mt __lanesclone __lanesclone
1689 // 'i' slot is the closure, but from now on it is the actual userdata
1690 i = lua_gettop( L);
1691 source = lua_touserdata( L, -1); 1679 source = lua_touserdata( L, -1);
1692 // call the cloning function with 1 argument, should return the number of bytes to allocate for the clone 1680 // call the cloning function with 1 argument, should return the number of bytes to allocate for the clone
1693 lua_pushlightuserdata( L2, source); // ... mt __lanesclone __lanesclone source 1681 userdata_size = (size_t) lua_rawlen( L, -1);
1694 lua_call( L2, 1, 1); // ... mt __lanesclone size
1695 userdata_size = (size_t) lua_tointeger( L2, -1); // ... mt __lanesclone size
1696 lua_pop( L2, 1); // ... mt __lanesclone
1697 { 1682 {
1698 // extract uservalues (don't transfer them yet) 1683 // extract uservalues (don't transfer them yet)
1699 int uvi = 0; 1684 int uvi = 0;
1700 while( lua_getiuservalue( L, i, uvi + 1) != LUA_TNONE) // ... u uv 1685 while( lua_getiuservalue( L, source_i_, ++ uvi) != LUA_TNONE) {} // ... u uv
1701 {
1702 ++ uvi;
1703 }
1704 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now 1686 // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now
1705 lua_pop( L, 1); // ... u [uv]* 1687 lua_pop( L, 1); // ... u [uv]*
1688 -- uvi;
1706 STACK_MID( L, uvi + 1); 1689 STACK_MID( L, uvi + 1);
1707 // create the clone userdata with the required number of uservalue slots 1690 // create the clone userdata with the required number of uservalue slots
1708 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt __lanesclone u 1691 clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt u
1709 // add it in the cache 1692 // add it in the cache
1710 lua_pushlightuserdata( L2, source); // ... mt __lanesclone u source 1693 lua_pushlightuserdata( L2, source); // ... mt u source
1711 lua_pushvalue( L2, -2); // ... mt __lanesclone u source u 1694 lua_pushvalue( L2, -2); // ... mt u source u
1712 lua_rawset( L2, L2_cache_i); // ... mt __lanesclone u 1695 lua_rawset( L2, L2_cache_i); // ... mt u
1713 // set metatable 1696 // set metatable
1714 lua_pushvalue( L2, -3); // ... mt __lanesclone u mt 1697 lua_pushvalue( L2, -2); // ... mt u mt
1715 lua_setmetatable( L2, -2); // ... mt __lanesclone u 1698 lua_setmetatable( L2, -2); // ... mt u
1716 // transfer and assign uservalues 1699 // transfer and assign uservalues
1717 while( uvi > 0) 1700 while( uvi > 0)
1718 { 1701 {
1719 inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), vt, mode_, upName_); // ... mt __lanesclone u uv 1702 inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), vt, mode_, upName_); // ... mt u uv
1720 lua_pop( L, 1); // ... u [uv]* 1703 lua_pop( L, 1); // ... u [uv]*
1721 // this pops the value from the stack 1704 // this pops the value from the stack
1722 lua_setiuservalue( L2, -2, uvi); // ... mt __lanesclone u 1705 lua_setiuservalue( L2, -2, uvi); // ... mt u
1723 -- uvi; 1706 -- uvi;
1724 } 1707 }
1725 // when we are done, all uservalues are popped from the stack 1708 // when we are done, all uservalues are popped from the stack, we can pop the source as well
1726 lua_pop( L, 1); // ... 1709 lua_pop( L, 1); // ...
1727 STACK_MID( L, 0); 1710 STACK_MID( L, 0);
1728 STACK_MID( L2, 3); // ... mt __lanesclone u 1711 STACK_MID( L2, 2); // ... mt u
1729 } 1712 }
1730 // perform the custom cloning part 1713 // perform the custom cloning part
1731 lua_replace( L2, -3); // ... u __lanesclone 1714 lua_insert( L2, -2); // ... u mt
1732 lua_pushlightuserdata( L2, clone); // ... u __lanesclone clone 1715 // __lanesclone should always exist because we wouldn't be restoring data from a userdata_clone_sentinel closure to begin with
1733 lua_pushlightuserdata( L2, source); // ... u __lanesclone clone source 1716 lua_getfield(L2, -2, "__lanesclone"); // ... u mt __lanesclone
1734 lua_call( L2, 2, 0); // ... u 1717 lua_remove( L2, -2); // ... u __lanesclone
1718 lua_pushlightuserdata( L2, clone); // ... u __lanesclone clone
1719 lua_pushlightuserdata( L2, source); // ... u __lanesclone clone source
1720 lua_pushinteger( L2, userdata_size); // ... u __lanesclone clone source size
1721 // clone:__lanesclone(source, size)
1722 lua_call( L2, 3, 0); // ... u
1735 } 1723 }
1736 else 1724 else // regular function
1737 { 1725 {
1738 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); 1726 DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_));
1739 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); 1727 DEBUGSPEW_CODE( ++ U->debugspew_indent_depth);
1740 STACK_CHECK( L2, 0); 1728 STACK_CHECK( L2, 0);
1741 copy_cached_func( U, L2, L2_cache_i, L, i, mode_, upName_); 1729 copy_cached_func( U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f
1742 STACK_END( L2, 1); 1730 STACK_END( L2, 1);
1743 DEBUGSPEW_CODE( -- U->debugspew_indent_depth); 1731 DEBUGSPEW_CODE( -- U->debugspew_indent_depth);
1744 } 1732 }