diff options
Diffstat (limited to 'src/tools.c')
-rw-r--r-- | src/tools.c | 129 |
1 files changed, 66 insertions, 63 deletions
diff --git a/src/tools.c b/src/tools.c index 8e886b5..6f71dd8 100644 --- a/src/tools.c +++ b/src/tools.c | |||
@@ -199,7 +199,7 @@ static const luaL_Reg libs[] = | |||
199 | { NULL, NULL } | 199 | { NULL, NULL } |
200 | }; | 200 | }; |
201 | 201 | ||
202 | static void open1lib( Universe* U, lua_State* L, char const* name_, size_t len_, lua_State* from_) | 202 | static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char const* name_, size_t len_) |
203 | { | 203 | { |
204 | int i; | 204 | int i; |
205 | for( i = 0; libs[i].name; ++ i) | 205 | for( i = 0; libs[i].name; ++ i) |
@@ -679,7 +679,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
679 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); | 679 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening ALL standard libraries\n" INDENT_END)); |
680 | luaL_openlibs( L); | 680 | luaL_openlibs( L); |
681 | // don't forget lanes.core for regular lane states | 681 | // don't forget lanes.core for regular lane states |
682 | open1lib( U, L, "lanes.core", 10, from_); | 682 | open1lib( DEBUGSPEW_PARAM_COMMA( U) L, "lanes.core", 10); |
683 | libs_ = NULL; // done with libs | 683 | libs_ = NULL; // done with libs |
684 | } | 684 | } |
685 | else | 685 | else |
@@ -713,12 +713,12 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
713 | while( isalnum( p[len]) || p[len] == '.') | 713 | while( isalnum( p[len]) || p[len] == '.') |
714 | ++ len; | 714 | ++ len; |
715 | // open library | 715 | // open library |
716 | open1lib( U, L, p, len, from_); | 716 | open1lib( DEBUGSPEW_PARAM_COMMA( U) L, p, len); |
717 | } | 717 | } |
718 | } | 718 | } |
719 | lua_gc( L, LUA_GCRESTART, 0); | 719 | lua_gc( L, LUA_GCRESTART, 0); |
720 | 720 | ||
721 | serialize_require( U, L); | 721 | serialize_require( DEBUGSPEW_PARAM_COMMA( U) L); |
722 | 722 | ||
723 | // call this after the base libraries are loaded and GC is restarted | 723 | // call this after the base libraries are loaded and GC is restarted |
724 | // will raise an error in from_ in case of problem | 724 | // will raise an error in from_ in case of problem |
@@ -1353,7 +1353,7 @@ static void inter_copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_ | |||
1353 | // "Otherwise, it pushes an error message" | 1353 | // "Otherwise, it pushes an error message" |
1354 | // | 1354 | // |
1355 | STACK_GROW( L, 1); | 1355 | STACK_GROW( L, 1); |
1356 | luaL_error( L, "%s", lua_tostring( L2, -1)); | 1356 | luaL_error( L, "%s: %s", upName_, lua_tostring( L2, -1)); |
1357 | } | 1357 | } |
1358 | // remove the dumped string | 1358 | // remove the dumped string |
1359 | lua_pop( L, 1); // ... | 1359 | lua_pop( L, 1); // ... |
@@ -1567,6 +1567,12 @@ static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache | |||
1567 | valPath = (char*) alloca( strlen( upName_) + 32 + 3); | 1567 | valPath = (char*) alloca( strlen( upName_) + 32 + 3); |
1568 | sprintf( valPath, "%s[" LUA_NUMBER_FMT "]", upName_, key); | 1568 | sprintf( valPath, "%s[" LUA_NUMBER_FMT "]", upName_, key); |
1569 | } | 1569 | } |
1570 | else if( lua_type( L, key_i) == LUA_TLIGHTUSERDATA) | ||
1571 | { | ||
1572 | void* key = lua_touserdata( L, key_i); | ||
1573 | valPath = (char*) alloca( strlen( upName_) + 16 + 5); | ||
1574 | sprintf( valPath, "%s[U:%p]", upName_, key); | ||
1575 | } | ||
1570 | } | 1576 | } |
1571 | /* | 1577 | /* |
1572 | * Contents of metatables are copied with cache checking; | 1578 | * Contents of metatables are copied with cache checking; |
@@ -1597,7 +1603,6 @@ static void inter_copy_keyvaluepair( Universe* U, lua_State* L2, uint_t L2_cache | |||
1597 | static bool_t inter_copy_one_( 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_) | 1603 | static bool_t inter_copy_one_( 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_) |
1598 | { | 1604 | { |
1599 | bool_t ret = TRUE; | 1605 | bool_t ret = TRUE; |
1600 | bool_t ignore = FALSE; | ||
1601 | int val_type = lua_type( L, i); | 1606 | int val_type = lua_type( L, i); |
1602 | STACK_GROW( L2, 1); | 1607 | STACK_GROW( L2, 1); |
1603 | STACK_CHECK( L); // L // L2 | 1608 | STACK_CHECK( L); // L // L2 |
@@ -1671,71 +1676,69 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu | |||
1671 | } | 1676 | } |
1672 | STACK_MID( L, 0); | 1677 | STACK_MID( L, 0); |
1673 | 1678 | ||
1674 | if( lua_getmetatable( L, i)) // ... mt? | 1679 | if( lua_getmetatable( L, i)) // ... mt? |
1680 | { | ||
1681 | lua_getfield( L, -1, "__lanesclone"); // ... mt __lanesclone? | ||
1682 | if( lua_isnil( L, -1)) | ||
1675 | { | 1683 | { |
1676 | lua_getfield( L, -1, "__lanesclone"); // ... mt __lanesclone? | 1684 | lua_pop( L, 2); // ... |
1677 | if( lua_isnil( L, -1)) | 1685 | } |
1678 | { | 1686 | else |
1679 | lua_pop( L, 2); // ... | 1687 | { |
1680 | } | 1688 | size_t userdata_size = 0; |
1681 | else | 1689 | void* const source = lua_touserdata( L, i); |
1690 | void* clone = NULL; | ||
1691 | lua_pushvalue( L, -1); // ... mt __lanesclone __lanesclone | ||
1692 | // call the cloning function with 0 arguments, should return the number of bytes to allocate for the clone | ||
1693 | lua_call( L, 0, 1); // ... mt __lanesclone size | ||
1694 | STACK_MID( L, 3); | ||
1695 | userdata_size = (size_t) lua_tointeger( L, -1); // ... mt __lanesclone size | ||
1696 | lua_pop( L, 1); // ... mt __lanesclone | ||
1697 | clone = lua_newuserdata( L2, userdata_size); // ... u | ||
1698 | // call cloning function in source state to perform the actual memory cloning | ||
1699 | lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone | ||
1700 | lua_pushlightuserdata( L, source); // ... mt __lanesclone source | ||
1701 | lua_call( L, 2, 0); // ... mt | ||
1702 | STACK_MID( L, 1); | ||
1703 | // copy the metatable in the target state | ||
1704 | if( inter_copy_one_( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_)) // ... u mt? | ||
1682 | { | 1705 | { |
1683 | FuncSubType fst; | 1706 | lua_pop( L, 1); // ... |
1684 | lua_CFunction cloneFunc = luaG_tocfunction( L, -1, &fst); | 1707 | STACK_MID( L, 0); |
1685 | size_t userdata_size = 0; | 1708 | // when writing to a keeper state, we have here a sentinel function with the metatable's fqn as upvalue |
1686 | void* const source = lua_touserdata( L, i); | 1709 | if( eLM_ToKeeper == mode_) // ... u sentinel |
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); | ||
1700 | // copy the metatable in the target state | ||
1701 | if( inter_copy_one_( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_)) // ... u mt? | ||
1702 | { | 1710 | { |
1703 | lua_pop( L, 1); // ... | 1711 | ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel); |
1704 | STACK_MID( L, 0); | 1712 | // we want to create a new closure with a 'clone sentinel' function, where the upvalues are the userdata and the metatable fqn |
1705 | // when writing to a keeper state, we have here a sentinel function with the metatable's fqn as upvalue | 1713 | lua_getupvalue( L2, -1, 1); // ... u sentinel fqn |
1706 | if( eLM_ToKeeper == mode_) // ... u sentinel | 1714 | lua_remove( L2, -2); // ... u fqn |
1707 | { | 1715 | lua_insert( L2, -2); // ... fqn u |
1708 | ASSERT_L( lua_tocfunction( L2, -1) == table_lookup_sentinel); | 1716 | lua_pushcclosure( L2, userdata_clone_sentinel, 2); // ... userdata_clone_sentinel |
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 | ||
1714 | } | ||
1715 | else // from keeper or direct, we have the userdata and the metatable | ||
1716 | { | ||
1717 | ASSERT_L( lua_istable( L2, -1)); | ||
1718 | lua_setmetatable( L2, -2); // ... u | ||
1719 | } | ||
1720 | } | 1717 | } |
1721 | else | 1718 | else // from keeper or direct, we have the userdata and the metatable |
1722 | { | 1719 | { |
1723 | (void) luaL_error( L, "Error copying a metatable"); | 1720 | ASSERT_L( lua_istable( L2, -1)); |
1721 | lua_setmetatable( L2, -2); // ... u | ||
1724 | } | 1722 | } |
1725 | } | 1723 | } |
1726 | break; | 1724 | else |
1725 | { | ||
1726 | (void) luaL_error( L, "Error copying a metatable"); | ||
1727 | } | ||
1727 | } | 1728 | } |
1729 | break; | ||
1730 | } | ||
1728 | 1731 | ||
1729 | // Not a deep or clonable full userdata | 1732 | // Not a deep or clonable full userdata |
1730 | if( U->demoteFullUserdata) // attempt demotion to light userdata | 1733 | if( U->demoteFullUserdata) // attempt demotion to light userdata |
1731 | { | 1734 | { |
1732 | void* lud = lua_touserdata( L, i); | 1735 | void* lud = lua_touserdata( L, i); |
1733 | lua_pushlightuserdata( L2, lud); | 1736 | lua_pushlightuserdata( L2, lud); |
1734 | } | 1737 | } |
1735 | else // raise an error | 1738 | else // raise an error |
1736 | { | 1739 | { |
1737 | (void) luaL_error( L, "can't copy non-deep full userdata across lanes"); | 1740 | (void) luaL_error( L, "can't copy non-deep full userdata across lanes"); |
1738 | } | 1741 | } |
1739 | break; | 1742 | break; |
1740 | 1743 | ||
1741 | case LUA_TNIL: | 1744 | case LUA_TNIL: |
@@ -2035,7 +2038,7 @@ int luaG_new_require( lua_State* L) | |||
2035 | /* | 2038 | /* |
2036 | * Serialize calls to 'require', if it exists | 2039 | * Serialize calls to 'require', if it exists |
2037 | */ | 2040 | */ |
2038 | void serialize_require( Universe* U, lua_State* L) | 2041 | void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) |
2039 | { | 2042 | { |
2040 | STACK_GROW( L, 1); | 2043 | STACK_GROW( L, 1); |
2041 | STACK_CHECK( L); | 2044 | STACK_CHECK( L); |