Skip to content

Commit edec2f0

Browse files
authored
[mono][interp] Fix handing of native types (#61612)
* [interp] Improve logging on mobile devices Use a single g_print in bulk for every instruction. Otherwise, the instruction ends up being displayed on multiple lines. * [interp] Remove hack for nint/nfloat These structures are valuetypes, but their mint_type is a primitive. This means that a LDFLD applied on the type would have attempted to do a pointer dereference, because it saw that the current top of stack is not STACK_TYPE_VT. This was fixed in the past by passing the managed pointer to the valuetype rather than the valuetype itself, against the normal call convention, which lead to inconsistencies in the code. This commit removes that hack and fixes the problem by ignoring LDFLD applied to nint/nfloat valuetypes in the first place.
1 parent c9ea14c commit edec2f0

File tree

1 file changed

+34
-63
lines changed

1 file changed

+34
-63
lines changed

src/mono/mono/mini/interp/transform.c

+34-63
Original file line numberDiff line numberDiff line change
@@ -1446,25 +1446,27 @@ dump_interp_compacted_ins (const guint16 *ip, const guint16 *start)
14461446
{
14471447
int opcode = *ip;
14481448
int ins_offset = ip - start;
1449+
GString *str = g_string_new ("");
14491450

1450-
g_print ("IR_%04x: %-14s", ins_offset, mono_interp_opname (opcode));
1451+
g_string_append_printf (str, "IR_%04x: %-14s", ins_offset, mono_interp_opname (opcode));
14511452
ip++;
14521453

14531454
if (mono_interp_op_dregs [opcode] > 0)
1454-
g_print (" [%d <-", *ip++);
1455+
g_string_append_printf (str, " [%d <-", *ip++);
14551456
else
1456-
g_print (" [nil <-");
1457+
g_string_append_printf (str, " [nil <-");
14571458

14581459
if (mono_interp_op_sregs [opcode] > 0) {
14591460
for (int i = 0; i < mono_interp_op_sregs [opcode]; i++)
1460-
g_print (" %d", *ip++);
1461-
g_print ("],");
1461+
g_string_append_printf (str, " %d", *ip++);
1462+
g_string_append_printf (str, "],");
14621463
} else {
1463-
g_print (" nil],");
1464+
g_string_append_printf (str, " nil],");
14641465
}
1465-
char *ins = dump_interp_ins_data (NULL, ins_offset, ip, opcode);
1466-
g_print ("%s\n", ins);
1467-
g_free (ins);
1466+
char *ins_data = dump_interp_ins_data (NULL, ins_offset, ip, opcode);
1467+
g_print ("%s%s\n", str->str, ins_data);
1468+
g_string_free (str, TRUE);
1469+
g_free (ins_data);
14681470
}
14691471

14701472
static void
@@ -1478,51 +1480,47 @@ dump_interp_code (const guint16 *start, const guint16* end)
14781480
}
14791481

14801482
static void
1481-
dump_interp_inst_no_newline (InterpInst *ins)
1483+
dump_interp_inst (InterpInst *ins)
14821484
{
14831485
int opcode = ins->opcode;
1484-
g_print ("IL_%04x: %-14s", ins->il_offset, mono_interp_opname (opcode));
1486+
GString *str = g_string_new ("");
1487+
g_string_append_printf (str, "IL_%04x: %-14s", ins->il_offset, mono_interp_opname (opcode));
14851488

14861489
if (mono_interp_op_dregs [opcode] > 0)
1487-
g_print (" [%d <-", ins->dreg);
1490+
g_string_append_printf (str, " [%d <-", ins->dreg);
14881491
else
1489-
g_print (" [nil <-");
1492+
g_string_append_printf (str, " [nil <-");
14901493

14911494
if (mono_interp_op_sregs [opcode] > 0) {
14921495
for (int i = 0; i < mono_interp_op_sregs [opcode]; i++) {
14931496
if (ins->sregs [i] == MINT_CALL_ARGS_SREG) {
1494-
g_print (" c:");
1497+
g_string_append_printf (str, " c:");
14951498
int *call_args = ins->info.call_args;
14961499
if (call_args) {
14971500
while (*call_args != -1) {
1498-
g_print (" %d", *call_args);
1501+
g_string_append_printf (str, " %d", *call_args);
14991502
call_args++;
15001503
}
15011504
}
15021505
} else {
1503-
g_print (" %d", ins->sregs [i]);
1506+
g_string_append_printf (str, " %d", ins->sregs [i]);
15041507
}
15051508
}
1506-
g_print ("],");
1509+
g_string_append_printf (str, "],");
15071510
} else {
1508-
g_print (" nil],");
1511+
g_string_append_printf (str, " nil],");
15091512
}
15101513

15111514
if (opcode == MINT_LDLOCA_S) {
15121515
// LDLOCA has special semantics, it has data in sregs [0], but it doesn't have any sregs
1513-
g_print (" %d", ins->sregs [0]);
1516+
g_string_append_printf (str, " %d", ins->sregs [0]);
15141517
} else {
15151518
char *descr = dump_interp_ins_data (ins, ins->il_offset, &ins->data [0], ins->opcode);
1516-
g_print ("%s", descr);
1519+
g_string_append_printf (str, "%s", descr);
15171520
g_free (descr);
15181521
}
1519-
}
1520-
1521-
static void
1522-
dump_interp_inst (InterpInst *ins)
1523-
{
1524-
dump_interp_inst_no_newline (ins);
1525-
g_print ("\n");
1522+
g_print ("%s\n", str->str);
1523+
g_string_free (str, TRUE);
15261524
}
15271525

15281526
static G_GNUC_UNUSED void
@@ -1581,21 +1579,6 @@ interp_method_get_header (MonoMethod* method, MonoError *error)
15811579
return mono_method_get_header_internal (method, error);
15821580
}
15831581

1584-
/* stores top of stack as local and pushes address of it on stack */
1585-
static void
1586-
emit_store_value_as_local (TransformData *td, MonoType *src)
1587-
{
1588-
int local = create_interp_local (td, mini_native_type_replace_type (src));
1589-
1590-
store_local (td, local);
1591-
1592-
interp_add_ins (td, MINT_LDLOCA_S);
1593-
push_simple_type (td, STACK_TYPE_MP);
1594-
interp_ins_set_dreg (td->last_ins, td->sp [-1].local);
1595-
interp_ins_set_sreg (td->last_ins, local);
1596-
td->locals [local].indirects++;
1597-
}
1598-
15991582
static gboolean
16001583
interp_ip_in_cbb (TransformData *td, int il_offset)
16011584
{
@@ -1906,37 +1889,33 @@ interp_handle_magic_type_intrinsics (TransformData *td, MonoMethod *target_metho
19061889
int src_size = mini_magic_type_size (NULL, src);
19071890
int dst_size = mini_magic_type_size (NULL, dst);
19081891

1909-
gboolean store_value_as_local = FALSE;
1892+
gboolean managed_fallback = FALSE;
19101893

19111894
switch (type_index) {
19121895
case 0: case 1:
19131896
if (!mini_magic_is_int_type (src) || !mini_magic_is_int_type (dst)) {
19141897
if (mini_magic_is_int_type (src))
1915-
store_value_as_local = TRUE;
1898+
managed_fallback = TRUE;
19161899
else if (mono_class_is_magic_float (src_klass))
1917-
store_value_as_local = TRUE;
1900+
managed_fallback = TRUE;
19181901
else
19191902
return FALSE;
19201903
}
19211904
break;
19221905
case 2:
19231906
if (!mini_magic_is_float_type (src) || !mini_magic_is_float_type (dst)) {
19241907
if (mini_magic_is_float_type (src))
1925-
store_value_as_local = TRUE;
1908+
managed_fallback = TRUE;
19261909
else if (mono_class_is_magic_int (src_klass))
1927-
store_value_as_local = TRUE;
1910+
managed_fallback = TRUE;
19281911
else
19291912
return FALSE;
19301913
}
19311914
break;
19321915
}
19331916

1934-
if (store_value_as_local) {
1935-
emit_store_value_as_local (td, src);
1936-
1937-
/* emit call to managed conversion method */
1917+
if (managed_fallback)
19381918
return FALSE;
1939-
}
19401919

19411920
if (src_size > dst_size) { // 8 -> 4
19421921
switch (type_index) {
@@ -1993,15 +1972,6 @@ interp_handle_magic_type_intrinsics (TransformData *td, MonoMethod *target_metho
19931972
td->ip += 5;
19941973
return TRUE;
19951974
} else if (!strcmp ("CompareTo", tm) || !strcmp ("Equals", tm)) {
1996-
MonoType *arg = csignature->params [0];
1997-
int mt = mint_type (arg);
1998-
1999-
/* on 'System.n*::{CompareTo,Equals} (System.n*)' variant we need to push managed
2000-
* pointer instead of value */
2001-
if (mt != MINT_TYPE_O)
2002-
emit_store_value_as_local (td, arg);
2003-
2004-
/* emit call to managed conversion method */
20051975
return FALSE;
20061976
} else if (!strcmp (".cctor", tm)) {
20071977
return FALSE;
@@ -2836,8 +2806,7 @@ interp_method_check_inlining (TransformData *td, MonoMethod *method, MonoMethodS
28362806
if (method->wrapper_type != MONO_WRAPPER_NONE)
28372807
return FALSE;
28382808

2839-
/* Our usage of `emit_store_value_as_local ()` for nint, nuint and nfloat
2840-
* is kinda hacky, and doesn't work with the inliner */
2809+
// FIXME Re-enable this
28412810
if (mono_class_get_magic_index (method->klass) >= 0)
28422811
return FALSE;
28432812

@@ -6059,6 +6028,8 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
60596028
td->sp--;
60606029
interp_emit_sfld_access (td, field, field_klass, mt, TRUE, error);
60616030
goto_if_nok (error, exit);
6031+
} else if (td->sp [-1].type != STACK_TYPE_O && td->sp [-1].type != STACK_TYPE_MP && (mono_class_is_magic_int (klass) || mono_class_is_magic_float (klass))) {
6032+
// No need to load anything, the value is already on the execution stack
60626033
} else if (td->sp [-1].type == STACK_TYPE_VT) {
60636034
int size = 0;
60646035
/* First we pop the vt object from the stack. Then we push the field */

0 commit comments

Comments
 (0)