From 96cb163f32f138fa6a2f018084ff6d90a942683d Mon Sep 17 00:00:00 2001 From: monojenkins Date: Thu, 19 Mar 2020 04:37:37 -0400 Subject: [PATCH] [interp] Optimize out intptr ctor (#33720) Co-authored-by: BrzVlad --- src/mono/mono/mini/interp/transform.c | 364 ++++++++++++++++++---------------- 1 file changed, 191 insertions(+), 173 deletions(-) diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index 03b4e98..76d15a0 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -1176,224 +1176,231 @@ interp_emit_ldelema (TransformData *td, MonoClass *array_class, MonoClass *check SET_SIMPLE_TYPE (td->sp - 1, STACK_TYPE_MP); } -/* Return TRUE if call transformation is finished */ static gboolean -interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClass *constrained_class, MonoMethodSignature *csignature, gboolean readonly, int *op) +interp_handle_magic_type_intrinsics (TransformData *td, MonoMethod *target_method, MonoMethodSignature *csignature, int type_index) { + MonoClass *magic_class = target_method->klass; const char *tm = target_method->name; int i; - int type_index = mono_class_get_magic_index (target_method->klass); - gboolean in_corlib = m_class_get_image (target_method->klass) == mono_defaults.corlib; - const char *klass_name_space = m_class_get_name_space (target_method->klass); - const char *klass_name = m_class_get_name (target_method->klass); - if (target_method->klass == mono_defaults.string_class) { - if (tm [0] == 'g') { - if (strcmp (tm, "get_Chars") == 0) - *op = MINT_GETCHR; - else if (strcmp (tm, "get_Length") == 0) - *op = MINT_STRLEN; - } - } else if (type_index >= 0) { - MonoClass *magic_class = target_method->klass; - - const int mt = mint_type (m_class_get_byval_arg (magic_class)); - if (!strcmp (".ctor", tm)) { - MonoType *arg = csignature->params [0]; - /* depending on SIZEOF_VOID_P and the type of the value passed to the .ctor we either have to CONV it, or do nothing */ - int arg_size = mini_magic_type_size (NULL, arg); + const int mt = mint_type (m_class_get_byval_arg (magic_class)); + if (!strcmp (".ctor", tm)) { + MonoType *arg = csignature->params [0]; + /* depending on SIZEOF_VOID_P and the type of the value passed to the .ctor we either have to CONV it, or do nothing */ + int arg_size = mini_magic_type_size (NULL, arg); - if (arg_size > SIZEOF_VOID_P) { // 8 -> 4 - switch (type_index) { - case 0: case 1: - interp_add_ins (td, MINT_CONV_I4_I8); - break; - case 2: - interp_add_ins (td, MINT_CONV_R4_R8); - break; - } + if (arg_size > SIZEOF_VOID_P) { // 8 -> 4 + switch (type_index) { + case 0: case 1: + interp_add_ins (td, MINT_CONV_I4_I8); + break; + case 2: + interp_add_ins (td, MINT_CONV_R4_R8); + break; } + } - if (arg_size < SIZEOF_VOID_P) { // 4 -> 8 - switch (type_index) { - case 0: - interp_add_ins (td, MINT_CONV_I8_I4); - break; - case 1: - interp_add_ins (td, MINT_CONV_I8_U4); - break; - case 2: - interp_add_ins (td, MINT_CONV_R8_R4); - break; - } + if (arg_size < SIZEOF_VOID_P) { // 4 -> 8 + switch (type_index) { + case 0: + interp_add_ins (td, MINT_CONV_I8_I4); + break; + case 1: + interp_add_ins (td, MINT_CONV_I8_U4); + break; + case 2: + interp_add_ins (td, MINT_CONV_R8_R4); + break; } + } - switch (type_index) { - case 0: case 1: + switch (type_index) { + case 0: case 1: #if SIZEOF_VOID_P == 4 - interp_add_ins (td, MINT_STIND_I4); + interp_add_ins (td, MINT_STIND_I4); #else - interp_add_ins (td, MINT_STIND_I8); + interp_add_ins (td, MINT_STIND_I8); #endif - break; - case 2: + break; + case 2: #if SIZEOF_VOID_P == 4 - interp_add_ins (td, MINT_STIND_R4); + interp_add_ins (td, MINT_STIND_R4); #else - interp_add_ins (td, MINT_STIND_R8); + interp_add_ins (td, MINT_STIND_R8); #endif - break; + break; + } + + td->sp -= 2; + td->ip += 5; + return TRUE; + } else if (!strcmp ("op_Implicit", tm ) || !strcmp ("op_Explicit", tm)) { + MonoType *src = csignature->params [0]; + MonoType *dst = csignature->ret; + MonoClass *src_klass = mono_class_from_mono_type_internal (src); + int src_size = mini_magic_type_size (NULL, src); + int dst_size = mini_magic_type_size (NULL, dst); + + gboolean store_value_as_local = FALSE; + + switch (type_index) { + case 0: case 1: + if (!mini_magic_is_int_type (src) || !mini_magic_is_int_type (dst)) { + if (mini_magic_is_int_type (src)) + store_value_as_local = TRUE; + else if (mono_class_is_magic_float (src_klass)) + store_value_as_local = TRUE; + else + return FALSE; } + break; + case 2: + if (!mini_magic_is_float_type (src) || !mini_magic_is_float_type (dst)) { + if (mini_magic_is_float_type (src)) + store_value_as_local = TRUE; + else if (mono_class_is_magic_int (src_klass)) + store_value_as_local = TRUE; + else + return FALSE; + } + break; + } - td->sp -= 2; - td->ip += 5; - return TRUE; - } else if (!strcmp ("op_Implicit", tm ) || !strcmp ("op_Explicit", tm)) { - MonoType *src = csignature->params [0]; - MonoType *dst = csignature->ret; - MonoClass *src_klass = mono_class_from_mono_type_internal (src); - int src_size = mini_magic_type_size (NULL, src); - int dst_size = mini_magic_type_size (NULL, dst); + if (store_value_as_local) { + emit_store_value_as_local (td, src); - gboolean store_value_as_local = FALSE; + /* emit call to managed conversion method */ + return FALSE; + } + if (src_size > dst_size) { // 8 -> 4 switch (type_index) { case 0: case 1: - if (!mini_magic_is_int_type (src) || !mini_magic_is_int_type (dst)) { - if (mini_magic_is_int_type (src)) - store_value_as_local = TRUE; - else if (mono_class_is_magic_float (src_klass)) - store_value_as_local = TRUE; - else - return FALSE; - } + interp_add_ins (td, MINT_CONV_I4_I8); break; case 2: - if (!mini_magic_is_float_type (src) || !mini_magic_is_float_type (dst)) { - if (mini_magic_is_float_type (src)) - store_value_as_local = TRUE; - else if (mono_class_is_magic_int (src_klass)) - store_value_as_local = TRUE; - else - return FALSE; - } + interp_add_ins (td, MINT_CONV_R4_R8); break; } + } - if (store_value_as_local) { - emit_store_value_as_local (td, src); - - /* emit call to managed conversion method */ - return FALSE; - } - - if (src_size > dst_size) { // 8 -> 4 - switch (type_index) { - case 0: case 1: - interp_add_ins (td, MINT_CONV_I4_I8); - break; - case 2: - interp_add_ins (td, MINT_CONV_R4_R8); - break; - } - } - - if (src_size < dst_size) { // 4 -> 8 - switch (type_index) { - case 0: - interp_add_ins (td, MINT_CONV_I8_I4); - break; - case 1: - interp_add_ins (td, MINT_CONV_I8_U4); - break; - case 2: - interp_add_ins (td, MINT_CONV_R8_R4); - break; - } + if (src_size < dst_size) { // 4 -> 8 + switch (type_index) { + case 0: + interp_add_ins (td, MINT_CONV_I8_I4); + break; + case 1: + interp_add_ins (td, MINT_CONV_I8_U4); + break; + case 2: + interp_add_ins (td, MINT_CONV_R8_R4); + break; } + } - SET_TYPE (td->sp - 1, stack_type [mint_type (dst)], mono_class_from_mono_type_internal (dst)); - td->ip += 5; - return TRUE; - } else if (!strcmp ("op_Increment", tm)) { - g_assert (type_index != 2); // no nfloat + SET_TYPE (td->sp - 1, stack_type [mint_type (dst)], mono_class_from_mono_type_internal (dst)); + td->ip += 5; + return TRUE; + } else if (!strcmp ("op_Increment", tm)) { + g_assert (type_index != 2); // no nfloat #if SIZEOF_VOID_P == 8 - interp_add_ins (td, MINT_ADD1_I8); + interp_add_ins (td, MINT_ADD1_I8); #else - interp_add_ins (td, MINT_ADD1_I4); + interp_add_ins (td, MINT_ADD1_I4); #endif - SET_TYPE (td->sp - 1, stack_type [mt], magic_class); - td->ip += 5; - return TRUE; - } else if (!strcmp ("op_Decrement", tm)) { - g_assert (type_index != 2); // no nfloat + SET_TYPE (td->sp - 1, stack_type [mt], magic_class); + td->ip += 5; + return TRUE; + } else if (!strcmp ("op_Decrement", tm)) { + g_assert (type_index != 2); // no nfloat #if SIZEOF_VOID_P == 8 - interp_add_ins (td, MINT_SUB1_I8); + interp_add_ins (td, MINT_SUB1_I8); #else - interp_add_ins (td, MINT_SUB1_I4); + interp_add_ins (td, MINT_SUB1_I4); #endif + SET_TYPE (td->sp - 1, stack_type [mt], magic_class); + td->ip += 5; + return TRUE; + } else if (!strcmp ("CompareTo", tm) || !strcmp ("Equals", tm)) { + MonoType *arg = csignature->params [0]; + + /* on 'System.n*::{CompareTo,Equals} (System.n*)' variant we need to push managed + * pointer instead of value */ + if (arg->type == MONO_TYPE_VALUETYPE) + emit_store_value_as_local (td, arg); + + /* emit call to managed conversion method */ + return FALSE; + } else if (!strcmp (".cctor", tm)) { + /* white list */ + return FALSE; + } else if (!strcmp ("Parse", tm)) { + /* white list */ + return FALSE; + } else if (!strcmp ("ToString", tm)) { + /* white list */ + return FALSE; + } else if (!strcmp ("GetHashCode", tm)) { + /* white list */ + return FALSE; + } else if (!strcmp ("IsNaN", tm) || !strcmp ("IsInfinity", tm) || !strcmp ("IsNegativeInfinity", tm) || !strcmp ("IsPositiveInfinity", tm)) { + g_assert (type_index == 2); // nfloat only + /* white list */ + return FALSE; + } + + for (i = 0; i < sizeof (int_unnop) / sizeof (MagicIntrinsic); ++i) { + if (!strcmp (int_unnop [i].op_name, tm)) { + interp_add_ins (td, int_unnop [i].insn [type_index]); SET_TYPE (td->sp - 1, stack_type [mt], magic_class); td->ip += 5; return TRUE; - } else if (!strcmp ("CompareTo", tm) || !strcmp ("Equals", tm)) { - MonoType *arg = csignature->params [0]; - - /* on 'System.n*::{CompareTo,Equals} (System.n*)' variant we need to push managed - * pointer instead of value */ - if (arg->type == MONO_TYPE_VALUETYPE) - emit_store_value_as_local (td, arg); - - /* emit call to managed conversion method */ - return FALSE; - } else if (!strcmp (".cctor", tm)) { - /* white list */ - return FALSE; - } else if (!strcmp ("Parse", tm)) { - /* white list */ - return FALSE; - } else if (!strcmp ("ToString", tm)) { - /* white list */ - return FALSE; - } else if (!strcmp ("GetHashCode", tm)) { - /* white list */ - return FALSE; - } else if (!strcmp ("IsNaN", tm) || !strcmp ("IsInfinity", tm) || !strcmp ("IsNegativeInfinity", tm) || !strcmp ("IsPositiveInfinity", tm)) { - g_assert (type_index == 2); // nfloat only - /* white list */ - return FALSE; } + } - for (i = 0; i < sizeof (int_unnop) / sizeof (MagicIntrinsic); ++i) { - if (!strcmp (int_unnop [i].op_name, tm)) { - interp_add_ins (td, int_unnop [i].insn [type_index]); - SET_TYPE (td->sp - 1, stack_type [mt], magic_class); - td->ip += 5; - return TRUE; - } + for (i = 0; i < sizeof (int_binop) / sizeof (MagicIntrinsic); ++i) { + if (!strcmp (int_binop [i].op_name, tm)) { + interp_add_ins (td, int_binop [i].insn [type_index]); + td->sp -= 1; + SET_TYPE (td->sp - 1, stack_type [mt], magic_class); + td->ip += 5; + return TRUE; } + } - for (i = 0; i < sizeof (int_binop) / sizeof (MagicIntrinsic); ++i) { - if (!strcmp (int_binop [i].op_name, tm)) { - interp_add_ins (td, int_binop [i].insn [type_index]); - td->sp -= 1; - SET_TYPE (td->sp - 1, stack_type [mt], magic_class); - td->ip += 5; - return TRUE; - } + for (i = 0; i < sizeof (int_cmpop) / sizeof (MagicIntrinsic); ++i) { + if (!strcmp (int_cmpop [i].op_name, tm)) { + MonoClass *k = mono_defaults.boolean_class; + interp_add_ins (td, int_cmpop [i].insn [type_index]); + td->sp -= 1; + SET_TYPE (td->sp - 1, stack_type [mint_type (m_class_get_byval_arg (k))], k); + td->ip += 5; + return TRUE; } + } - for (i = 0; i < sizeof (int_cmpop) / sizeof (MagicIntrinsic); ++i) { - if (!strcmp (int_cmpop [i].op_name, tm)) { - MonoClass *k = mono_defaults.boolean_class; - interp_add_ins (td, int_cmpop [i].insn [type_index]); - td->sp -= 1; - SET_TYPE (td->sp - 1, stack_type [mint_type (m_class_get_byval_arg (k))], k); - td->ip += 5; - return TRUE; - } - } + g_error ("TODO: interp_transform_call %s:%s", m_class_get_name (target_method->klass), tm); +} - g_error ("TODO: interp_transform_call %s:%s", m_class_get_name (target_method->klass), tm); +/* Return TRUE if call transformation is finished */ +static gboolean +interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClass *constrained_class, MonoMethodSignature *csignature, gboolean readonly, int *op) +{ + const char *tm = target_method->name; + int type_index = mono_class_get_magic_index (target_method->klass); + gboolean in_corlib = m_class_get_image (target_method->klass) == mono_defaults.corlib; + const char *klass_name_space = m_class_get_name_space (target_method->klass); + const char *klass_name = m_class_get_name (target_method->klass); + + if (target_method->klass == mono_defaults.string_class) { + if (tm [0] == 'g') { + if (strcmp (tm, "get_Chars") == 0) + *op = MINT_GETCHR; + else if (strcmp (tm, "get_Length") == 0) + *op = MINT_STRLEN; + } + } else if (type_index >= 0) { + return interp_handle_magic_type_intrinsics (td, target_method, csignature, type_index); } else if (mono_class_is_subclass_of_internal (target_method->klass, mono_defaults.array_class, FALSE)) { if (!strcmp (tm, "get_Rank")) { *op = MINT_ARRAY_RANK; @@ -4564,6 +4571,17 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, goto_if_nok (error, exit); PUSH_TYPE (td, stack_type [mint_type (m_class_get_byval_arg (klass))], klass); + } else if (klass == mono_defaults.int_class && csignature->param_count == 1) { + td->sp--; +#if SIZEOF_VOID_P == 8 + if (td->sp [0].type == STACK_TYPE_I4) + interp_add_ins (td, MINT_CONV_I8_I4); +#else + if (td->sp [0].type == STACK_TYPE_I8) + interp_add_ins (td, MINT_CONV_OVF_I4_I8); +#endif + + PUSH_TYPE (td, stack_type [mint_type (m_class_get_byval_arg (klass))], klass); } else { if (m_class_get_parent (klass) == mono_defaults.array_class) { interp_add_ins (td, MINT_NEWOBJ_ARRAY); -- 2.7.4