Merge pull request #4092 from ntherning/fix-w32process-win32.c-build-failure
[mono.git] / mono / metadata / sgen-mono.c
index 6372084d21dfb43b801fd1a0374c5aeb12a463c1..2b267f44c596955681bf54e34984e0e14f540cf7 100644 (file)
@@ -30,6 +30,7 @@
 #include "utils/mono-threads-coop.h"
 #include "sgen/sgen-thread-pool.h"
 #include "utils/mono-threads.h"
+#include "metadata/w32handle.h"
 
 #ifdef HEAVY_STATISTICS
 static guint64 stat_wbarrier_set_arrayref = 0;
@@ -212,6 +213,32 @@ sgen_has_critical_method (void)
        return sgen_has_managed_allocator ();
 }
 
+static gboolean
+ip_in_critical_region (MonoDomain *domain, gpointer ip)
+{
+       MonoJitInfo *ji;
+       MonoMethod *method;
+
+       /*
+        * We pass false for 'try_aot' so this becomes async safe.
+        * It won't find aot methods whose jit info is not yet loaded,
+        * so we preload their jit info in the JIT.
+        */
+       ji = mono_jit_info_table_find_internal (domain, ip, FALSE, FALSE);
+       if (!ji)
+               return FALSE;
+
+       method = mono_jit_info_get_method (ji);
+
+       return mono_runtime_is_critical_method (method) || sgen_is_critical_method (method);
+}
+
+gboolean
+mono_gc_is_critical_method (MonoMethod *method)
+{
+       return sgen_is_critical_method (method);
+}
+
 #ifndef DISABLE_JIT
 
 static void
@@ -1040,7 +1067,7 @@ static gboolean use_managed_allocator = TRUE;
 static MonoMethod*
 create_allocator (int atype, ManagedAllocatorVariant variant)
 {
-       int p_var, size_var, thread_var G_GNUC_UNUSED;
+       int p_var, size_var, real_size_var, thread_var G_GNUC_UNUSED;
        gboolean slowpath = variant == MANAGED_ALLOCATOR_SLOW_PATH;
        guint32 slowpath_branch, max_size_branch;
        MonoMethodBuilder *mb;
@@ -1253,6 +1280,14 @@ create_allocator (int atype, ManagedAllocatorVariant variant)
        mono_mb_emit_i4 (mb, MONO_MEMORY_BARRIER_NONE);
 #endif
 
+       if (nursery_canaries_enabled ()) {
+               real_size_var = mono_mb_add_local (mb, &mono_defaults.int_class->byval_arg);
+               mono_mb_emit_ldloc (mb, size_var);
+               mono_mb_emit_stloc(mb, real_size_var);
+       }
+       else
+               real_size_var = size_var;
+
        /* size += ALLOC_ALIGN - 1; */
        mono_mb_emit_ldloc (mb, size_var);
        mono_mb_emit_icon (mb, SGEN_ALLOC_ALIGN - 1);
@@ -1291,6 +1326,11 @@ create_allocator (int atype, ManagedAllocatorVariant variant)
        mono_mb_emit_ldloc (mb, size_var);
        mono_mb_emit_byte (mb, CEE_CONV_I);
        mono_mb_emit_byte (mb, CEE_ADD);
+
+       if (nursery_canaries_enabled ()) {
+                       mono_mb_emit_icon (mb, CANARY_SIZE);
+                       mono_mb_emit_byte (mb, CEE_ADD);
+       }
        mono_mb_emit_stloc (mb, new_next_var);
 
        /* if (G_LIKELY (new_next < tlab_temp_end)) */
@@ -1319,7 +1359,7 @@ create_allocator (int atype, ManagedAllocatorVariant variant)
 
        /* FIXME: mono_gc_alloc_obj takes a 'size_t' as an argument, not an int32 */
        mono_mb_emit_ldarg (mb, 0);
-       mono_mb_emit_ldloc (mb, size_var);
+       mono_mb_emit_ldloc (mb, real_size_var);
        if (atype == ATYPE_NORMAL || atype == ATYPE_SMALL) {
                mono_mb_emit_icall (mb, mono_gc_alloc_obj);
        } else if (atype == ATYPE_VECTOR) {
@@ -1348,6 +1388,17 @@ create_allocator (int atype, ManagedAllocatorVariant variant)
        mono_mb_emit_ldarg (mb, 0);
        mono_mb_emit_byte (mb, CEE_STIND_I);
 
+       /* mark object end with nursery word */
+       if (nursery_canaries_enabled ()) {
+                       mono_mb_emit_ldloc (mb, p_var);
+                       mono_mb_emit_ldloc (mb, real_size_var);
+                       mono_mb_emit_byte (mb, MONO_CEE_ADD);
+                       mono_mb_emit_icon8 (mb, (mword) CANARY_STRING);
+                       mono_mb_emit_icon (mb, CANARY_SIZE);
+                       mono_mb_emit_byte (mb, MONO_CEE_PREFIX1);
+                       mono_mb_emit_byte (mb, CEE_CPBLK);
+       }
+
        if (atype == ATYPE_VECTOR) {
                /* arr->max_length = max_length; */
                mono_mb_emit_ldloc (mb, p_var);
@@ -2285,12 +2336,6 @@ mono_gc_set_skip_thread (gboolean skip)
        UNLOCK_GC;
 }
 
-static gboolean
-is_critical_method (MonoMethod *method)
-{
-       return mono_runtime_is_critical_method (method) || sgen_is_critical_method (method);
-}
-
 static gboolean
 thread_in_critical_region (SgenThreadInfo *info)
 {
@@ -2845,8 +2890,8 @@ sgen_client_init (void)
        cb.thread_detach = sgen_thread_detach;
        cb.thread_unregister = sgen_thread_unregister;
        cb.thread_attach = sgen_thread_attach;
-       cb.mono_method_is_critical = (gboolean (*)(void *))is_critical_method;
        cb.mono_thread_in_critical_region = thread_in_critical_region;
+       cb.ip_in_critical_region = ip_in_critical_region;
 
        mono_threads_init (&cb, sizeof (SgenThreadInfo));
 
@@ -2990,9 +3035,6 @@ mono_gc_base_init (void)
 
        sgen_gc_init ();
 
-       if (nursery_canaries_enabled ())
-               sgen_set_use_managed_allocator (FALSE);
-
 #if defined(HAVE_KW_THREAD)
        /* This can happen with using libmonosgen.so */
        if (mono_tls_key_get_offset (TLS_KEY_SGEN_THREAD_INFO) == -1)