aboutsummaryrefslogtreecommitdiff
path: root/src/tools.c
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>2013-09-26 21:11:24 +0200
committerBenoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m>2013-09-26 21:11:24 +0200
commitf823c6887e28c815234f8b4bd355887b4f554857 (patch)
tree862b37cc93d6779c3c2577e78ed6ff5389412f90 /src/tools.c
parentc97ad8630ea9dcb92b4e9db16c4dbade1de18884 (diff)
downloadlanes-f823c6887e28c815234f8b4bd355887b4f554857.tar.gz
lanes-f823c6887e28c815234f8b4bd355887b4f554857.tar.bz2
lanes-f823c6887e28c815234f8b4bd355887b4f554857.zip
Reduce memory footprint, simplify module order setup in conjuction with Lanes, and send over native functions a bit faster as well
* Lanes no longer has to internally require modules inside the keeper states because they no longer need a lookup database. the lookup name is stored as-is and actually converted in the destination state * optimisation: bypass cache when sending native functions over * removed all the KEEPER_MODEL_LUA code, as it can no longer work anyway
Diffstat (limited to 'src/tools.c')
-rw-r--r--src/tools.c446
1 files changed, 230 insertions, 216 deletions
diff --git a/src/tools.c b/src/tools.c
index a3cc6b7..a957f41 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -515,8 +515,6 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* _name)
515* Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL. 515* Base ("unpack", "print" etc.) is always added, unless 'libs' is NULL.
516* 516*
517*/ 517*/
518extern void register_core_libfuncs_for_keeper( lua_State* L);
519
520lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs) 518lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char const* libs)
521{ 519{
522 // reuse alloc function from the originating state 520 // reuse alloc function from the originating state
@@ -534,6 +532,7 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
534 { 532 {
535 return L; 533 return L;
536 } 534 }
535 // if we are here, no keeper state is involved (because libs == NULL when we init keepers)
537 536
538 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END)); 537 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_newstate()\n" INDENT_END));
539 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 538 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
@@ -549,9 +548,8 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
549 if( libs) 548 if( libs)
550 { 549 {
551 // special "*" case (mainly to help with LuaJIT compatibility) 550 // special "*" case (mainly to help with LuaJIT compatibility)
552 // "K" is used when opening keeper states: almost the same as "*", but for the fact we don't open lanes.core
553 // as we are called from luaopen_lanes_core() already, and that would deadlock 551 // as we are called from luaopen_lanes_core() already, and that would deadlock
554 if( (libs[0] == '*' || libs[0] == 'K') && libs[1] == 0) 552 if( libs[0] == '*' && libs[1] == 0)
555 { 553 {
556 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); 554 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END));
557 luaL_openlibs( L); 555 luaL_openlibs( L);
@@ -560,12 +558,6 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
560 // don't forget lanes.core for regular lane states 558 // don't forget lanes.core for regular lane states
561 open1lib( L, "lanes.core", 10); 559 open1lib( L, "lanes.core", 10);
562 } 560 }
563 else
564 {
565 // In keeper states however, we only want to register the lanes.core functions to be able to transfer them through lindas
566 // (we don't care about a full lanes.core init in the keeper states as we won't call anything in there)
567 register_core_libfuncs_for_keeper( L);
568 }
569 libs = NULL; // done with libs 561 libs = NULL; // done with libs
570 } 562 }
571 else 563 else
@@ -622,7 +614,7 @@ lua_State* luaG_newstate( lua_State* _from, int const _on_state_create, char con
622 STACK_CHECK( _from); 614 STACK_CHECK( _from);
623 // Lua function: transfer as usual (should work as long as it only uses base libraries) 615 // Lua function: transfer as usual (should work as long as it only uses base libraries)
624 lua_pushvalue( _from, _on_state_create); 616 lua_pushvalue( _from, _on_state_create);
625 luaG_inter_move( _from, L, 1); 617 luaG_inter_move( _from, L, 1, eLM_LaneBody);
626 STACK_END( _from, 0); 618 STACK_END( _from, 0);
627 } 619 }
628 // capture error and forward it to main state 620 // capture error and forward it to main state
@@ -1283,59 +1275,6 @@ static bool_t push_cached_table( lua_State *L2, uint_t L2_cache_i, lua_State *L,
1283} 1275}
1284 1276
1285 1277
1286/*
1287 * Check if we've already copied the same function from 'L', and reuse the old
1288 * copy.
1289 *
1290 * Always pushes a function to 'L2'.
1291 */
1292static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, char const* upName_);
1293
1294static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, char const* upName_)
1295{
1296 void* const aspointer = (void*)lua_topointer( L, i);
1297 // TBD: Merge this and same code for tables
1298 ASSERT_L( L2_cache_i != 0);
1299
1300 STACK_GROW( L2, 2);
1301
1302 // L2_cache[id_str]= function
1303 //
1304 STACK_CHECK( L2);
1305
1306 // We don't need to use the from state ('L') in ID since the life span
1307 // is only for the duration of a copy (both states are locked).
1308 //
1309
1310 // push a light userdata uniquely representing the function
1311 lua_pushlightuserdata( L2, aspointer); // ... {cache} ... p
1312
1313 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
1314
1315 lua_pushvalue( L2, -1); // ... {cache} ... p p
1316 lua_rawget( L2, L2_cache_i); // ... {cache} ... p function|nil|true
1317
1318 if( lua_isnil(L2,-1)) // function is unknown
1319 {
1320 lua_pop( L2, 1); // ... {cache} ... p
1321
1322 // Set to 'true' for the duration of creation; need to find self-references
1323 // via upvalues
1324 //
1325 // pushes a copy of the func, stores a reference in the cache
1326 inter_copy_func( L2, L2_cache_i, L, i, upName_); // ... {cache} ... function
1327 }
1328 else // found function in the cache
1329 {
1330 lua_remove( L2, -2); // ... {cache} ... function
1331 }
1332 STACK_END( L2, 1);
1333 //
1334 // L2 [-1]: function
1335
1336 ASSERT_L( lua_isfunction( L2, -1));
1337}
1338
1339/* 1278/*
1340 * Return some name helping to identify an object 1279 * Return some name helping to identify an object
1341 */ 1280 */
@@ -1509,24 +1448,41 @@ int luaG_nameof( lua_State* L)
1509 return 2; 1448 return 2;
1510} 1449}
1511 1450
1451// function sentinel used to transfer native functions from/to keeper states
1452static int sentinelfunc( lua_State* L)
1453{
1454 return luaL_error( L, "transfer sentinel function for %s, should never be called", lua_tostring( L, lua_upvalueindex( 1)));
1455}
1456
1512/* 1457/*
1513* Push a looked-up native/LuaJIT function. 1458* Push a looked-up native/LuaJIT function.
1514*/ 1459*/
1515static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, char const* upName_) 1460static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_)
1516{ 1461{
1517 char const* fqn; // L // L2 1462 char const* fqn; // L // L2
1518 size_t len; 1463 size_t len;
1519 _ASSERT_L( L, lua_isfunction( L, i)); // ... f ... 1464 _ASSERT_L( L, lua_isfunction( L, i)); // ... f ...
1520 STACK_CHECK( L); 1465 STACK_CHECK( L);
1521 // fetch the name from the source state's lookup table 1466 if( mode_ == eLM_FromKeeper)
1522 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // ... f ... {} 1467 {
1523 _ASSERT_L( L, lua_istable( L, -1)); 1468 lua_CFunction f = lua_tocfunction( L, i); // should *always* be sentinelfunc!
1524 lua_pushvalue( L, i); // ... f ... {} f 1469 _ASSERT_L( L, f == sentinelfunc);
1525 lua_rawget( L, -2); // ... f ... {} "f.q.n" 1470 lua_getupvalue( L, i, 1); // ... f ... "f.q.n"
1526 fqn = lua_tolstring( L, -1, &len); 1471 fqn = lua_tolstring( L, -1, &len);
1472 }
1473 else
1474 {
1475 // fetch the name from the source state's lookup table
1476 lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_KEY); // ... f ... {}
1477 _ASSERT_L( L, lua_istable( L, -1));
1478 lua_pushvalue( L, i); // ... f ... {} f
1479 lua_rawget( L, -2); // ... f ... {} "f.q.n"
1480 fqn = lua_tolstring( L, -1, &len);
1481 }
1527 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn)); 1482 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn));
1528 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database 1483 // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database
1529 lua_pop( L, 2); // ... f ... 1484 lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... f ...
1485 STACK_MID( L, 0);
1530 if( !fqn) 1486 if( !fqn)
1531 { 1487 {
1532 char const *from, *typewhat, *what, *gotchaA, *gotchaB; 1488 char const *from, *typewhat, *what, *gotchaA, *gotchaB;
@@ -1556,21 +1512,30 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, char cons
1556 STACK_END( L, 0); 1512 STACK_END( L, 0);
1557 // push the equivalent function in the destination's stack, retrieved from the lookup table 1513 // push the equivalent function in the destination's stack, retrieved from the lookup table
1558 STACK_CHECK( L2); 1514 STACK_CHECK( L2);
1559 lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {} 1515 if( mode_ == eLM_ToKeeper)
1560 _ASSERT_L( L2, lua_istable( L2, -1));
1561 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
1562 lua_rawget( L2, -2); // {} f
1563 if( !lua_isfunction( L2, -1))
1564 { 1516 {
1565 char const* from, * to; 1517 // push a sentinel closure that holds the lookup name as upvalue
1566 lua_getglobal( L, "decoda_name"); // // ... f ... decoda_name 1518 lua_pushlstring( L2, fqn, len); // "f.q.n"
1567 from = lua_tostring( L, -1); 1519 lua_pushcclosure( L2, sentinelfunc, 1); // f
1568 lua_getglobal( L2, "decoda_name"); // {} f decoda_name 1520 }
1569 to = lua_tostring( L2, -1); 1521 else
1570 (void) luaL_error( L, "%s: function '%s' not found in %s destination transfer database.", from ? from : "main", fqn, to ? to : "main"); 1522 {
1571 return; 1523 lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_KEY); // {}
1524 _ASSERT_L( L2, lua_istable( L2, -1));
1525 lua_pushlstring( L2, fqn, len); // {} "f.q.n"
1526 lua_rawget( L2, -2); // {} f
1527 if( !lua_isfunction( L2, -1))
1528 {
1529 char const* from, * to;
1530 lua_getglobal( L, "decoda_name"); // ... f ... decoda_name
1531 from = lua_tostring( L, -1);
1532 lua_getglobal( L2, "decoda_name"); // {} f decoda_name
1533 to = lua_tostring( L2, -1);
1534 (void) luaL_error( L, "%s: function '%s' not found in %s destination transfer database.", from ? from : "main", fqn, to ? to : "main");
1535 return;
1536 }
1537 lua_remove( L2, -2); // f
1572 } 1538 }
1573 lua_remove( L2, -2); // f
1574 STACK_END( L2, 1); 1539 STACK_END( L2, 1);
1575} 1540}
1576 1541
@@ -1581,159 +1546,207 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, char cons
1581enum e_vt { 1546enum e_vt {
1582 VT_NORMAL, VT_KEY, VT_METATABLE 1547 VT_NORMAL, VT_KEY, VT_METATABLE
1583}; 1548};
1584static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt value_type, char const* upName_); 1549static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt value_type, enum eLookupMode mode_, char const* upName_);
1585 1550
1586static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, char const* upName_) 1551static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_)
1587{ 1552{
1588 FuncSubType funcSubType; 1553 int n, needToPush;
1589 /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions 1554 luaL_Buffer b;
1590
1591 ASSERT_L( L2_cache_i != 0); // ... {cache} ... p 1555 ASSERT_L( L2_cache_i != 0); // ... {cache} ... p
1592 STACK_GROW(L,2); 1556 STACK_GROW(L,2);
1593 STACK_CHECK( L); 1557 STACK_CHECK( L);
1594 1558
1595 if( funcSubType == FST_Bytecode) 1559 // 'lua_dump()' needs the function at top of stack
1560 // if already on top of the stack, no need to push again
1561 needToPush = (i != (uint_t)lua_gettop( L));
1562 if( needToPush)
1596 { 1563 {
1597 int n; 1564 lua_pushvalue( L, i); // ... f
1598 luaL_Buffer b; 1565 }
1599 // 'lua_dump()' needs the function at top of stack
1600 // if already on top of the stack, no need to push again
1601 int needToPush = (i != (uint_t)lua_gettop( L));
1602 if( needToPush)
1603 {
1604 lua_pushvalue( L, i); // ... f
1605 }
1606 1566
1607 luaL_buffinit( L, &b); 1567 luaL_buffinit( L, &b);
1608 // 1568 //
1609 // "value returned is the error code returned by the last call 1569 // "value returned is the error code returned by the last call
1610 // to the writer" (and we only return 0) 1570 // to the writer" (and we only return 0)
1611 // not sure this could ever fail but for memory shortage reasons 1571 // not sure this could ever fail but for memory shortage reasons
1612 if( lua_dump( L, buf_writer, &b) != 0) 1572 if( lua_dump( L, buf_writer, &b) != 0)
1613 { 1573 {
1614 luaL_error( L, "internal error: function dump failed."); 1574 luaL_error( L, "internal error: function dump failed.");
1615 } 1575 }
1616 1576
1617 // pushes dumped string on 'L' 1577 // pushes dumped string on 'L'
1618 luaL_pushresult( &b); // ... f b 1578 luaL_pushresult( &b); // ... f b
1619 1579
1620 // if not pushed, no need to pop 1580 // if not pushed, no need to pop
1621 if( needToPush) 1581 if( needToPush)
1582 {
1583 lua_remove( L, -2); // ... b
1584 }
1585
1586 // transfer the bytecode, then the upvalues, to create a similar closure
1587 {
1588 char const* name = NULL;
1589
1590 #if LOG_FUNC_INFO
1591 // "To get information about a function you push it onto the
1592 // stack and start the what string with the character '>'."
1593 //
1622 { 1594 {
1623 lua_remove( L, -2); // ... b 1595 lua_Debug ar;
1596 lua_pushvalue( L, i); // ... b f
1597 // fills 'name' 'namewhat' and 'linedefined', pops function
1598 lua_getinfo(L, ">nS", &ar); // ... b
1599 name = ar.namewhat;
1600 fprintf( stderr, INDENT_BEGIN "FNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL
1624 } 1601 }
1625 1602 #endif // LOG_FUNC_INFO
1626 // transfer the bytecode, then the upvalues, to create a similar closure
1627 { 1603 {
1628 char const* name = NULL; 1604 size_t sz;
1629 1605 char const* s = lua_tolstring( L, -1, &sz); // ... b
1630 #if LOG_FUNC_INFO 1606 ASSERT_L( s && sz);
1631 // "To get information about a function you push it onto the 1607 STACK_GROW( L2, 2);
1632 // stack and start the what string with the character '>'." 1608 // Note: Line numbers seem to be taken precisely from the
1609 // original function. 'name' is not used since the chunk
1610 // is precompiled (it seems...).
1633 // 1611 //
1612 // TBD: Can we get the function's original name through, as well?
1613 //
1614 if( luaL_loadbuffer( L2, s, sz, name) != 0) // ... {cache} ... p function
1634 { 1615 {
1635 lua_Debug ar; 1616 // chunk is precompiled so only LUA_ERRMEM can happen
1636 lua_pushvalue( L, i); // ... b f 1617 // "Otherwise, it pushes an error message"
1637 // fills 'name' 'namewhat' and 'linedefined', pops function
1638 lua_getinfo(L, ">nS", &ar); // ... b
1639 name = ar.namewhat;
1640 fprintf( stderr, INDENT_BEGIN "FNAME: %s @ %d\n", i, s_indent, ar.short_src, ar.linedefined); // just gives NULL
1641 }
1642 #endif // LOG_FUNC_INFO
1643 {
1644 size_t sz;
1645 char const* s = lua_tolstring( L, -1, &sz); // ... b
1646 ASSERT_L( s && sz);
1647 STACK_GROW( L2, 2);
1648 // Note: Line numbers seem to be taken precisely from the
1649 // original function. 'name' is not used since the chunk
1650 // is precompiled (it seems...).
1651 //
1652 // TBD: Can we get the function's original name through, as well?
1653 // 1618 //
1654 if( luaL_loadbuffer( L2, s, sz, name) != 0) // ... {cache} ... p function 1619 STACK_GROW( L, 1);
1655 { 1620 luaL_error( L, "%s", lua_tostring( L2, -1));
1656 // chunk is precompiled so only LUA_ERRMEM can happen
1657 // "Otherwise, it pushes an error message"
1658 //
1659 STACK_GROW( L, 1);
1660 luaL_error( L, "%s", lua_tostring( L2, -1));
1661 }
1662 // remove the dumped string
1663 lua_pop( L, 1); // ...
1664 // now set the cache as soon as we can.
1665 // this is necessary if one of the function's upvalues references it indirectly
1666 // we need to find it in the cache even if it isn't fully transfered yet
1667 lua_insert( L2, -2); // ... {cache} ... function p
1668 lua_pushvalue( L2, -2); // ... {cache} ... function p function
1669 // cache[p] = function
1670 lua_rawset( L2, L2_cache_i); // ... {cache} ... function
1671 } 1621 }
1672 STACK_MID( L, 0); 1622 // remove the dumped string
1623 lua_pop( L, 1); // ...
1624 // now set the cache as soon as we can.
1625 // this is necessary if one of the function's upvalues references it indirectly
1626 // we need to find it in the cache even if it isn't fully transfered yet
1627 lua_insert( L2, -2); // ... {cache} ... function p
1628 lua_pushvalue( L2, -2); // ... {cache} ... function p function
1629 // cache[p] = function
1630 lua_rawset( L2, L2_cache_i); // ... {cache} ... function
1631 }
1632 STACK_MID( L, 0);
1673 1633
1674 /* push over any upvalues; references to this function will come from 1634 /* push over any upvalues; references to this function will come from
1675 * cache so we don't end up in eternal loop. 1635 * cache so we don't end up in eternal loop.
1676 * Lua5.2: one of the upvalues is _ENV, which we don't want to copy! 1636 * Lua5.2: one of the upvalues is _ENV, which we don't want to copy!
1677 * instead, the function shall have LUA_RIDX_GLOBALS taken in the destination state! 1637 * instead, the function shall have LUA_RIDX_GLOBALS taken in the destination state!
1678 */ 1638 */
1679 { 1639 {
1680 char const* upname; 1640 char const* upname;
1681#if LUA_VERSION_NUM == 502 1641#if LUA_VERSION_NUM == 502
1682 // With Lua 5.2, each Lua function gets its environment as one of its upvalues (named LUA_ENV, aka "_ENV" by default) 1642 // With Lua 5.2, each Lua function gets its environment as one of its upvalues (named LUA_ENV, aka "_ENV" by default)
1683 // Generally this is LUA_RIDX_GLOBALS, which we don't want to copy from the source to the destination state... 1643 // Generally this is LUA_RIDX_GLOBALS, which we don't want to copy from the source to the destination state...
1684 // -> if we encounter an upvalue equal to the global table in the source, bind it to the destination's global table 1644 // -> if we encounter an upvalue equal to the global table in the source, bind it to the destination's global table
1685 lua_pushglobaltable( L); // ... _G 1645 lua_pushglobaltable( L); // ... _G
1686#endif // LUA_VERSION_NUM 1646#endif // LUA_VERSION_NUM
1687 for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n) 1647 for( n = 0; (upname = lua_getupvalue( L, i, 1 + n)) != NULL; ++ n)
1688 { // ... _G up[n] 1648 { // ... _G up[n]
1689 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "UPNAME[%d]: %s\n" INDENT_END, n, upname)); 1649 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "UPNAME[%d]: %s\n" INDENT_END, n, upname));
1690#if LUA_VERSION_NUM == 502 1650#if LUA_VERSION_NUM == 502
1691 if( lua_rawequal( L, -1, -2)) // is the upvalue equal to the global table? 1651 if( lua_rawequal( L, -1, -2)) // is the upvalue equal to the global table?
1692 { 1652 {
1693 lua_pushglobaltable( L2); // ... {cache} ... function <upvalues> 1653 lua_pushglobaltable( L2); // ... {cache} ... function <upvalues>
1694 } 1654 }
1695 else 1655 else
1696#endif // LUA_VERSION_NUM 1656#endif // LUA_VERSION_NUM
1657 {
1658 if( !inter_copy_one_( L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, mode_, upname)) // ... {cache} ... function <upvalues>
1697 { 1659 {
1698 if( !inter_copy_one_( L2, L2_cache_i, L, lua_gettop( L), VT_NORMAL, upname)) // ... {cache} ... function <upvalues> 1660 luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1));
1699 {
1700 luaL_error( L, "Cannot copy upvalue type '%s'", luaL_typename( L, -1));
1701 }
1702 } 1661 }
1703 lua_pop( L, 1); // ... _G
1704 } 1662 }
1663 lua_pop( L, 1); // ... _G
1664 }
1705#if LUA_VERSION_NUM == 502 1665#if LUA_VERSION_NUM == 502
1706 lua_pop( L, 1); // ... 1666 lua_pop( L, 1); // ...
1707#endif // LUA_VERSION_NUM 1667#endif // LUA_VERSION_NUM
1708 } 1668 }
1709 // L2: function + 'n' upvalues (>=0) 1669 // L2: function + 'n' upvalues (>=0)
1710 1670
1711 STACK_MID( L, 0); 1671 STACK_MID( L, 0);
1712 1672
1713 // Set upvalues (originally set to 'nil' by 'lua_load') 1673 // Set upvalues (originally set to 'nil' by 'lua_load')
1674 {
1675 int func_index = lua_gettop( L2) - n;
1676 for( ; n > 0; -- n)
1714 { 1677 {
1715 int func_index = lua_gettop( L2) - n; 1678 char const* rc = lua_setupvalue( L2, func_index, n); // ... {cache} ... function
1716 for( ; n > 0; -- n) 1679 //
1717 { 1680 // "assigns the value at the top of the stack to the upvalue and returns its name.
1718 char const* rc = lua_setupvalue( L2, func_index, n); // ... {cache} ... function 1681 // It also pops the value from the stack."
1719 //
1720 // "assigns the value at the top of the stack to the upvalue and returns its name.
1721 // It also pops the value from the stack."
1722 1682
1723 ASSERT_L( rc); // not having enough slots? 1683 ASSERT_L( rc); // not having enough slots?
1724 }
1725 // once all upvalues have been set we are left
1726 // with the function at the top of the stack // ... {cache} ... function
1727 } 1684 }
1685 // once all upvalues have been set we are left
1686 // with the function at the top of the stack // ... {cache} ... function
1728 } 1687 }
1729 } 1688 }
1730 else // C function OR LuaJIT fast function!!! 1689 STACK_END( L, 0);
1690}
1691
1692/*
1693 * Check if we've already copied the same function from 'L', and reuse the old
1694 * copy.
1695 *
1696 * Always pushes a function to 'L2'.
1697 */
1698static void push_cached_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum eLookupMode mode_, char const* upName_)
1699{
1700 FuncSubType funcSubType;
1701 /*lua_CFunction cfunc =*/ luaG_tocfunction( L, i, &funcSubType); // NULL for LuaJIT-fast && bytecode functions
1702 if( funcSubType == FST_Bytecode)
1703 {
1704 void* const aspointer = (void*)lua_topointer( L, i);
1705 // TBD: Merge this and same code for tables
1706 ASSERT_L( L2_cache_i != 0);
1707
1708 STACK_GROW( L2, 2);
1709
1710 // L2_cache[id_str]= function
1711 //
1712 STACK_CHECK( L2);
1713
1714 // We don't need to use the from state ('L') in ID since the life span
1715 // is only for the duration of a copy (both states are locked).
1716 //
1717
1718 // push a light userdata uniquely representing the function
1719 lua_pushlightuserdata( L2, aspointer); // ... {cache} ... p
1720
1721 //fprintf( stderr, "<< ID: %s >>\n", lua_tostring(L2,-1) );
1722
1723 lua_pushvalue( L2, -1); // ... {cache} ... p p
1724 lua_rawget( L2, L2_cache_i); // ... {cache} ... p function|nil|true
1725
1726 if( lua_isnil(L2,-1)) // function is unknown
1727 {
1728 lua_pop( L2, 1); // ... {cache} ... p
1729
1730 // Set to 'true' for the duration of creation; need to find self-references
1731 // via upvalues
1732 //
1733 // pushes a copy of the func, stores a reference in the cache
1734 inter_copy_func( L2, L2_cache_i, L, i, mode_, upName_); // ... {cache} ... function
1735 }
1736 else // found function in the cache
1737 {
1738 lua_remove( L2, -2); // ... {cache} ... function
1739 }
1740 STACK_END( L2, 1);
1741 }
1742 else // function is native/LuaJIT: no need to cache
1731 { 1743 {
1732 lua_pop( L2, 1); // ... {cache} ... 1744 lookup_native_func( L2, L, i, mode_, upName_); // ... {cache} ... function
1733 // No need to transfer upvalues for C/JIT functions since they weren't actually copied, only looked up
1734 lookup_native_func( L2, L, i, upName_); // ... {cache} ... function
1735 } 1745 }
1736 STACK_END( L, 0); 1746
1747 //
1748 // L2 [-1]: function
1749 ASSERT_L( lua_isfunction( L2, -1));
1737} 1750}
1738 1751
1739/* 1752/*
@@ -1746,7 +1759,7 @@ static void inter_copy_func( lua_State* L2, uint_t L2_cache_i, lua_State* L, uin
1746* 1759*
1747* Returns TRUE if value was pushed, FALSE if its type is non-supported. 1760* Returns TRUE if value was pushed, FALSE if its type is non-supported.
1748*/ 1761*/
1749static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, char const* upName_) 1762static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i, enum e_vt vt, enum eLookupMode mode_, char const* upName_)
1750{ 1763{
1751 bool_t ret = TRUE; 1764 bool_t ret = TRUE;
1752 1765
@@ -1764,6 +1777,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1764 1777
1765 case LUA_TNUMBER: 1778 case LUA_TNUMBER:
1766 /* LNUM patch support (keeping integer accuracy) */ 1779 /* LNUM patch support (keeping integer accuracy) */
1780 // TODO: support for integer in Lua 5.3
1767#ifdef LUA_LNUM 1781#ifdef LUA_LNUM
1768 if( lua_isinteger(L,i)) 1782 if( lua_isinteger(L,i))
1769 { 1783 {
@@ -1831,7 +1845,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1831 { 1845 {
1832 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "FUNCTION\n" INDENT_END)); 1846 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "FUNCTION\n" INDENT_END));
1833 STACK_CHECK( L2); 1847 STACK_CHECK( L2);
1834 push_cached_func( L2, L2_cache_i, L, i, upName_); 1848 push_cached_func( L2, L2_cache_i, L, i, mode_, upName_);
1835 STACK_END( L2, 1); 1849 STACK_END( L2, 1);
1836 } 1850 }
1837 break; 1851 break;
@@ -1873,7 +1887,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1873 1887
1874 /* Only basic key types are copied over; others ignored 1888 /* Only basic key types are copied over; others ignored
1875 */ 1889 */
1876 if( inter_copy_one_( L2, 0 /*key*/, L, key_i, VT_KEY, upName_)) 1890 if( inter_copy_one_( L2, 0 /*key*/, L, key_i, VT_KEY, mode_, upName_))
1877 { 1891 {
1878 char* valPath = (char*) upName_; 1892 char* valPath = (char*) upName_;
1879 if( GVerboseErrors) 1893 if( GVerboseErrors)
@@ -1894,7 +1908,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1894 * Contents of metatables are copied with cache checking; 1908 * Contents of metatables are copied with cache checking;
1895 * important to detect loops. 1909 * important to detect loops.
1896 */ 1910 */
1897 if( inter_copy_one_( L2, L2_cache_i, L, val_i, VT_NORMAL, valPath)) 1911 if( inter_copy_one_( L2, L2_cache_i, L, val_i, VT_NORMAL, mode_, valPath))
1898 { 1912 {
1899 ASSERT_L( lua_istable(L2,-3)); 1913 ASSERT_L( lua_istable(L2,-3));
1900 lua_rawset( L2, -3); // add to table (pops key & val) 1914 lua_rawset( L2, -3); // add to table (pops key & val)
@@ -1936,7 +1950,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1936 lua_pop( L2, 1); 1950 lua_pop( L2, 1);
1937 STACK_MID( L2, 2); 1951 STACK_MID( L2, 2);
1938 ASSERT_L( lua_istable(L,-1)); 1952 ASSERT_L( lua_istable(L,-1));
1939 if( inter_copy_one_( L2, L2_cache_i /*for function cacheing*/, L, lua_gettop(L) /*[-1]*/, VT_METATABLE, upName_)) 1953 if( inter_copy_one_( L2, L2_cache_i /*for function cacheing*/, L, lua_gettop(L) /*[-1]*/, VT_METATABLE, mode_, upName_))
1940 { 1954 {
1941 // 1955 //
1942 // L2 ([-3]: copied table) 1956 // L2 ([-3]: copied table)
@@ -1981,8 +1995,8 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
1981 } 1995 }
1982 STACK_END( L2, 1); 1996 STACK_END( L2, 1);
1983 STACK_END( L, 0); 1997 STACK_END( L, 0);
1984 } 1998 }
1985 break; 1999 break;
1986 2000
1987 /* The following types cannot be copied */ 2001 /* The following types cannot be copied */
1988 2002
@@ -2004,7 +2018,7 @@ static bool_t inter_copy_one_( lua_State* L2, uint_t L2_cache_i, lua_State* L, u
2004* 2018*
2005* Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'. 2019* Note: Parameters are in this order ('L' = from first) to be same as 'lua_xmove'.
2006*/ 2020*/
2007int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n) 2021int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_)
2008{ 2022{
2009 uint_t top_L = lua_gettop( L); 2023 uint_t top_L = lua_gettop( L);
2010 uint_t top_L2 = lua_gettop( L2); 2024 uint_t top_L2 = lua_gettop( L2);
@@ -2034,7 +2048,7 @@ int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n)
2034 { 2048 {
2035 sprintf( tmpBuf, "arg_%d", j); 2049 sprintf( tmpBuf, "arg_%d", j);
2036 } 2050 }
2037 copyok = inter_copy_one_( L2, top_L2 + 1, L, i, VT_NORMAL, pBuf); 2051 copyok = inter_copy_one_( L2, top_L2 + 1, L, i, VT_NORMAL, mode_, pBuf);
2038 if( !copyok) 2052 if( !copyok)
2039 { 2053 {
2040 break; 2054 break;
@@ -2062,14 +2076,14 @@ int luaG_inter_copy( lua_State* L, lua_State* L2, uint_t n)
2062} 2076}
2063 2077
2064 2078
2065int luaG_inter_move( lua_State* L, lua_State* L2, uint_t n) 2079int luaG_inter_move( lua_State* L, lua_State* L2, uint_t n, enum eLookupMode mode_)
2066{ 2080{
2067 int ret = luaG_inter_copy( L, L2, n); 2081 int ret = luaG_inter_copy( L, L2, n, mode_);
2068 lua_pop( L, (int) n); 2082 lua_pop( L, (int) n);
2069 return ret; 2083 return ret;
2070} 2084}
2071 2085
2072void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx) 2086void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx, enum eLookupMode mode_)
2073{ 2087{
2074 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); 2088 DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END));
2075 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 2089 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
@@ -2100,7 +2114,7 @@ void luaG_inter_copy_package( lua_State* L, lua_State* L2, int _idx)
2100 else 2114 else
2101 { 2115 {
2102 DEBUGSPEW_CODE( ++ debugspew_indent_depth); 2116 DEBUGSPEW_CODE( ++ debugspew_indent_depth);
2103 luaG_inter_move( L, L2, 1); // moves the entry to L2 2117 luaG_inter_move( L, L2, 1, mode_); // moves the entry to L2
2104 DEBUGSPEW_CODE( -- debugspew_indent_depth); 2118 DEBUGSPEW_CODE( -- debugspew_indent_depth);
2105 lua_setfield( L2, -2, entries[i]); // set package[entries[i]] 2119 lua_setfield( L2, -2, entries[i]); // set package[entries[i]]
2106 } 2120 }