88
99// //////////////////////////////////////////////////////////////////////////////////////////////////
1010
11+ #include < type_traits>
1112#include < nanoCLR_Types.h>
1213#include < nanoCLR_Interop.h>
1314#include < nanoCLR_ErrorCodes.h>
@@ -515,6 +516,15 @@ struct CLR_RT_Memory
515516 memset (buf, 0 , len);
516517 }
517518
519+ template <typename T> static void Clear (T &ref)
520+ {
521+ // A type with a non-trivial destructor owns something that has to be released
522+ // for example, an entry in the CLR_RT_ProtectFromGC chain on which zero-filling it silently orphans that.
523+ static_assert (std::is_trivially_destructible<T>::value, " NANOCLR_CLEAR on a type that owns resources" );
524+
525+ ZeroFill (&ref, sizeof (T));
526+ }
527+
518528 // --//
519529
520530 static void Reset ();
@@ -551,7 +561,7 @@ extern void CLR_RT_GetVersion(
551561 unsigned short int *pBuild,
552562 unsigned short int *pRevision);
553563
554- #define NANOCLR_CLEAR (ref ) CLR_RT_Memory::ZeroFill(& ref, sizeof (ref) )
564+ #define NANOCLR_CLEAR (ref ) CLR_RT_Memory::Clear( ref)
555565
556566// --//
557567
@@ -1581,7 +1591,7 @@ struct CLR_RT_WellKnownTypes
15811591 CLR_RT_TypeDef_Index m_I2cTransferResult;
15821592 CLR_RT_TypeDef_Index m_I2cTransferResult_old;
15831593
1584- CLR_RT_TypeDef_Index m_RmtCommand ;
1594+ CLR_RT_TypeDef_Index m_RmtSymbol ;
15851595
15861596 PROHIBIT_COPY_CONSTRUCTORS (CLR_RT_WellKnownTypes);
15871597};
@@ -1968,6 +1978,50 @@ struct CLR_RT_MethodDef_Instance : public CLR_RT_MethodDef_Index
19681978#endif // #if defined(NANOCLR_ENABLE_SOURCELEVELDEBUGGING)
19691979};
19701980
1981+ // //////////////////////////////////////////////////////////////////////////////
1982+
1983+ struct CLR_RT_ProtectFromGC
1984+ {
1985+ static const CLR_UINT32 c_Generic = 0x00000001 ;
1986+ static const CLR_UINT32 c_HeapBlock = 0x00000002 ;
1987+ static const CLR_UINT32 c_ResetKeepAlive = 0x00000004 ;
1988+
1989+ typedef void (*Callback)(void *state);
1990+
1991+ static CLR_RT_ProtectFromGC *s_first;
1992+
1993+ CLR_RT_ProtectFromGC *m_next;
1994+ void **m_data;
1995+ Callback m_fpn;
1996+ CLR_UINT32 m_flags;
1997+
1998+ CLR_RT_ProtectFromGC (CLR_RT_HeapBlock &ref)
1999+ {
2000+ Initialize (ref);
2001+ }
2002+ CLR_RT_ProtectFromGC (void **data, Callback fpn)
2003+ {
2004+ Initialize (data, fpn);
2005+ }
2006+ ~CLR_RT_ProtectFromGC ()
2007+ {
2008+ Cleanup ();
2009+ }
2010+
2011+ static void InvokeAll ();
2012+
2013+ private:
2014+ void Initialize (CLR_RT_HeapBlock &ref);
2015+ void Initialize (void **data, Callback fpn);
2016+ void Cleanup ();
2017+
2018+ // Cold recovery path for Cleanup(), kept out of line so that it isn't inlined into every
2019+ // destruction site.
2020+ NANOCLR_NOINLINE void UnlinkOutOfOrder ();
2021+
2022+ void Invoke ();
2023+ };
2024+
19712025// //////////////////////////////////////////////////////////////////////////////////////////////////
19722026
19732027struct CLR_RT_AttributeEnumerator
@@ -1994,6 +2048,9 @@ struct CLR_RT_AttributeEnumerator
19942048 void Initialize (CLR_RT_Assembly *assm);
19952049};
19962050
2051+ // Developer note: Value::m_valueGC holds a live entry in the CLR_RT_ProtectFromGC chain for this object whole lifetime.
2052+ // Never memset/memcpy an instance (NANOCLR_CLEAR included) and never give one a lifetime that doesn't nest with the
2053+ // enclosing scope.
19972054struct CLR_RT_AttributeParser
19982055{
19992056 struct Value
@@ -2004,10 +2061,34 @@ struct CLR_RT_AttributeParser
20042061 static const int c_DefaultConstructor = 4 ;
20052062
20062063 int m_mode;
2007- CLR_RT_HeapBlock m_value;
2064+ // Declaration order below is load-bearing: CLR_RT_ProtectFromGC's constructor reads
2065+ // m_value.IsForcedAlive(), so m_value has to be declared -- and zeroed -- before m_valueGC.
2066+ CLR_RT_HeapBlock m_value{};
2067+ CLR_RT_ProtectFromGC m_valueGC{m_value};
20082068
20092069 int m_pos;
20102070 const char *m_name;
2071+
2072+ // --//
2073+
2074+ // Required, not decorative: declaring the deleted copy constructor below suppresses the
2075+ // implicit default constructor. It also has to stay defaulted *here*, in the class body --
2076+ // an out of line "= default" would make it user provided, which drops the zero
2077+ // initialization that m_valueGC's constructor depends on.
2078+ Value () = default ;
2079+
2080+ // Prevent copying because shallow copies of CLR_RT_ProtectFromGC
2081+ // can corrupt the GC protection list during destruction.
2082+
2083+ // Delete copy constructor
2084+ Value (const Value &) = delete ;
2085+ // Delete copy-assignment operator
2086+ Value &operator =(const Value &) = delete ;
2087+
2088+ // Stack only: the CLR_RT_ProtectFromGC entry is released by popping the chain, not by
2089+ // searching it, so this object's lifetime has to nest with the enclosing scope.
2090+ static void *operator new (size_t ) = delete ;
2091+ static void *operator new [](size_t ) = delete ;
20112092 };
20122093
20132094 // --//
@@ -2040,6 +2121,11 @@ struct CLR_RT_AttributeParser
20402121 const CLR_UINT32 size);
20412122 HRESULT ReadString (CLR_RT_HeapBlock *&value);
20422123
2124+ // Stack only, for the same reason as CLR_RT_AttributeParser::Value above: this owns the
2125+ // registration through m_lastValue.
2126+ static void *operator new (size_t ) = delete ;
2127+ static void *operator new [](size_t ) = delete ;
2128+
20432129 private:
20442130 const char *GetString ();
20452131};
@@ -2509,46 +2595,6 @@ CT_ASSERT(
25092595
25102596#endif // _MSC_VER
25112597
2512- // //////////////////////////////////////////////////////////////////////////////
2513-
2514- struct CLR_RT_ProtectFromGC
2515- {
2516- static const CLR_UINT32 c_Generic = 0x00000001 ;
2517- static const CLR_UINT32 c_HeapBlock = 0x00000002 ;
2518- static const CLR_UINT32 c_ResetKeepAlive = 0x00000004 ;
2519-
2520- typedef void (*Callback)(void *state);
2521-
2522- static CLR_RT_ProtectFromGC *s_first;
2523-
2524- CLR_RT_ProtectFromGC *m_next;
2525- void **m_data;
2526- Callback m_fpn;
2527- CLR_UINT32 m_flags;
2528-
2529- CLR_RT_ProtectFromGC (CLR_RT_HeapBlock &ref)
2530- {
2531- Initialize (ref);
2532- }
2533- CLR_RT_ProtectFromGC (void **data, Callback fpn)
2534- {
2535- Initialize (data, fpn);
2536- }
2537- ~CLR_RT_ProtectFromGC ()
2538- {
2539- Cleanup ();
2540- }
2541-
2542- static void InvokeAll ();
2543-
2544- private:
2545- void Initialize (CLR_RT_HeapBlock &ref);
2546- void Initialize (void **data, Callback fpn);
2547- void Cleanup ();
2548-
2549- void Invoke ();
2550- };
2551-
25522598// //////////////////////////////////////
25532599
25542600#if defined(NANOCLR_TRACE_EARLYCOLLECTION)
@@ -3452,6 +3498,7 @@ typedef enum Events
34523498 Event_UsbOut = 0x00004000 ,
34533499 Event_IO = 0x00008000 ,
34543500 Event_I2cSlave = 0x00010000 ,
3501+ Event_RmtRx = 0x00020000 ,
34553502 Event_AppDomain = 0x02000000 ,
34563503 Event_Socket = 0x20000000 ,
34573504 Event_IdleCPU = 0x40000000 ,
0 commit comments