@@ -517,6 +517,67 @@ private static void ArrayTypeCheck_Helper(object obj, void* elementType)
517517 }
518518 }
519519
520+ // Helpers for boxing
521+ [ DebuggerHidden ]
522+ private static unsafe object ? Box_Nullable ( IntPtr handle , ref byte nullableData )
523+ {
524+ MethodTable * srcMT = new TypeHandle ( ( void * ) handle ) . AsMethodTable ( ) ;
525+ return BoxNullableImpl ( srcMT , ref nullableData ) ;
526+ }
527+
528+ [ DebuggerHidden ]
529+ internal static object ? BoxNullableImpl ( MethodTable * srcMT , ref byte nullableData )
530+ {
531+ Debug . Assert ( srcMT ->IsNullable ) ;
532+
533+ // If 'hasValue' is false, return null.
534+ if ( ! Unsafe . As < byte , bool > ( ref nullableData ) )
535+ return null ;
536+
537+ // Allocate a new instance of the T in Nullable<T>.
538+ MethodTable * dstMT = srcMT ->InstantiationArg0 ( ) ;
539+ object dst = RuntimeTypeHandle . InternalAllocNoChecks ( dstMT ) ;
540+
541+ // Copy data from the Nullable<T>.
542+ ref byte srcData = ref Unsafe . Add ( ref nullableData , srcMT ->NullableValueAddrOffset ) ;
543+ ref byte dstData = ref RuntimeHelpers . GetRawData ( dst ) ;
544+ if ( dstMT ->ContainsGCPointers )
545+ Buffer . BulkMoveWithWriteBarrier ( ref dstData , ref srcData , dstMT ->GetNumInstanceFieldBytesIfContainsGCPointers ( ) ) ;
546+ else
547+ SpanHelpers . Memmove ( ref dstData , ref srcData , dstMT ->GetNumInstanceFieldBytes ( ) ) ;
548+
549+ return dst ;
550+ }
551+
552+ [ DebuggerHidden ]
553+ internal static unsafe object Box ( IntPtr handle , ref byte unboxedData )
554+ {
555+ MethodTable * typeMT = new TypeHandle ( ( void * ) handle ) . AsMethodTable ( ) ;
556+ Debug . Assert ( typeMT ->IsValueType && ! typeMT ->IsNullable ) ;
557+
558+ return BoxImpl ( typeMT , ref unboxedData ) ;
559+ }
560+
561+ [ DebuggerHidden ]
562+ internal static unsafe object BoxImpl ( MethodTable * typeMT , ref byte unboxedData )
563+ {
564+ Debug . Assert ( typeMT != null ) ;
565+ Debug . Assert ( typeMT ->IsValueType ) ;
566+
567+ object boxed = RuntimeTypeHandle . InternalAlloc ( typeMT ) ;
568+ if ( typeMT ->ContainsGCPointers )
569+ {
570+ Buffer . BulkMoveWithWriteBarrier ( ref boxed . GetRawData ( ) , ref unboxedData ,
571+ typeMT ->GetNumInstanceFieldBytesIfContainsGCPointers ( ) ) ;
572+ }
573+ else
574+ {
575+ SpanHelpers . Memmove ( ref boxed . GetRawData ( ) , ref unboxedData , typeMT ->GetNumInstanceFieldBytes ( ) ) ;
576+ }
577+
578+ return boxed ;
579+ }
580+
520581 // Helpers for Unboxing
521582#if FEATURE_TYPEEQUIVALENCE
522583 [ DebuggerHidden ]
@@ -619,23 +680,7 @@ internal static void Unbox_Nullable(ref byte destPtr, MethodTable* typeMT, objec
619680
620681 ref byte nullableData = ref src . GetRawData ( ) ;
621682
622- // If 'hasValue' is false, return null.
623- if ( ! Unsafe . As < byte , bool > ( ref nullableData ) )
624- return null ;
625-
626- // Allocate a new instance of the T in Nullable<T>.
627- MethodTable * dstMT = srcMT ->InstantiationArg0 ( ) ;
628- object dst = RuntimeTypeHandle . InternalAlloc ( dstMT ) ;
629-
630- // Copy data from the Nullable<T>.
631- ref byte srcData = ref Unsafe . Add ( ref nullableData , srcMT ->NullableValueAddrOffset ) ;
632- ref byte dstData = ref RuntimeHelpers . GetRawData ( dst ) ;
633- if ( dstMT ->ContainsGCPointers )
634- Buffer . BulkMoveWithWriteBarrier ( ref dstData , ref srcData , dstMT ->GetNumInstanceFieldBytesIfContainsGCPointers ( ) ) ;
635- else
636- SpanHelpers . Memmove ( ref dstData , ref srcData , dstMT ->GetNumInstanceFieldBytes ( ) ) ;
637-
638- return dst ;
683+ return BoxNullableImpl ( srcMT , ref nullableData ) ;
639684 }
640685
641686 [ DebuggerHidden ]
0 commit comments