Merge pull request #2870 from madewokherd/arginfo
authormonojenkins <jo.shields+jenkins@xamarin.com>
Tue, 12 Apr 2016 03:45:27 +0000 (04:45 +0100)
committermonojenkins <jo.shields+jenkins@xamarin.com>
Tue, 12 Apr 2016 03:45:27 +0000 (04:45 +0100)
x86 cleanups for register arguments

Best I can tell, cinfo->args and cfg->args need to be independent before implementing calling conventions where some arguments are in registers, at least if we want to do it cleanly. Also, storing the argument offset in a cfg->args instruction that claims to be for a register seems hacky and confusing to me.

mono/metadata/cominterop.c
mono/metadata/marshal.c
mono/mini/driver.c
mono/sgen/sgen-marksweep.c

index 08450558d9d27e9998da65efb7ea26943303570f..3ebe507d0d185472c7aada8bed2713c8b11847df 100644 (file)
@@ -622,6 +622,7 @@ mono_cominterop_cleanup (void)
 void
 mono_mb_emit_cominterop_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethod* method)
 {
+#ifndef DISABLE_JIT
        // get function pointer from 1st arg, the COM interface pointer
        mono_mb_emit_ldarg (mb, 0);
        mono_mb_emit_icon (mb, cominterop_get_com_slot_for_method (method));
@@ -632,11 +633,13 @@ mono_mb_emit_cominterop_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, M
        mono_mb_emit_calli (mb, sig);
        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
        mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
+#endif /* DISABLE_JIT */
 }
 
 void
 mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec)
 {
+#ifndef DISABLE_JIT
        switch (conv) {
        case MONO_MARSHAL_CONV_OBJECT_INTERFACE:
        case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN:
@@ -708,11 +711,13 @@ mono_cominterop_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type,
        default:
                g_assert_not_reached ();
        }
+#endif /* DISABLE_JIT */
 }
 
 void
 mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec)
 {
+#ifndef DISABLE_JIT
        switch (conv) {
        case MONO_MARSHAL_CONV_OBJECT_INTERFACE:
        case MONO_MARSHAL_CONV_OBJECT_IDISPATCH:
@@ -800,6 +805,7 @@ mono_cominterop_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type,
        default:
                g_assert_not_reached ();
        }
+#endif /* DISABLE_JIT */
 }
 
 /**
@@ -936,6 +942,7 @@ mono_cominterop_get_native_wrapper (MonoMethod *method)
        sig = mono_method_signature (method);
        mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP);
 
+#ifndef DISABLE_JIT
        /* if method klass is import, that means method
         * is really a com call. let interop system emit it.
        */
@@ -1009,6 +1016,8 @@ mono_cominterop_get_native_wrapper (MonoMethod *method)
                        imported classes is not yet implemented.");
                mono_mb_emit_exception (mb, "NotSupportedException", msg);
        }
+#endif /* DISABLE_JIT */
+
        csig = mono_metadata_signature_dup_full (method->klass->image, sig);
        csig->pinvoke = 0;
        res = mono_mb_create_and_cache (cache, method,
@@ -1048,6 +1057,7 @@ mono_cominterop_get_invoke (MonoMethod *method)
 
        mb = mono_mb_new (method->klass, method->name, MONO_WRAPPER_COMINTEROP_INVOKE);
 
+#ifndef DISABLE_JIT
        /* get real proxy object, which is a ComInteropProxy in this case*/
        mono_mb_add_local (mb, &mono_defaults.object_class->byval_arg);
        mono_mb_emit_ldarg (mb, 0);
@@ -1088,6 +1098,7 @@ mono_cominterop_get_invoke (MonoMethod *method)
        mono_marshal_emit_thread_interrupt_checkpoint (mb);
 
        mono_mb_emit_byte (mb, CEE_RET);
+#endif /* DISABLE_JIT */
 
        res = mono_mb_create_and_cache (cache, method, mb, sig, sig->param_count + 16);
        mono_mb_free (mb);
@@ -1142,6 +1153,18 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum,
        if (!marshal_release)
                marshal_release = mono_class_get_method_from_name (mono_defaults.marshal_class, "Release", 1);
 
+#ifdef DISABLE_JIT
+       switch (action) {
+       case MARSHAL_ACTION_CONV_IN:
+               *conv_arg_type = &mono_defaults.int_class->byval_arg;
+               break;
+       case MARSHAL_ACTION_MANAGED_CONV_IN:
+               *conv_arg_type = &mono_defaults.int_class->byval_arg;
+               break;
+       default:
+               break;
+       }
+#else
        switch (action) {
        case MARSHAL_ACTION_CONV_IN: {
                guint32 pos_null = 0;
@@ -1428,6 +1451,7 @@ mono_cominterop_emit_marshal_com_interface (EmitMarshalContext *m, int argnum,
        default:
                g_assert_not_reached ();
        }
+#endif /* DISABLE_JIT */
 
        return conv_arg;
 }
@@ -2077,8 +2101,10 @@ cominterop_get_ccw_checked (MonoObject* object, MonoClass* itf, MonoError *error
                                mspecs [0] = NULL;
                        }
 
+#ifndef DISABLE_JIT
                        /* skip visiblity since we call internal methods */
                        mb->skip_visibility = TRUE;
+#endif
 
                        cominterop_setup_marshal_context (&m, adjust_method);
                        m.mb = mb;
@@ -2089,7 +2115,6 @@ cominterop_get_ccw_checked (MonoObject* object, MonoClass* itf, MonoError *error
 
                        vtable [vtable_index--] = mono_compile_method (wrapper_method);
 
-                       
                        for (param_index = sig_adjusted->param_count; param_index >= 0; param_index--)
                                if (mspecs [param_index])
                                        mono_metadata_free_marshal_spec (mspecs [param_index]);
@@ -2249,9 +2274,9 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method)
 
        mspecs [0] = NULL;
 
-       if (!preserve_sig) {
+#ifndef DISABLE_JIT
+       if (!preserve_sig)
                hr = mono_mb_add_local (mb, &mono_defaults.int32_class->byval_arg);
-       }
        else if (!MONO_TYPE_IS_VOID (sig->ret))
                hr = mono_mb_add_local (mb, sig->ret);
 
@@ -2315,6 +2340,7 @@ cominterop_get_managed_wrapper_adjusted (MonoMethod *method)
                mono_mb_emit_ldloc (mb, hr);
 
        mono_mb_emit_byte (mb, CEE_RET);
+#endif /* DISABLE_JIT */
 
        mono_cominterop_lock ();
        res = mono_mb_create_method (mb, sig_native, sig_native->param_count + 16);     
@@ -2806,10 +2832,9 @@ mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoT
 {
        MonoMethodBuilder *mb = m->mb;
 
+#ifndef DISABLE_JIT
        switch (action) {
-
        case MARSHAL_ACTION_CONV_IN: {
-
                if (t->attrs & PARAM_ATTRIBUTE_IN) {
 
                        /* Generates IL code for the following algorithm:
@@ -2923,7 +2948,6 @@ mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoT
                break;
 
        case MARSHAL_ACTION_CONV_OUT: {
-
                if (t->attrs & PARAM_ATTRIBUTE_OUT) {
                        /* Generates IL code for the following algorithm:
 
@@ -3041,6 +3065,7 @@ mono_cominterop_emit_marshal_safearray (EmitMarshalContext *m, int argnum, MonoT
        default:
                g_assert_not_reached ();
        }
+#endif /* DISABLE_JIT */
 
        return conv_arg;
 }
index a847b0f58624a0587765b4bd6e526bda2787d1d6..3d4e8146decc3263d8a87bbba9a445e391fcfb57 100644 (file)
@@ -7163,10 +7163,12 @@ emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t,
                return emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action);
        case MONO_TYPE_CLASS:
        case MONO_TYPE_OBJECT:
-#ifndef DISABLE_COM
+#if !defined(DISABLE_COM) && !defined(DISABLE_JIT)
                if (spec && spec->native == MONO_NATIVE_STRUCT)
                        return emit_marshal_variant (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+#endif
 
+#if !defined(DISABLE_COM)
                if (spec && (spec->native == MONO_NATIVE_IUNKNOWN ||
                        spec->native == MONO_NATIVE_IDISPATCH ||
                        spec->native == MONO_NATIVE_INTERFACE))
index e39a941023491c1b34581a32ef7f7e3db9789cd6..dd5800be728affba67579b0669a00558cdf9e00f 100644 (file)
@@ -1637,19 +1637,6 @@ mono_main (int argc, char* argv[])
                        gc_descr = mono_gc_get_description ();
                        g_print ("\tGC:            %s\n", gc_descr);
                        g_free (gc_descr);
-                       if (mini_verbose) {
-                               const char *cerror;
-                               const char *clibpath;
-                               mono_init ("mono");
-                               cerror = mono_check_corlib_version ();
-                               clibpath = mono_defaults.corlib? mono_image_get_filename (mono_defaults.corlib): "unknown";
-                               if (cerror) {
-                                       g_print ("The currently installed mscorlib doesn't match this runtime version.\n");
-                                       g_print ("The error is: %s\n", cerror);
-                                       g_print ("mscorlib.dll loaded at: %s\n", clibpath);
-                                       return 1;
-                               }
-                       }
                        return 0;
                } else if (strcmp (argv [i], "--help") == 0 || strcmp (argv [i], "-h") == 0) {
                        mini_usage ();
index 5f4f149a3f4a35bc5e26a67b9120de1ede78c49f..38e127b8cd541fe4b304adf4f3e91d19135265db 100644 (file)
@@ -99,6 +99,7 @@ struct _MSBlockInfo {
        guint16 obj_size_index;
        /* FIXME: Reduce this - it only needs a byte. */
        volatile gint32 state;
+       gint16 nused;
        unsigned int pinned : 1;
        unsigned int has_references : 1;
        unsigned int has_pinned : 1;    /* means cannot evacuate */
@@ -1514,6 +1515,7 @@ ensure_block_is_checked_for_sweeping (guint32 block_index, gboolean wait, gboole
        for (i = 0; i < MS_NUM_MARK_WORDS; ++i)
                nused += bitcount (block->mark_words [i]);
 
+       block->nused = nused;
        if (nused)
                have_live = TRUE;
        if (nused < count)
@@ -1778,6 +1780,67 @@ major_finish_nursery_collection (void)
 #endif
 }
 
+static int
+block_usage_comparer (const void *bl1, const void *bl2)
+{
+       const gint16 nused1 = (*(MSBlockInfo**)bl1)->nused;
+       const gint16 nused2 = (*(MSBlockInfo**)bl2)->nused;
+
+       return nused2 - nused1;
+}
+
+static void
+sgen_evacuation_freelist_blocks (MSBlockInfo * volatile *block_list, int size_index)
+{
+       MSBlockInfo **evacuated_blocks;
+       size_t index = 0, count, num_blocks = 0, num_used = 0;
+       MSBlockInfo *info;
+       MSBlockInfo * volatile *prev;
+
+       for (info = *block_list; info != NULL; info = info->next_free) {
+               num_blocks++;
+               num_used += info->nused;
+       }
+
+       /*
+        * We have a set of blocks in the freelist which will be evacuated. Instead
+        * of evacuating all of the blocks into new ones, we traverse the freelist
+        * sorting it by the number of occupied slots, evacuating the objects from
+        * blocks with fewer used slots into fuller blocks.
+        *
+        * The number of used slots is set at the end of the previous sweep. Since
+        * we sequentially unlink slots from blocks, except for the head of the
+        * freelist, for blocks on the freelist, the number of used slots is the same
+        * as at the end of the previous sweep.
+        */
+       evacuated_blocks = (MSBlockInfo**)sgen_alloc_internal_dynamic (sizeof (MSBlockInfo*) * num_blocks, INTERNAL_MEM_TEMPORARY, TRUE);
+
+       for (info = *block_list; info != NULL; info = info->next_free) {
+               evacuated_blocks [index++] = info;
+       }
+
+       SGEN_ASSERT (0, num_blocks == index, "Why did the freelist change ?");
+
+       qsort (evacuated_blocks, num_blocks, sizeof (gpointer), block_usage_comparer);
+
+       /*
+        * Form a new freelist with the fullest blocks. These blocks will also be
+        * marked as to_space so we don't evacuate from them.
+        */
+       count = MS_BLOCK_FREE / block_obj_sizes [size_index];
+       prev = block_list;
+       for (index = 0; index < (num_used + count - 1) / count; index++) {
+               SGEN_ASSERT (0, index < num_blocks, "Why do we need more blocks for compaction than we already had ?");
+               info = evacuated_blocks [index];
+               info->is_to_space = TRUE;
+               *prev = info;
+               prev = &info->next_free;
+       }
+       *prev = NULL;
+
+       sgen_free_internal_dynamic (evacuated_blocks, sizeof (MSBlockInfo*) * num_blocks, INTERNAL_MEM_TEMPORARY);
+}
+
 static void
 major_start_major_collection (void)
 {
@@ -1796,8 +1859,8 @@ major_start_major_collection (void)
 
                binary_protocol_evacuating_blocks (block_obj_sizes [i]);
 
-               free_block_lists [0][i] = NULL;
-               free_block_lists [MS_BLOCK_FLAG_REFS][i] = NULL;
+               sgen_evacuation_freelist_blocks (&free_block_lists [0][i], i);
+               sgen_evacuation_freelist_blocks (&free_block_lists [MS_BLOCK_FLAG_REFS][i], i);
        }
 
        if (lazy_sweep)
@@ -1809,6 +1872,13 @@ major_start_major_collection (void)
                        sweep_block (block);
                SGEN_ASSERT (0, block->state == BLOCK_STATE_SWEPT, "All blocks must be swept when we're pinning.");
                set_block_state (block, BLOCK_STATE_MARKING, BLOCK_STATE_SWEPT);
+               /*
+                * Swept blocks that have a null free_list are full. Evacuation is not
+                * effective on these blocks since we expect them to have high usage anyway,
+                * given that the survival rate for majors is relatively high.
+                */
+               if (evacuate_block_obj_sizes [block->obj_size_index] && !block->free_list)
+                       block->is_to_space = TRUE;
        } END_FOREACH_BLOCK_NO_LOCK;
 
        if (lazy_sweep)