Optimize typeof(T).IsValueType (mono/mono#18307)
authorEgor Bogatov <egorbo@gmail.com>
Tue, 14 Jan 2020 15:37:16 +0000 (18:37 +0300)
committerLarry Ewing <lewing@microsoft.com>
Tue, 14 Jan 2020 15:37:16 +0000 (09:37 -0600)
* Optimize Type.IsValueType

* Ignore gsharedvt types

* use mini_is_gsharedvt_variable_klass

* test

* fix build

Commit migrated from https://github.com/mono/mono/commit/08bb5660f6b2cc87ec59fb77c01a1f8cdeda183f

src/mono/mono/mini/method-to-ir.c

index eb4ea0a..e5190cf 100644 (file)
@@ -10085,6 +10085,24 @@ field_access_end:
                                        MonoClass *tclass = mono_class_from_mono_type_internal ((MonoType *)handle);
 
                                        mono_class_init_internal (tclass);
+
+                                       // Optimize to true/false if next instruction is `call instance bool Type::get_IsValueType()`
+                                       guchar *is_vt_ip;
+                                       guint32 is_vt_token;
+                                       if ((is_vt_ip = il_read_call (next_ip + 5, end, &is_vt_token)) && ip_in_bb (cfg, cfg->cbb, is_vt_ip)) {
+                                               MonoMethod *is_vt_method = mini_get_method (cfg, method, is_vt_token, NULL, generic_context);
+                                               if (is_vt_method->klass == mono_defaults.systemtype_class &&
+                                                       !mini_is_gsharedvt_variable_klass (tclass) &&
+                                                       !mono_class_is_open_constructed_type (m_class_get_byval_arg (tclass)) &&
+                                                       !strcmp ("get_IsValueType", is_vt_method->name)) {
+                                                       next_ip = is_vt_ip;
+                                                       EMIT_NEW_ICONST (cfg, ins, m_class_is_valuetype (tclass) ? 1 : 0);
+                                                       ins->type = STACK_I4;
+                                                       *sp++ = ins;
+                                                       break;
+                                               }
+                                       }
+
                                        if (context_used) {
                                                ins = mini_emit_get_rgctx_klass (cfg, context_used,
                                                        tclass, MONO_RGCTX_INFO_REFLECTION_TYPE);