Merge pull request #1857 from slluis/fix-assembly-resolver
[mono.git] / mono / metadata / sgen-mono.c
index b4a0009eafd5f86ce05596de9e72ccd31762abd6..9050c3b1d2f9d45bfaa907bc35d4c83330e5dc5d 100644 (file)
@@ -923,24 +923,47 @@ mono_gc_clear_domain (MonoDomain * domain)
  * Allocation
  */
 
+static gboolean alloc_events = FALSE;
+
+void
+mono_gc_enable_alloc_events (void)
+{
+       alloc_events = TRUE;
+}
+
 void*
 mono_gc_alloc_obj (MonoVTable *vtable, size_t size)
 {
-       return sgen_alloc_obj (vtable, size);
+       MonoObject *obj = sgen_alloc_obj (vtable, size);
+
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (obj);
+
+       return obj;
 }
 
 void*
 mono_gc_alloc_pinned_obj (MonoVTable *vtable, size_t size)
 {
-       return sgen_alloc_obj_pinned (vtable, size);
+       MonoObject *obj = sgen_alloc_obj_pinned (vtable, size);
+
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (obj);
+
+       return obj;
 }
 
 void*
 mono_gc_alloc_mature (MonoVTable *vtable)
 {
        MonoObject *obj = sgen_alloc_obj_mature (vtable, vtable->klass->instance_size);
+
        if (obj && G_UNLIKELY (obj->vtable->klass->has_finalize))
                mono_object_register_finalizer (obj);
+
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (obj);
+
        return obj;
 }
 
@@ -970,6 +993,7 @@ mono_gc_free_fixed (void* addr)
  */
 
 static MonoMethod* alloc_method_cache [ATYPE_NUM];
+static MonoMethod* slowpath_alloc_method_cache [ATYPE_NUM];
 static gboolean use_managed_allocator = TRUE;
 
 #ifdef MANAGED_ALLOCATION
@@ -1025,7 +1049,7 @@ static gboolean use_managed_allocator = TRUE;
  * that they are executed atomically via the restart mechanism.
  */
 static MonoMethod*
-create_allocator (int atype)
+create_allocator (int atype, gboolean slowpath)
 {
        int p_var, size_var;
        guint32 slowpath_branch, max_size_branch;
@@ -1034,9 +1058,9 @@ create_allocator (int atype)
        MonoMethodSignature *csig;
        static gboolean registered = FALSE;
        int tlab_next_addr_var, new_next_var;
-       int num_params, i;
        const char *name = NULL;
        AllocatorWrapperInfo *info;
+       int num_params, i;
 
        if (!registered) {
                mono_register_jit_icall (mono_gc_alloc_obj, "mono_gc_alloc_obj", mono_create_icall_signature ("object ptr int"), FALSE);
@@ -1046,21 +1070,22 @@ create_allocator (int atype)
        }
 
        if (atype == ATYPE_SMALL) {
-               num_params = 2;
-               name = "AllocSmall";
+               name = slowpath ? "SlowAllocSmall" : "AllocSmall";
        } else if (atype == ATYPE_NORMAL) {
-               num_params = 1;
-               name = "Alloc";
+               name = slowpath ? "SlowAlloc" : "Alloc";
        } else if (atype == ATYPE_VECTOR) {
-               num_params = 2;
-               name = "AllocVector";
+               name = slowpath ? "SlowAllocVector" : "AllocVector";
        } else if (atype == ATYPE_STRING) {
-               num_params = 2;
-               name = "AllocString";
+               name = slowpath ? "SlowAllocString" : "AllocString";
        } else {
                g_assert_not_reached ();
        }
 
+       if (atype == ATYPE_NORMAL)
+               num_params = 1;
+       else
+               num_params = 2;
+
        csig = mono_metadata_signature_alloc (mono_defaults.corlib, num_params);
        if (atype == ATYPE_STRING) {
                csig->ret = &mono_defaults.string_class->byval_arg;
@@ -1068,13 +1093,36 @@ create_allocator (int atype)
                csig->params [1] = &mono_defaults.int32_class->byval_arg;
        } else {
                csig->ret = &mono_defaults.object_class->byval_arg;
-               for (i = 0; i < num_params; ++i)
+               for (i = 0; i < num_params; i++)
                        csig->params [i] = &mono_defaults.int_class->byval_arg;
        }
 
        mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_ALLOC);
 
 #ifndef DISABLE_JIT
+       if (slowpath) {
+               switch (atype) {
+               case ATYPE_NORMAL:
+               case ATYPE_SMALL:
+                       mono_mb_emit_ldarg (mb, 0);
+                       mono_mb_emit_icall (mb, mono_object_new_specific);
+                       break;
+               case ATYPE_VECTOR:
+                       mono_mb_emit_ldarg (mb, 0);
+                       mono_mb_emit_ldarg (mb, 1);
+                       mono_mb_emit_icall (mb, mono_array_new_specific);
+                       break;
+               case ATYPE_STRING:
+                       mono_mb_emit_ldarg (mb, 1);
+                       mono_mb_emit_icall (mb, mono_string_alloc);
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+
+               goto done;
+       }
+
        size_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
        if (atype == ATYPE_SMALL) {
                /* size_var = size_arg */
@@ -1330,6 +1378,8 @@ create_allocator (int atype)
 
        /* return p */
        mono_mb_emit_ldloc (mb, p_var);
+
+ done:
        mono_mb_emit_byte (mb, CEE_RET);
 #endif
 
@@ -1372,17 +1422,17 @@ mono_gc_get_managed_allocator (MonoClass *klass, gboolean for_box, gboolean know
                return NULL;
        if (known_instance_size && ALIGN_TO (klass->instance_size, SGEN_ALLOC_ALIGN) >= SGEN_MAX_SMALL_OBJ_SIZE)
                return NULL;
-       if (klass->has_finalize || mono_class_is_marshalbyref (klass) || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
+       if (mono_class_has_finalizer (klass) || mono_class_is_marshalbyref (klass) || (mono_profiler_get_events () & MONO_PROFILE_ALLOCATIONS))
                return NULL;
        if (klass->rank)
                return NULL;
        if (klass->byval_arg.type == MONO_TYPE_STRING)
-               return mono_gc_get_managed_allocator_by_type (ATYPE_STRING);
+               return mono_gc_get_managed_allocator_by_type (ATYPE_STRING, FALSE);
        /* Generic classes have dynamic field and can go above MAX_SMALL_OBJ_SIZE. */
        if (known_instance_size)
-               return mono_gc_get_managed_allocator_by_type (ATYPE_SMALL);
+               return mono_gc_get_managed_allocator_by_type (ATYPE_SMALL, FALSE);
        else
-               return mono_gc_get_managed_allocator_by_type (ATYPE_NORMAL);
+               return mono_gc_get_managed_allocator_by_type (ATYPE_NORMAL, FALSE);
 #else
        return NULL;
 #endif
@@ -1402,7 +1452,7 @@ mono_gc_get_managed_array_allocator (MonoClass *klass)
                return NULL;
        g_assert (!mono_class_has_finalizer (klass) && !mono_class_is_marshalbyref (klass));
 
-       return mono_gc_get_managed_allocator_by_type (ATYPE_VECTOR);
+       return mono_gc_get_managed_allocator_by_type (ATYPE_VECTOR, FALSE);
 #else
        return NULL;
 #endif
@@ -1415,10 +1465,11 @@ sgen_set_use_managed_allocator (gboolean flag)
 }
 
 MonoMethod*
-mono_gc_get_managed_allocator_by_type (int atype)
+mono_gc_get_managed_allocator_by_type (int atype, gboolean slowpath)
 {
 #ifdef MANAGED_ALLOCATION
        MonoMethod *res;
+       MonoMethod **cache = slowpath ? slowpath_alloc_method_cache : alloc_method_cache;
 
        if (!use_managed_allocator)
                return NULL;
@@ -1426,18 +1477,18 @@ mono_gc_get_managed_allocator_by_type (int atype)
        if (!mono_runtime_has_tls_get ())
                return NULL;
 
-       res = alloc_method_cache [atype];
+       res = cache [atype];
        if (res)
                return res;
 
-       res = create_allocator (atype);
+       res = create_allocator (atype, slowpath);
        LOCK_GC;
-       if (alloc_method_cache [atype]) {
+       if (cache [atype]) {
                mono_free_method (res);
-               res = alloc_method_cache [atype];
+               res = cache [atype];
        } else {
                mono_memory_barrier ();
-               alloc_method_cache [atype] = res;
+               cache [atype] = res;
        }
        UNLOCK_GC;
 
@@ -1459,7 +1510,7 @@ sgen_is_managed_allocator (MonoMethod *method)
        int i;
 
        for (i = 0; i < ATYPE_NUM; ++i)
-               if (method == alloc_method_cache [i])
+               if (method == alloc_method_cache [i] || method == slowpath_alloc_method_cache [i])
                        return TRUE;
        return FALSE;
 }
@@ -1470,7 +1521,7 @@ sgen_has_managed_allocator (void)
        int i;
 
        for (i = 0; i < ATYPE_NUM; ++i)
-               if (alloc_method_cache [i])
+               if (alloc_method_cache [i] || slowpath_alloc_method_cache [i])
                        return TRUE;
        return FALSE;
 }
@@ -1688,6 +1739,9 @@ mono_gc_alloc_vector (MonoVTable *vtable, size_t size, uintptr_t max_length)
        UNLOCK_GC;
 
  done:
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (&arr->obj);
+
        SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size ((GCVTable*)vtable, (GCObject*)arr)), "Vector has incorrect size.");
        return arr;
 }
@@ -1733,6 +1787,9 @@ mono_gc_alloc_array (MonoVTable *vtable, size_t size, uintptr_t max_length, uint
        UNLOCK_GC;
 
  done:
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (&arr->obj);
+
        SGEN_ASSERT (6, SGEN_ALIGN_UP (size) == SGEN_ALIGN_UP (sgen_client_par_object_get_size ((GCVTable*)vtable, (GCObject*)arr)), "Array has incorrect size.");
        return arr;
 }
@@ -1753,7 +1810,7 @@ mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len)
                /*This doesn't require fencing since EXIT_CRITICAL_REGION already does it for us*/
                str->length = len;
                EXIT_CRITICAL_REGION;
-               return str;
+               goto done;
        }
        EXIT_CRITICAL_REGION;
 #endif
@@ -1770,6 +1827,10 @@ mono_gc_alloc_string (MonoVTable *vtable, size_t size, gint32 len)
 
        UNLOCK_GC;
 
+ done:
+       if (G_UNLIKELY (alloc_events))
+               mono_profiler_allocation (&str->object);
+
        return str;
 }
 
@@ -2362,32 +2423,16 @@ mono_gc_deregister_root (char* addr)
 }
 
 /*
- * Pthread intercept
+ * PThreads
  */
 
-#if USE_PTHREAD_INTERCEPT
-
-int
-mono_gc_pthread_join (pthread_t thread, void **retval)
-{
-       return pthread_join (thread, retval);
-}
-
+#ifndef HOST_WIN32
 int
-mono_gc_pthread_detach (pthread_t thread)
+mono_gc_pthread_create (pthread_t *new_thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
 {
-       return pthread_detach (thread);
+       return pthread_create (new_thread, attr, start_routine, arg);
 }
-
-void
-mono_gc_pthread_exit (void *retval) 
-{
-       mono_thread_info_detach ();
-       pthread_exit (retval);
-       g_assert_not_reached ();
-}
-
-#endif /* USE_PTHREAD_INTERCEPT */
+#endif
 
 /*
  * Miscellaneous
@@ -2698,9 +2743,6 @@ sgen_client_init (void)
        cb.thread_attach = sgen_thread_attach;
        cb.mono_method_is_critical = (gpointer)is_critical_method;
        cb.mono_thread_in_critical_region = thread_in_critical_region;
-#ifndef HOST_WIN32
-       cb.thread_exit = mono_gc_pthread_exit;
-#endif
 
        mono_threads_init (&cb, sizeof (SgenThreadInfo));
 
@@ -2842,4 +2884,15 @@ mono_gc_base_init (void)
                sgen_set_use_managed_allocator (FALSE);
 }
 
+void
+mono_gc_base_cleanup (void)
+{
+}
+
+gboolean
+mono_gc_is_null (void)
+{
+       return FALSE;
+}
+
 #endif