2010-03-06 Rodrigo Kumpera <rkumpera@novell.com>
authorRodrigo Kumpera <kumpera@gmail.com>
Sun, 7 Mar 2010 20:18:02 +0000 (20:18 -0000)
committerRodrigo Kumpera <kumpera@gmail.com>
Sun, 7 Mar 2010 20:18:02 +0000 (20:18 -0000)
* method-to-ir.c: Generate better code for the NewObject
intrinsic.

svn path=/trunk/mono/; revision=153222

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

index 796b333f939532e3e503e3aff9a0abca8553a306..c440acb64a926d1ca38de5155cac3e1eb9ab78ec 100755 (executable)
@@ -1,3 +1,8 @@
+2010-03-07  Rodrigo Kumpera  <rkumpera@novell.com>
+
+       * method-to-ir.c: Generate better code for the NewObject
+       intrinsic.
+       
 2010-03-07  Zoltan Varga  <vargaz@gmail.com>
 
        * branch-opts.c (mono_if_conversion): Disable one of the cases when deadce
index 7821351e3364eb1b41b32f5d7150d8b9e0971e0a..756f68432f6580bcaed12cb7fcb7cf101b6d6a65 100644 (file)
@@ -8770,37 +8770,59 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 
                                EMIT_NEW_TEMPLOAD (cfg, ins, vtvar->inst_c0);
                        } else {
+                               gboolean use_slow_path = TRUE;
                                if ((ip + 5 < end) && ip_in_bb (cfg, bblock, ip + 5) && 
                                        ((ip [5] == CEE_CALL) || (ip [5] == CEE_CALLVIRT)) && 
-                                       (cmethod = mini_get_method (cfg, method, read32 (ip + 6), NULL, generic_context)) &&
-                                       (cmethod->klass == mono_defaults.monotype_class->parent) &&
-                                       (strcmp (cmethod->name, "GetTypeFromHandle") == 0)) {
-                                       MonoClass *tclass = mono_class_from_mono_type (handle);
+                                       (cmethod = mini_get_method (cfg, method, read32 (ip + 6), NULL, generic_context))) {
 
-                                       mono_class_init (tclass);
-                                       if (context_used) {
-                                               ins = emit_get_rgctx_klass (cfg, context_used,
-                                                       tclass, MONO_RGCTX_INFO_REFLECTION_TYPE);
-                                       } else if (cfg->compile_aot) {
-                                               if (method->wrapper_type) {
-                                                       if (mono_class_get (tclass->image, tclass->type_token) == tclass && !generic_context) {
-                                                               /* Special case for static synchronized wrappers */
-                                                               EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, tclass->image, tclass->type_token, generic_context);
+                                       if ((cmethod->klass == mono_defaults.monotype_class->parent) && (strcmp (cmethod->name, "GetTypeFromHandle") == 0)) {
+                                               MonoClass *tclass = mono_class_from_mono_type (handle);
+
+                                               mono_class_init (tclass);
+                                               if (context_used) {
+                                                       ins = emit_get_rgctx_klass (cfg, context_used,
+                                                               tclass, MONO_RGCTX_INFO_REFLECTION_TYPE);
+                                               } else if (cfg->compile_aot) {
+                                                       if (method->wrapper_type) {
+                                                               if (mono_class_get (tclass->image, tclass->type_token) == tclass && !generic_context) {
+                                                                       /* Special case for static synchronized wrappers */
+                                                                       EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, tclass->image, tclass->type_token, generic_context);
+                                                               } else {
+                                                                       /* FIXME: n is not a normal token */
+                                                                       cfg->disable_aot = TRUE;
+                                                                       EMIT_NEW_PCONST (cfg, ins, NULL);
+                                                               }
                                                        } else {
-                                                               /* FIXME: n is not a normal token */
-                                                               cfg->disable_aot = TRUE;
-                                                               EMIT_NEW_PCONST (cfg, ins, NULL);
+                                                               EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, image, n, generic_context);
                                                        }
                                                } else {
-                                                       EMIT_NEW_TYPE_FROM_HANDLE_CONST (cfg, ins, image, n, generic_context);
+                                                       EMIT_NEW_PCONST (cfg, ins, mono_type_get_object (cfg->domain, handle));
+                                               }
+                                               ins->type = STACK_OBJ;
+                                               ins->klass = cmethod->klass;
+                                               ip += 5;
+                                               use_slow_path = FALSE;
+                                       } else if (cmethod->klass->image == mono_defaults.corlib &&
+                                                               !strcmp ("Mono", cmethod->klass->name_space) &&
+                                                               !strcmp ("Runtime", cmethod->klass->name) &&
+                                                               !strcmp ("NewObject", cmethod->name)) {
+
+                                               /*FIXME relax those restrictions if it's worth the trouble*/
+                                               if (!context_used && !cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED)) {
+                                                       MonoClass *klass = mono_class_from_mono_type (handle);
+                                                       gpointer vtable = mono_class_vtable (cfg->domain, klass);
+                                                       MonoInst *iargs [1];
+
+                                                       EMIT_NEW_PCONST (cfg, iargs [0], vtable);
+                                                       ins = mono_emit_jit_icall (cfg, mono_object_new_specific, iargs);
+
+                                                       ip += 5;
+                                                       use_slow_path = FALSE;
                                                }
-                                       } else {
-                                               EMIT_NEW_PCONST (cfg, ins, mono_type_get_object (cfg->domain, handle));
                                        }
-                                       ins->type = STACK_OBJ;
-                                       ins->klass = cmethod->klass;
-                                       ip += 5;
-                               } else {
+                               }
+
+                               if (use_slow_path) {
                                        MonoInst *addr, *vtvar;
 
                                        vtvar = mono_compile_create_var (cfg, &handle_class->byval_arg, OP_LOCAL);