Skip to content

Commit d6e7483

Browse files
BrzVladlewurm
authored andcommitted
[interp] Fix CEE_UNBOX
When unboxing nullable we call Nullable.Unbox which returns the valuetype, but CEE_UNBOX needs to return an address to it. Therefore we store the result in a local in the frame so we can get its address.
1 parent 7a528f6 commit d6e7483

3 files changed

Lines changed: 43 additions & 7 deletions

File tree

mono/mini/aot-tests.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,6 @@ static int test_0_arm64_dyncall_vtypebyref_ret () {
216216
return 0;
217217
}
218218

219-
[Category ("!INTERPRETER")]
220219
static int test_42_arm64_dyncall_vtypebyval () {
221220
var method = typeof (Foo5<string>).GetMethod ("vtype_by_val").MakeGenericMethod (new Type [] { typeof (int), typeof (long?), typeof (long?), typeof (long?), typeof (long?) });
222221
long res = (long)method.Invoke (null, new object [] { 1, 2L, 3L, 4L, 42L });

mono/mini/interp/interp-internals.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ typedef struct _InterpMethod
8888
MonoMethod *method;
8989
struct _InterpMethod *next_jit_code_hash;
9090
guint32 locals_size;
91+
guint32 total_locals_size;
9192
guint32 args_size;
9293
guint32 stack_size;
9394
guint32 vt_stack_size;

mono/mini/interp/transform.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

690691
static 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+
14261452
static void
14271453
interp_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

Comments
 (0)