Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / mini-gc.c
index 882f3a99506d1c8fe02511771389cba03081b2db..ae9204f82601f2c041548231acc7fe1c41029b6e 100644 (file)
@@ -1,16 +1,18 @@
-/*
- * mini-gc.c: GC interface for the mono JIT
+/**
+ * \file
+ * GC interface for the mono JIT
  *
  * Author:
  *   Zoltan Varga (vargaz@gmail.com)
  *
  * Copyright 2009 Novell, Inc (http://www.novell.com)
  * Copyright 2011 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
 #include "mini-gc.h"
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
 
 static gboolean
 get_provenance (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
@@ -38,8 +40,9 @@ get_provenance_func (void)
 //#if defined(MONO_ARCH_GC_MAPS_SUPPORTED)
 
 #include <mono/metadata/sgen-conf.h>
-#include <mono/metadata/gc-internal.h>
+#include <mono/metadata/gc-internals.h>
 #include <mono/utils/mono-counters.h>
+#include <mono/utils/unlocked.h>
 
 #define SIZEOF_SLOT ((int)sizeof (mgreg_t))
 
@@ -252,27 +255,27 @@ static gboolean precise_frame_limit_inited;
 
 /* Stats */
 typedef struct {
-       int scanned_stacks;
-       int scanned;
-       int scanned_precisely;
-       int scanned_conservatively;
-       int scanned_registers;
-       int scanned_native;
-       int scanned_other;
+       gint32 scanned_stacks;
+       gint32 scanned;
+       gint32 scanned_precisely;
+       gint32 scanned_conservatively;
+       gint32 scanned_registers;
+       gint32 scanned_native;
+       gint32 scanned_other;
        
-       int all_slots;
-       int noref_slots;
-       int ref_slots;
-       int pin_slots;
-
-       int gc_maps_size;
-       int gc_callsites_size;
-       int gc_callsites8_size;
-       int gc_callsites16_size;
-       int gc_callsites32_size;
-       int gc_bitmaps_size;
-       int gc_map_struct_size;
-       int tlsdata_size;
+       gint32 all_slots;
+       gint32 noref_slots;
+       gint32 ref_slots;
+       gint32 pin_slots;
+
+       gint32 gc_maps_size;
+       gint32 gc_callsites_size;
+       gint32 gc_callsites8_size;
+       gint32 gc_callsites16_size;
+       gint32 gc_callsites32_size;
+       gint32 gc_bitmaps_size;
+       gint32 gc_map_struct_size;
+       gint32 tlsdata_size;
 } JITGCStats;
 
 static JITGCStats stats;
@@ -597,9 +600,9 @@ thread_attach_func (void)
        TlsData *tls;
 
        tls = g_new0 (TlsData, 1);
-       tls->tid = GetCurrentThreadId ();
+       tls->tid = mono_native_thread_id_get ();
        tls->info = mono_thread_info_current ();
-       stats.tlsdata_size += sizeof (TlsData);
+       UnlockedAdd (&stats.tlsdata_size, sizeof (TlsData));
 
        return tls;
 }
@@ -622,7 +625,7 @@ thread_suspend_func (gpointer user_data, void *sigctx, MonoContext *ctx)
                return;
        }
 
-       if (tls->tid != GetCurrentThreadId ()) {
+       if (tls->tid != mono_native_thread_id_get ()) {
                /* Happens on osx because threads are not suspended using signals */
 #ifndef TARGET_WIN32
                gboolean res;
@@ -649,7 +652,7 @@ thread_suspend_func (gpointer user_data, void *sigctx, MonoContext *ctx)
                } else {
                        tls->unwind_state.valid = FALSE;
                }
-               tls->unwind_state.unwind_data [MONO_UNWIND_DATA_JIT_TLS] = mono_native_tls_get_value (mono_jit_tls_id);
+               tls->unwind_state.unwind_data [MONO_UNWIND_DATA_JIT_TLS] = mono_tls_get_jit_tls ();
                tls->unwind_state.unwind_data [MONO_UNWIND_DATA_DOMAIN] = mono_domain_get ();
        }
 
@@ -760,7 +763,7 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end)
        /* tls == NULL can happen during startup */
        if (mono_thread_internal_current () == NULL || !tls) {
                mono_gc_conservatively_scan_area (stack_start, stack_end);
-               stats.scanned_stacks += stack_end - stack_start;
+               UnlockedAdd (&stats.scanned_stacks, stack_end - stack_start);
                return;
        }
 
@@ -821,6 +824,7 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end)
                ji = frame.ji;
 
                // FIXME: For skipped frames, scan the param area of the parent frame conservatively ?
+               // FIXME: trampolines
 
                if (frame.type == FRAME_TYPE_MANAGED_TO_NATIVE) {
                        /*
@@ -922,8 +926,11 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end)
                 * Debugging aid to control the number of frames scanned precisely
                 */
                if (!precise_frame_limit_inited) {
-                       if (g_getenv ("MONO_PRECISE_COUNT"))
-                               precise_frame_limit = atoi (g_getenv ("MONO_PRECISE_COUNT"));
+                       char *mono_precise_count = g_getenv ("MONO_PRECISE_COUNT");
+                       if (mono_precise_count) {
+                               precise_frame_limit = atoi (mono_precise_count);
+                               g_free (mono_precise_count);
+                       }
                        precise_frame_limit_inited = TRUE;
                }
                                
@@ -987,7 +994,7 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end)
                        /* This scans the previously skipped frames as well */
                        DEBUG (fprintf (logfile, "\tscan area %p-%p (%d).\n", stack_limit, real_frame_start, (int)(real_frame_start - stack_limit)));
                        mono_gc_conservatively_scan_area (stack_limit, real_frame_start);
-                       stats.scanned_other += real_frame_start - stack_limit;
+                       UnlockedAdd (&stats.scanned_other, real_frame_start - stack_limit);
                }
 
                /* Mark stack slots */
@@ -1113,16 +1120,16 @@ conservative_pass (TlsData *tls, guint8 *stack_start, guint8 *stack_end)
        if (stack_limit < stack_end) {
                DEBUG (fprintf (logfile, "\tscan remaining stack %p-%p (%d).\n", stack_limit, stack_end, (int)(stack_end - stack_limit)));
                mono_gc_conservatively_scan_area (stack_limit, stack_end);
-               stats.scanned_native += stack_end - stack_limit;
+               UnlockedAdd (&stats.scanned_native, stack_end - stack_limit);
        }
 
        DEBUG (fprintf (logfile, "Marked %d bytes, p=%d,c=%d out of %d.\n", scanned, scanned_precisely, scanned_conservatively, (int)(stack_end - stack_start)));
 
-       stats.scanned_stacks += stack_end - stack_start;
-       stats.scanned += scanned;
-       stats.scanned_precisely += scanned_precisely;
-       stats.scanned_conservatively += scanned_conservatively;
-       stats.scanned_registers += scanned_registers;
+       UnlockedAdd (&stats.scanned_stacks, stack_end - stack_start);
+       UnlockedAdd (&stats.scanned, scanned);
+       UnlockedAdd (&stats.scanned_precisely, scanned_precisely);
+       UnlockedAdd (&stats.scanned_conservatively, scanned_conservatively);
+       UnlockedAdd (&stats.scanned_registers, scanned_registers);
 
        //mono_gc_conservatively_scan_area (stack_start, stack_end);
 }
@@ -1278,10 +1285,13 @@ mini_gc_init_gc_map (MonoCompile *cfg)
                static int precise_count;
 
                precise_count ++;
-               if (g_getenv ("MONO_GCMAP_COUNT")) {
-                       if (precise_count == atoi (g_getenv ("MONO_GCMAP_COUNT")))
+               char *mono_gcmap_count = g_getenv ("MONO_GCMAP_COUNT");
+               if (mono_gcmap_count) {
+                       int count = atoi (mono_gcmap_count);
+                       g_free (mono_gcmap_count);
+                       if (precise_count == count)
                                printf ("LAST: %s\n", mono_method_full_name (cfg->method, TRUE));
-                       if (precise_count > atoi (g_getenv ("MONO_GCMAP_COUNT")))
+                       if (precise_count > count)
                                return;
                }
        }
@@ -1678,7 +1688,7 @@ process_variables (MonoCompile *cfg)
                        int hreg;
                        GCSlotType slot_type;
 
-                       t = mini_type_get_underlying_type (NULL, t);
+                       t = mini_get_underlying_type (t);
 
                        hreg = ins->dreg;
                        g_assert (hreg < MONO_MAX_IREGS);
@@ -1686,7 +1696,7 @@ process_variables (MonoCompile *cfg)
                        if (byref)
                                slot_type = SLOT_PIN;
                        else
-                               slot_type = mini_type_is_reference (cfg, t) ? SLOT_REF : SLOT_NOREF;
+                               slot_type = mini_type_is_reference (t) ? SLOT_REF : SLOT_NOREF;
 
                        if (slot_type == SLOT_PIN) {
                                /* These have no live interval, be conservative */
@@ -1833,9 +1843,9 @@ process_variables (MonoCompile *cfg)
                }
 #endif
 
-               t = mini_type_get_underlying_type (NULL, t);
+               t = mini_get_underlying_type (t);
 
-               if (!mini_type_is_reference (cfg, t)) {
+               if (!mini_type_is_reference (t)) {
                        set_slot_everywhere (gcfg, pos, SLOT_NOREF);
                        if (cfg->verbose_level > 1)
                                printf ("\tnoref%s at %s0x%x(fp) (R%d, slot = %d): %s\n", (is_arg ? " arg" : ""), ins->inst_offset < 0 ? "-" : "", (ins->inst_offset < 0) ? -(int)ins->inst_offset : (int)ins->inst_offset, vmv->vreg, pos, mono_type_full_name (ins->inst_vtype));
@@ -1939,7 +1949,7 @@ process_param_area_slots (MonoCompile *cfg)
                        guint32 size;
 
                        if (MONO_TYPE_ISSTRUCT (t)) {
-                               size = mini_type_stack_size_full (cfg->generic_sharing_context, t, &align, FALSE);
+                               size = mini_type_stack_size_full (t, &align, FALSE);
                        } else {
                                size = sizeof (mgreg_t);
                        }
@@ -2053,7 +2063,7 @@ compute_frame_size (MonoCompile *cfg)
 
                if (ins->opcode == OP_REGOFFSET) {
                        int size, size_in_slots;
-                       size = mini_type_stack_size_full (cfg->generic_sharing_context, ins->inst_vtype, NULL, ins->backend.is_pinvoke);
+                       size = mini_type_stack_size_full (ins->inst_vtype, NULL, ins->backend.is_pinvoke);
                        size_in_slots = ALIGN_TO (size, SIZEOF_SLOT) / SIZEOF_SLOT;
 
                        min_offset = MIN (min_offset, ins->inst_offset);
@@ -2414,17 +2424,17 @@ create_map (MonoCompile *cfg)
                        guint8 *offsets = p;
                        for (i = 0; i < ncallsites; ++i)
                                offsets [i] = callsites [i]->pc_offset;
-                       stats.gc_callsites8_size += ncallsites * sizeof (guint8);
+                       UnlockedAdd (&stats.gc_callsites8_size, ncallsites * sizeof (guint8));
                } else if (map->callsite_entry_size == 2) {
                        guint16 *offsets = (guint16*)p;
                        for (i = 0; i < ncallsites; ++i)
                                offsets [i] = callsites [i]->pc_offset;
-                       stats.gc_callsites16_size += ncallsites * sizeof (guint16);
+                       UnlockedAdd (&stats.gc_callsites16_size, ncallsites * sizeof (guint16));
                } else {
                        guint32 *offsets = (guint32*)p;
                        for (i = 0; i < ncallsites; ++i)
                                offsets [i] = callsites [i]->pc_offset;
-                       stats.gc_callsites32_size += ncallsites * sizeof (guint32);
+                       UnlockedAdd (&stats.gc_callsites32_size, ncallsites * sizeof (guint32));
                }
                p += ncallsites * map->callsite_entry_size;
 
@@ -2434,10 +2444,10 @@ create_map (MonoCompile *cfg)
 
                g_assert ((guint8*)p - (guint8*)emap <= alloc_size);
 
-               stats.gc_maps_size += alloc_size;
-               stats.gc_callsites_size += ncallsites * map->callsite_entry_size;
-               stats.gc_bitmaps_size += bitmaps_size;
-               stats.gc_map_struct_size += sizeof (GCEncodedMap) + encoded_size;
+               UnlockedAdd (&stats.gc_maps_size, alloc_size);
+               UnlockedAdd (&stats.gc_callsites_size, ncallsites * map->callsite_entry_size);
+               UnlockedAdd (&stats.gc_bitmaps_size, bitmaps_size);
+               UnlockedAdd (&stats.gc_map_struct_size, sizeof (GCEncodedMap) + encoded_size);
 
                cfg->jit_info->gc_info = emap;
 
@@ -2445,10 +2455,10 @@ create_map (MonoCompile *cfg)
                cfg->gc_map_size = alloc_size;
        }
 
-       stats.all_slots += nslots;
-       stats.ref_slots += ntypes [SLOT_REF];
-       stats.noref_slots += ntypes [SLOT_NOREF];
-       stats.pin_slots += ntypes [SLOT_PIN];
+       UnlockedAdd (&stats.all_slots, nslots);
+       UnlockedAdd (&stats.ref_slots, ntypes [SLOT_REF]);
+       UnlockedAdd (&stats.noref_slots, ntypes [SLOT_NOREF]);
+       UnlockedAdd (&stats.pin_slots, ntypes [SLOT_PIN]);
 }
 
 void
@@ -2501,6 +2511,7 @@ parse_debug_options (void)
                exit (1);
        }
        g_strfreev (opts);
+       g_free (env);
 }
 
 void