@@ -517,6 +517,45 @@ private static void ArrayTypeCheck_Helper(object obj, void* elementType)
517517 }
518518 }
519519
520+ // Helpers for boxing
521+ [ DebuggerHidden ]
522+ internal static object ? Box_Nullable ( MethodTable * srcMT , ref byte nullableData )
523+ {
524+ Debug . Assert ( srcMT ->IsNullable ) ;
525+
526+ if ( nullableData == 0 )
527+ return null ;
528+
529+ // Allocate a new instance of the T in Nullable<T>.
530+ MethodTable * dstMT = srcMT ->InstantiationArg0 ( ) ;
531+ ref byte srcValue = ref Unsafe . Add ( ref nullableData , srcMT ->NullableValueAddrOffset ) ;
532+
533+ // Delegate to non-nullable boxing implementation
534+ return Box ( dstMT , ref srcValue ) ;
535+ }
536+
537+ [ DebuggerHidden ]
538+ internal static object Box ( MethodTable * typeMT , ref byte unboxedData )
539+ {
540+ Debug . Assert ( typeMT != null ) ;
541+ Debug . Assert ( typeMT ->IsValueType ) ;
542+
543+ // A null can be passed for boxing of a null ref.
544+ _ = Unsafe . ReadUnaligned < byte > ( ref unboxedData ) ;
545+
546+ object boxed = RuntimeTypeHandle . InternalAllocNoChecks ( typeMT ) ;
547+ if ( typeMT ->ContainsGCPointers )
548+ {
549+ Buffer . BulkMoveWithWriteBarrier ( ref boxed . GetRawData ( ) , ref unboxedData , typeMT ->GetNumInstanceFieldBytesIfContainsGCPointers ( ) ) ;
550+ }
551+ else
552+ {
553+ SpanHelpers . Memmove ( ref boxed . GetRawData ( ) , ref unboxedData , typeMT ->GetNumInstanceFieldBytes ( ) ) ;
554+ }
555+
556+ return boxed ;
557+ }
558+
520559 // Helpers for Unboxing
521560#if FEATURE_TYPEEQUIVALENCE
522561 [ DebuggerHidden ]
@@ -615,27 +654,8 @@ internal static void Unbox_Nullable(ref byte destPtr, MethodTable* typeMT, objec
615654 [ DebuggerHidden ]
616655 internal static object ? ReboxFromNullable ( MethodTable * srcMT , object src )
617656 {
618- Debug . Assert ( srcMT ->IsNullable ) ;
619-
620657 ref byte nullableData = ref src . GetRawData ( ) ;
621-
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 ;
658+ return Box_Nullable ( srcMT , ref nullableData ) ;
639659 }
640660
641661 [ DebuggerHidden ]
0 commit comments