@@ -85,6 +85,7 @@ typedef struct
8585 unsigned int stack_capacity ;
8686 unsigned int vt_sp ;
8787 unsigned int max_vt_sp ;
88+ unsigned int total_locals_size ;
8889 int n_data_items ;
8990 int max_data_items ;
9091 void * * data_items ;
@@ -688,11 +689,9 @@ load_local(TransformData *td, int n)
688689}
689690
690691static void
691- store_local (TransformData * td , int n )
692+ store_local_general (TransformData * td , int offset , MonoType * type )
692693{
693- MonoType * type = td -> header -> locals [n ];
694694 int mt = mint_type (type );
695- int offset = td -> rtm -> local_offsets [n ];
696695 CHECK_STACK (td , 1 );
697696#if SIZEOF_VOID_P == 8
698697 if (td -> sp [-1 ].type == STACK_TYPE_I4 && stack_type [mt ] == STACK_TYPE_I8 ) {
@@ -721,6 +720,14 @@ store_local(TransformData *td, int n)
721720 -- td -> sp ;
722721}
723722
723+ static void
724+ store_local (TransformData * td , int n )
725+ {
726+ MonoType * type = td -> header -> locals [n ];
727+ int offset = td -> rtm -> local_offsets [n ];
728+ store_local_general (td , offset , type );
729+ }
730+
724731#define SIMPLE_OP (td , op ) \
725732 do { \
726733 ADD_CODE(td, op); \
@@ -1423,6 +1430,25 @@ get_basic_blocks (TransformData *td)
14231430 }
14241431}
14251432
1433+ /*
1434+ * These are additional locals that can be allocated as we transform the code.
1435+ * They are allocated past the method locals so they are accessed in the same
1436+ * way, with an offset relative to the frame->locals.
1437+ */
1438+ static int
1439+ create_interp_local (TransformData * td , MonoType * type )
1440+ {
1441+ int align , size ;
1442+ int offset = td -> total_locals_size ;
1443+
1444+ size = mono_type_size (type , & align );
1445+ offset = ALIGN_TO (offset , align );
1446+
1447+ td -> total_locals_size = offset + size ;
1448+
1449+ return offset ;
1450+ }
1451+
14261452static void
14271453interp_save_debug_info (InterpMethod * rtm , MonoMethodHeader * header , TransformData * td , GArray * line_numbers )
14281454{
@@ -1727,6 +1753,7 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, unsig
17271753 td -> seq_points = g_ptr_array_new ();
17281754 td -> relocs = g_ptr_array_new ();
17291755 td -> verbose_level = mono_interp_traceopt ;
1756+ td -> total_locals_size = rtm -> locals_size ;
17301757 rtm -> data_items = td -> data_items ;
17311758 for (i = 0 ; i < header -> code_size ; i ++ ) {
17321759 td -> stack_height [i ] = -1 ;
@@ -2912,8 +2939,16 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, unsig
29122939 MonoMethod * target_method = mono_class_get_method_from_name (klass , "Unbox" , 1 );
29132940 /* td->ip is incremented by interp_transform_call */
29142941 interp_transform_call (td , method , target_method , domain , generic_context , is_bb_start , body_start_offset , NULL , FALSE, error , FALSE);
2915-
29162942 goto_if_nok (error , exit );
2943+ /*
2944+ * CEE_UNBOX needs to push address of vtype while Nullable.Unbox returns the value type
2945+ * We create a local variable in the frame so that we can fetch its address.
2946+ */
2947+ int local_offset = create_interp_local (td , & klass -> byval_arg );
2948+ store_local_general (td , local_offset , & klass -> byval_arg );
2949+ ADD_CODE (td , MINT_LDLOCA_S );
2950+ ADD_CODE (td , local_offset );
2951+ PUSH_SIMPLE_TYPE (td , STACK_TYPE_MP );
29172952 } else {
29182953 ADD_CODE (td , MINT_UNBOX );
29192954 ADD_CODE (td , get_data_item_index (td , klass ));
@@ -4418,9 +4453,10 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, unsig
44184453 c -> data .filter_offset = td -> in_offsets [c -> data .filter_offset ];
44194454 }
44204455 rtm -> stack_size = (sizeof (stackval )) * (td -> max_stack_height + 2 ); /* + 1 for returns of called functions + 1 for 0-ing in trace*/
4421- rtm -> stack_size = (rtm -> stack_size + 7 ) & ~ 7 ;
4456+ rtm -> stack_size = ALIGN_TO (rtm -> stack_size , MINT_VT_ALIGNMENT ) ;
44224457 rtm -> vt_stack_size = td -> max_vt_sp ;
4423- rtm -> alloca_size = rtm -> locals_size + rtm -> args_size + rtm -> vt_stack_size + rtm -> stack_size ;
4458+ rtm -> total_locals_size = td -> total_locals_size ;
4459+ rtm -> alloca_size = rtm -> total_locals_size + rtm -> args_size + rtm -> vt_stack_size + rtm -> stack_size ;
44244460 rtm -> data_items = mono_domain_alloc0 (domain , td -> n_data_items * sizeof (td -> data_items [0 ]));
44254461 memcpy (rtm -> data_items , td -> data_items , td -> n_data_items * sizeof (td -> data_items [0 ]));
44264462
0 commit comments