diff options
| author | Benoit Germain <bnt.germain@gmail.com> | 2022-02-08 10:39:48 +0100 |
|---|---|---|
| committer | Benoit Germain <bnt.germain@gmail.com> | 2022-02-08 10:39:48 +0100 |
| commit | 2c0000d5169cacf950d06637ada1a371cf382896 (patch) | |
| tree | edfe62d964b98cc745d867f09feac2df2eab758f /src | |
| parent | 54152c35e76acd1f21b477caf0a4403128032039 (diff) | |
| download | lanes-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.h | 4 | ||||
| -rw-r--r-- | src/tools.c | 220 |
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 | */ |
| 1480 | static DECLARE_CONST_UNIQUE_KEY( CLONABLES_CACHE_KEY, 0xD04EE018B3DEE8F5); | 1480 | static DECLARE_CONST_UNIQUE_KEY( CLONABLES_CACHE_KEY, 0xD04EE018B3DEE8F5); |
| 1481 | 1481 | ||
| 1482 | static bool_t copyclone( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, LookupMode mode_, char const* upName_) | 1482 | static 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 | ||
| 1652 | static 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_) | 1643 | static 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 | } |
