* Add GC.KeepAlive call in the IL stub when marshalling a HandleRef.
* Add a GC.KeepAlive call for the BoxedInt since it isn't kept alive when running GC Stress
* Reference HandleRef._handle via the binder instead of by field offset arithmetic
* Alignment
* Use Marshal.Alloc/FreeHGlobal instead of the weird no-pinning machinery that was failing before
* Update HandleRefTest.cs
ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
ILCodeStream* pcsMarshal = psl->GetMarshalCodeStream();
ILCodeStream* pcsDispatch = psl->GetDispatchCodeStream();
+ ILCodeStream* pcsUnmarshal = psl->GetUnmarshalCodeStream();
if (fManagedToNative && !byref)
{
if (fManagedToNative && !byref)
{
// HandleRefs are valuetypes, so pinning is not needed.
// The argument address is on the stack and will not move.
// HandleRefs are valuetypes, so pinning is not needed.
// The argument address is on the stack and will not move.
- pcsDispatch->EmitLDARGA(argidx);
- pcsDispatch->EmitLDC(offsetof(HANDLEREF, m_handle));
- pcsDispatch->EmitADD();
- pcsDispatch->EmitLDIND_I();
+ mdFieldDef handleField = pcsDispatch->GetToken(MscorlibBinder::GetField(FIELD__HANDLE_REF__HANDLE));
+ pcsDispatch->EmitLDARG(argidx);
+ pcsDispatch->EmitLDFLD(handleField);
+
+ mdFieldDef wrapperField = pcsUnmarshal->GetToken(MscorlibBinder::GetField(FIELD__HANDLE_REF__WRAPPER));
+ pcsUnmarshal->EmitLDARG(argidx);
+ pcsUnmarshal->EmitLDFLD(wrapperField);
+ pcsUnmarshal->EmitCALL(METHOD__GC__KEEP_ALIVE, 1, 0);
+
return OVERRIDDEN;
}
else
return OVERRIDDEN;
}
else
DEFINE_METHOD(CRITICAL_HANDLE, DISPOSE, Dispose, IM_RetVoid)
DEFINE_METHOD(CRITICAL_HANDLE, DISPOSE_BOOL, Dispose, IM_Bool_RetVoid)
DEFINE_METHOD(CRITICAL_HANDLE, DISPOSE, Dispose, IM_RetVoid)
DEFINE_METHOD(CRITICAL_HANDLE, DISPOSE_BOOL, Dispose, IM_Bool_RetVoid)
+DEFINE_CLASS(HANDLE_REF, Interop, HandleRef)
+DEFINE_FIELD(HANDLE_REF, WRAPPER, _wrapper)
+DEFINE_FIELD(HANDLE_REF, HANDLE, _handle)
+
DEFINE_CLASS(CRITICAL_FINALIZER_OBJECT, ConstrainedExecution, CriticalFinalizerObject)
DEFINE_METHOD(CRITICAL_FINALIZER_OBJECT, FINALIZE, Finalize, IM_RetVoid)
DEFINE_CLASS(CRITICAL_FINALIZER_OBJECT, ConstrainedExecution, CriticalFinalizerObject)
DEFINE_METHOD(CRITICAL_FINALIZER_OBJECT, FINALIZE, Finalize, IM_RetVoid)
using System.Text;
using TestLibrary;
using System.Text;
using TestLibrary;
-class BoxedInt
-{
- public int MyInt;
-}
-
class HandleRefTest
{
[DllImport(@"HandleRefNative", CallingConvention = CallingConvention.Winapi)]
class HandleRefTest
{
[DllImport(@"HandleRefNative", CallingConvention = CallingConvention.Winapi)]
// stay rooted until the end of the method.
Console.WriteLine("TestNoGC");
// stay rooted until the end of the method.
Console.WriteLine("TestNoGC");
- // Keep the int boxed and pinned to prevent it from getting collected.
- // That way, we can safely reference it from finalizers that run on shutdown.
- BoxedInt boxedInt = new BoxedInt();
- GCHandle.Alloc(boxedInt, GCHandleType.Normal);
- int* int4Ptr;
- fixed (int* tempIntPtr = &boxedInt.MyInt)
- {
- // Smuggle the pointer out of the fixed scope
- int4Ptr = tempIntPtr;
- }
+ int* int4Ptr = (int*)Marshal.AllocHGlobal(sizeof(int)); // We don't free this memory so we don't have to worry about a GC run between freeing and return (possible in a GCStress mode).
Console.WriteLine("2");
*int4Ptr = intManaged;
CollectableClass collectableClass = new CollectableClass(int4Ptr);
Console.WriteLine("2");
*int4Ptr = intManaged;
CollectableClass collectableClass = new CollectableClass(int4Ptr);