@@ -1275,16 +1275,19 @@ struct Func final {
12751275 OFF (inoutBits)
12761276 OFF (shared)
12771277 OFF (unit)
1278- OFF (methCallerMethName)
12791278 OFF (funcEntry)
12801279#undef OFF
12811280
12821281 static constexpr ptrdiff_t clsOff () {
1283- return offsetof (Func, m_u);
1282+ return offsetof (Func, m_u.m_cls .m_impl );
1283+ }
1284+
1285+ static constexpr ptrdiff_t methCallerMethNameOff () {
1286+ return offsetof (Func, m_u.m_methCaller .m_methName );
12841287 }
12851288
12861289 static constexpr ptrdiff_t methCallerClsNameOff () {
1287- return offsetof (Func, m_u);
1290+ return offsetof (Func, m_u. m_methCaller . m_clsName );
12881291 }
12891292
12901293 static constexpr ptrdiff_t sharedAllFlags () {
@@ -1595,79 +1598,10 @@ struct Func final {
15951598 };
15961599
15971600public:
1598- #ifdef USE_LOWPTR
1599- using low_storage_t = uint32_t ;
1600- #else
1601- using low_storage_t = uintptr_t ;
1602- #endif
1603-
1604- private:
1605- /*
1606- * Lowptr wrapper around std::atomic<Union> for Class* or StringData*
1607- */
1608- struct UnionWrapper {
1609- union U {
1610- low_storage_t m_cls;
1611- low_storage_t m_methCallerClsName;
1612- };
1613- std::atomic<U> m_u;
1614-
1615- // constructors
1616- explicit UnionWrapper (Class *cls)
1617- : m_u([](Class *cls){
1618- U u;
1619- u.m_cls = to_low (cls);
1620- return u; }(cls)) {}
1621- explicit UnionWrapper (const StringData *name)
1622- : m_u([](const StringData *n){
1623- U u;
1624- u.m_methCallerClsName = to_low (n, kMethCallerBit );
1625- return u; }(name)) {}
1626- /* implicit */ UnionWrapper(std::nullptr_t /* px*/ )
1627- : m_u([](){
1628- U u;
1629- u.m_cls = 0 ;
1630- return u; }()) {}
1631- UnionWrapper (const UnionWrapper& r) :
1632- m_u (r.m_u.load()) {
1633- }
1634-
1635- // Assignments
1636- UnionWrapper& operator =(UnionWrapper r) {
1637- m_u.store (r.m_u , std::memory_order_release);
1638- return *this ;
1639- }
1640-
1641- // setter & getter
1642- void setCls (Class *cls) {
1643- U u;
1644- u.m_cls = to_low (cls);
1645- m_u.store (u, std::memory_order_release);
1646- }
1647- Class* cls () const {
1648- auto cls = m_u.load (std::memory_order_acquire).m_cls ;
1649- assertx (!(cls & kMethCallerBit ));
1650- return reinterpret_cast <Class*>(cls);
1651- }
1652- StringData* name () const {
1653- auto n = m_u.load (std::memory_order_acquire).m_methCallerClsName ;
1654- assertx (n & kMethCallerBit );
1655- return reinterpret_cast <StringData*>(n - kMethCallerBit );
1656- }
1657- };
1658-
1659- template <class T >
1660- static Func::low_storage_t to_low (T* px, Func::low_storage_t bit = 0 ) {
1661- Func::low_storage_t ones = ~0 ;
1662- auto ptr = reinterpret_cast <uintptr_t >(px) | bit;
1663- always_assert ((ptr & ones) == ptr);
1664- return (Func::low_storage_t )(ptr);
1665- }
16661601
16671602 // ///////////////////////////////////////////////////////////////////////////
16681603 // Atomic Flags.
16691604
1670- public:
16711605 enum Flags : uint8_t {
16721606 None = 0 ,
16731607 Optimized = 1 << 0 ,
@@ -1792,8 +1726,6 @@ struct Func final {
17921726 static std::atomic<bool > s_treadmill;
17931727 static std::atomic<uint32_t > s_totalClonedClosures;
17941728
1795- // To conserve space, we use unions for pairs of mutually exclusive fields
1796- static auto constexpr kMethCallerBit = 0x1 ; // set for m_methCaller
17971729 // ///////////////////////////////////////////////////////////////////////////
17981730 // Data members.
17991731 //
@@ -1812,23 +1744,78 @@ struct Func final {
18121744 mutable AtomicLowPtr<const StringData> m_fullName{nullptr };
18131745 LowStringPtr m_name{nullptr };
18141746
1815- union {
1816- // The first Class in the inheritance hierarchy that declared this method.
1817- // Note that this may be an abstract class that did not provide an
1818- // implementation.
1819- low_storage_t m_baseCls{0 };
1820- // m_methCallerMethName can be accessed by meth_caller() only
1821- low_storage_t m_methCallerMethName;
1747+ struct ClsOrMethCaller {
1748+ struct Cls {
1749+ // The first Class in the inheritance hierarchy that declared this method.
1750+ // Note that this may be an abstract class that did not provide an
1751+ // implementation.
1752+ LowPtr<Class> m_base{nullptr };
1753+ // Class that provided this method implementation
1754+ AtomicLowPtr<Class> m_impl{nullptr };
1755+
1756+ Cls () {}
1757+
1758+ Cls (const Cls& o) {
1759+ m_base = o.m_base ;
1760+ m_impl = o.m_impl ;
1761+ }
1762+
1763+ Cls& operator =(const Cls& o) {
1764+ m_base = o.m_base ;
1765+ m_impl = o.m_impl ;
1766+ return *this ;
1767+ }
1768+ };
1769+ struct MethCaller {
1770+ LowStringPtr m_methName;
1771+ // Class name provided by meth_caller()
1772+ LowStringPtr m_clsName;
1773+ };
1774+
1775+ // The first part of the union is valid if !isMethCaller
1776+ // and the second part is valid if isMethCaller
1777+ union {
1778+ Cls m_cls;
1779+ MethCaller m_methCaller;
1780+ };
1781+
1782+ ClsOrMethCaller () {
1783+ m_cls.m_base = nullptr ;
1784+ m_cls.m_impl = nullptr ;
1785+ }
1786+
1787+ ClsOrMethCaller (const ClsOrMethCaller& o) {
1788+ m_cls = o.m_cls ;
1789+ }
18221790 };
18231791
1824- // m_u is used to represent
1825- // the Class that provided this method implementation, or
1826- // the class name provided by meth_caller()
1827- UnionWrapper m_u{nullptr };
1792+ ClsOrMethCaller::Cls& clsData () {
1793+ assertx (!isMethCaller ());
1794+ return m_u.m_cls ;
1795+ }
1796+
1797+ const ClsOrMethCaller::Cls& clsData () const {
1798+ assertx (!isMethCaller ());
1799+ return m_u.m_cls ;
1800+ }
1801+
1802+ ClsOrMethCaller::MethCaller& methCallerData () {
1803+ assertx (isMethCaller ());
1804+ return m_u.m_methCaller ;
1805+ }
1806+
1807+ const ClsOrMethCaller::MethCaller& methCallerData () const {
1808+ assertx (isMethCaller ());
1809+ return m_u.m_methCaller ;
1810+ }
1811+
1812+ ClsOrMethCaller m_u;
1813+
18281814 union {
18291815 Slot m_methodSlot{0 };
1830- LowPtr<const NamedFunc>::storage_type m_namedFunc;
1816+ LowPtr<const NamedFunc> m_namedFunc;
18311817 };
1818+
18321819 mutable ClonedFlag m_cloned;
18331820 mutable AtomicFlags m_atomicFlags;
18341821 bool m_isPreFunc : 1 ;
0 commit comments