Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mono / metadata / sgen-gc.h
index 0f0e73440cc0f296d027baa9d8e96075e5d2c9eb..7af57d698660730e9d9b4c2a7730a22fc9758239 100644 (file)
@@ -1,26 +1,23 @@
 /*
+ * sgen-gc.c: Simple generational GC.
+ *
  * Copyright 2001-2003 Ximian, Inc
  * Copyright 2003-2010 Novell, Inc.
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
- * 
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * Copyright (C) 2012 Xamarin Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License 2.0 as published by the Free Software Foundation;
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License 2.0 along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 #ifndef __MONO_SGENGC_H__
 #define __MONO_SGENGC_H__
@@ -41,6 +38,7 @@ typedef struct _SgenThreadInfo SgenThreadInfo;
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-threads.h>
 #include <mono/utils/dtrace.h>
+#include <mono/utils/mono-logger-internal.h>
 #include <mono/io-layer/mono-mutex.h>
 #include <mono/metadata/class-internals.h>
 #include <mono/metadata/object-internals.h>
@@ -48,10 +46,7 @@ typedef struct _SgenThreadInfo SgenThreadInfo;
 #include <mono/metadata/sgen-archdep.h>
 #include <mono/metadata/sgen-descriptor.h>
 #include <mono/metadata/sgen-gray.h>
-
-#if defined(__MACH__)
-       #include <mach/mach_port.h>
-#endif
+#include <mono/metadata/sgen-hash-table.h>
 
 /* The method used to clear the nursery */
 /* Clearing at nursery collections is the safest, but has bad interactions with caches.
@@ -104,14 +99,11 @@ enum {
 };
 
 /* eventually share with MonoThread? */
+/*
+ * This structure extends the MonoThreadInfo structure.
+ */
 struct _SgenThreadInfo {
        MonoThreadInfo info;
-#if defined(__MACH__)
-       thread_port_t mach_port;
-#else
-       int signal;
-       unsigned int stop_count; /* to catch duplicate signals */
-#endif
        int skip;
        volatile int in_critical_region;
        gboolean joined_stw;
@@ -129,22 +121,20 @@ struct _SgenThreadInfo {
        long *store_remset_buffer_index_addr;
        RememberedSet *remset;
        gpointer runtime_data;
+
+       /* Only used on POSIX platforms */
+       int signal;
+       /* Ditto */
+       unsigned int stop_count; /* to catch duplicate signals */
+
        gpointer stopped_ip;    /* only valid if the thread is stopped */
        MonoDomain *stopped_domain; /* ditto */
 
 #ifdef USE_MONO_CTX
-#ifdef __MACH__
        MonoContext ctx;                /* ditto */
-#endif
-       MonoContext *monoctx;   /* ditto */
-
 #else
-
-#if defined(__MACH__) || defined(HOST_WIN32)
        gpointer regs[ARCH_NUM_REGS];       /* ditto */
 #endif
-       gpointer *stopped_regs;     /* ditto */
-#endif
 
 #ifndef HAVE_KW_THREAD
        char *tlab_start;
@@ -212,8 +202,11 @@ typedef struct _SgenPinnedChunk SgenPinnedChunk;
                mono_mutex_unlock (&gc_mutex);                  \
                MONO_GC_UNLOCKED ();                            \
        } while (0)
-#define LOCK_INTERRUPTION mono_mutex_lock (&interruption_mutex)
-#define UNLOCK_INTERRUPTION mono_mutex_unlock (&interruption_mutex)
+
+extern LOCK_DECLARE (sgen_interruption_mutex);
+
+#define LOCK_INTERRUPTION mono_mutex_lock (&sgen_interruption_mutex)
+#define UNLOCK_INTERRUPTION mono_mutex_unlock (&sgen_interruption_mutex)
 
 /* FIXME: Use InterlockedAdd & InterlockedAdd64 to reduce the CAS cost. */
 #define SGEN_CAS_PTR   InterlockedCompareExchangePointer
@@ -247,7 +240,27 @@ extern long long stat_objects_copied_major;
 #define HEAVY_STAT(x)
 #endif
 
-#define DEBUG(level,a) do {if (G_UNLIKELY ((level) <= SGEN_MAX_DEBUG_LEVEL && (level) <= gc_debug_level)) { a; fflush (gc_debug_file); } } while (0)
+#define SGEN_ASSERT(level, a, ...) do {        \
+       if (G_UNLIKELY ((level) <= SGEN_MAX_ASSERT_LEVEL && !(a))) {    \
+               g_error (__VA_ARGS__);  \
+} } while (0)
+
+
+#define SGEN_LOG(level, format, ...) do {      \
+       if (G_UNLIKELY ((level) <= SGEN_MAX_DEBUG_LEVEL && (level) <= gc_debug_level)) {        \
+               mono_gc_printf (gc_debug_file, format, ##__VA_ARGS__);  \
+} } while (0)
+
+#define SGEN_COND_LOG(level, cond, format, ...) do {   \
+       if (G_UNLIKELY ((level) <= SGEN_MAX_DEBUG_LEVEL && (level) <= gc_debug_level)) {        \
+               if (cond)       \
+                       mono_gc_printf (gc_debug_file, format, ##__VA_ARGS__);  \
+} } while (0)
+
+#define SGEN_LOG_DO(level, fun) do {   \
+       if (G_UNLIKELY ((level) <= SGEN_MAX_DEBUG_LEVEL && (level) <= gc_debug_level)) {        \
+               fun;    \
+} } while (0)
 
 extern int gc_debug_level;
 extern FILE* gc_debug_file;
@@ -258,11 +271,21 @@ extern unsigned int sgen_global_stop_count;
 
 extern gboolean bridge_processing_in_progress;
 
+extern int num_ready_finalizers;
+
 #define SGEN_ALLOC_ALIGN               8
 #define SGEN_ALLOC_ALIGN_BITS  3
 
 #define SGEN_ALIGN_UP(s)               (((s)+(SGEN_ALLOC_ALIGN-1)) & ~(SGEN_ALLOC_ALIGN-1))
 
+/*
+ * The link pointer is hidden by negating each bit.  We use the lowest
+ * bit of the link (before negation) to store whether it needs
+ * resurrection tracking.
+ */
+#define HIDE_POINTER(p,t)      ((gpointer)(~((gulong)(p)|((t)?1:0))))
+#define REVEAL_POINTER(p)      ((gpointer)((~(gulong)(p))&~3L))
+
 #ifdef SGEN_ALIGN_NURSERY
 #define SGEN_PTR_IN_NURSERY(p,bits,start,end)  (((mword)(p) & ~((1 << (bits)) - 1)) == (mword)(start))
 #else
@@ -384,6 +407,25 @@ enum {
        SGEN_GC_BIT_BRIDGE_OBJECT = 1,
 };
 
+/* the runtime can register areas of memory as roots: we keep two lists of roots,
+ * a pinned root set for conservatively scanned roots and a normal one for
+ * precisely scanned roots (currently implemented as a single list).
+ */
+typedef struct _RootRecord RootRecord;
+struct _RootRecord {
+       char *end_root;
+       mword root_desc;
+};
+
+enum {
+       ROOT_TYPE_NORMAL = 0, /* "normal" roots */
+       ROOT_TYPE_PINNED = 1, /* roots without a GC descriptor */
+       ROOT_TYPE_WBARRIER = 2, /* roots with a write barrier */
+       ROOT_TYPE_NUM
+};
+
+extern SgenHashTable roots_hash [ROOT_TYPE_NUM];
+
 typedef void (*IterateObjectCallbackFunc) (char*, size_t, void*);
 
 int sgen_thread_handshake (BOOL suspend) MONO_INTERNAL;
@@ -426,6 +468,10 @@ enum {
        INTERNAL_MEM_EPHEMERON_LINK,
        INTERNAL_MEM_WORKER_DATA,
        INTERNAL_MEM_BRIDGE_DATA,
+       INTERNAL_MEM_BRIDGE_HASH_TABLE,
+       INTERNAL_MEM_BRIDGE_HASH_TABLE_ENTRY,
+       INTERNAL_MEM_BRIDGE_ALIVE_HASH_TABLE,
+       INTERNAL_MEM_BRIDGE_ALIVE_HASH_TABLE_ENTRY,
        INTERNAL_MEM_JOB_QUEUE_ENTRY,
        INTERNAL_MEM_TOGGLEREF_DATA,
        INTERNAL_MEM_MAX
@@ -473,9 +519,6 @@ void sgen_free_internal_dynamic (void *addr, size_t size, int type) MONO_INTERNA
 void* sgen_alloc_pinned (SgenPinnedAllocator *allocator, size_t size) MONO_INTERNAL;
 void sgen_free_pinned (SgenPinnedAllocator *allocator, void *addr, size_t size) MONO_INTERNAL;
 
-
-void sgen_debug_printf (int level, const char *format, ...) MONO_INTERNAL;
-
 gboolean sgen_parse_environment_string_extract_number (const char *str, glong *out) MONO_INTERNAL;
 
 void sgen_pinned_scan_objects (SgenPinnedAllocator *alc, IterateObjectCallbackFunc callback, void *callback_data) MONO_INTERNAL;
@@ -563,8 +606,8 @@ sgen_nursery_is_to_space (char *object)
        int byte = idx / 8;
        int bit = idx & 0x7;
 
-       DEBUG (4, g_assert (sgen_ptr_in_nursery (object)));
-       DEBUG (4, g_assert (byte < sgen_space_bitmap_size));
+       SGEN_ASSERT (4, sgen_ptr_in_nursery (object), "object %p is not in nursery [%p - %p]", object, sgen_get_nursery_start (), sgen_get_nursery_end ());
+       SGEN_ASSERT (4, byte < sgen_space_bitmap_size, "byte index %d out of range", byte, sgen_space_bitmap_size);
 
        return (sgen_space_bitmap [byte] & (1 << bit)) != 0;
 }
@@ -655,7 +698,7 @@ struct _SgenMajorCollector {
        void (*start_major_collection) (void);
        void (*finish_major_collection) (void);
        void (*have_computed_minor_collection_allowance) (void);
-       gboolean (*ptr_is_in_non_pinned_space) (char *ptr);
+       gboolean (*ptr_is_in_non_pinned_space) (char *ptr, char **start);
        gboolean (*obj_is_from_pinned_alloc) (char *obj);
        void (*report_pinned_memory_usage) (void);
        int (*get_num_major_sections) (void);
@@ -797,6 +840,19 @@ void sgen_null_links_with_predicate (int generation, WeakLinkAlivePredicateFunc
 gboolean sgen_gc_is_object_ready_for_finalization (void *object) MONO_INTERNAL;
 void sgen_gc_lock (void) MONO_INTERNAL;
 void sgen_gc_unlock (void) MONO_INTERNAL;
+void sgen_gc_event_moves (void) MONO_INTERNAL;
+
+void sgen_queue_finalization_entry (MonoObject *obj) MONO_INTERNAL;
+const char* sgen_generation_name (int generation) MONO_INTERNAL;
+
+void sgen_collect_bridge_objects (CopyOrMarkObjectFunc copy_func, char *start, char *end, int generation, SgenGrayQueue *queue) MONO_INTERNAL;
+void sgen_finalize_in_range (CopyOrMarkObjectFunc copy_func, char *start, char *end, int generation, SgenGrayQueue *queue) MONO_INTERNAL;
+void sgen_null_link_in_range (CopyOrMarkObjectFunc copy_func, char *start, char *end, int generation, gboolean before_finalization, SgenGrayQueue *queue) MONO_INTERNAL;
+void sgen_null_links_for_domain (MonoDomain *domain, int generation) MONO_INTERNAL;
+void sgen_remove_finalizers_for_domain (MonoDomain *domain, int generation) MONO_INTERNAL;
+void sgen_process_fin_stage_entries (void) MONO_INTERNAL;
+void sgen_process_dislink_stage_entries (void) MONO_INTERNAL;
+void sgen_register_disappearing_link (MonoObject *obj, void **link, gboolean track, gboolean in_gc) MONO_INTERNAL;
 
 enum {
        SPACE_NURSERY,
@@ -810,7 +866,22 @@ void sgen_set_pinned_from_failed_allocation (mword objsize) MONO_INTERNAL;
 
 void sgen_ensure_free_space (size_t size) MONO_INTERNAL;
 void sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason) MONO_INTERNAL;
+gboolean sgen_has_critical_method (void) MONO_INTERNAL;
+gboolean sgen_is_critical_method (MonoMethod *method) MONO_INTERNAL;
+
+/* STW */
+
+typedef struct {
+       int generation;
+       const char *reason;
+       gboolean is_overflow;
+       SGEN_TV_DECLARE (total_time);
+       SGEN_TV_DECLARE (stw_time);
+       SGEN_TV_DECLARE (bridge_time);
+} GGTimingInfo;
 
+int sgen_stop_world (int generation) MONO_INTERNAL;
+int sgen_restart_world (int generation, GGTimingInfo *timing) MONO_INTERNAL;
 
 /* LOS */
 
@@ -836,7 +907,6 @@ void sgen_los_iterate_objects (IterateObjectCallbackFunc cb, void *user_data) MO
 void sgen_los_iterate_live_block_ranges (sgen_cardtable_block_callback callback) MONO_INTERNAL;
 void sgen_los_scan_card_table (SgenGrayQueue *queue) MONO_INTERNAL;
 void sgen_major_collector_scan_card_table (SgenGrayQueue *queue) MONO_INTERNAL;
-FILE *sgen_get_logfile (void) MONO_INTERNAL;
 gboolean sgen_los_is_valid_object (char *object) MONO_INTERNAL;
 gboolean mono_sgen_los_describe_pointer (char *ptr) MONO_INTERNAL;
 
@@ -867,7 +937,7 @@ char* sgen_par_alloc_for_promotion (char *obj, size_t objsize, gboolean has_refe
 extern MonoNativeTlsKey thread_info_key;
 
 #ifdef HAVE_KW_THREAD
-extern __thread SgenThreadInfo *thread_info;
+extern __thread SgenThreadInfo *sgen_thread_info;
 extern __thread gpointer *store_remset_buffer;
 extern __thread long store_remset_buffer_index;
 extern __thread char *stack_end;
@@ -879,7 +949,7 @@ extern __thread long *store_remset_buffer_index_addr;
 #define REMEMBERED_SET remembered_set
 #define STORE_REMSET_BUFFER    store_remset_buffer
 #define STORE_REMSET_BUFFER_INDEX      store_remset_buffer_index
-#define IN_CRITICAL_REGION thread_info->in_critical_region
+#define IN_CRITICAL_REGION sgen_thread_info->in_critical_region
 #else
 #define TLAB_ACCESS_INIT       SgenThreadInfo *__thread_info__ = mono_native_tls_get_value (thread_info_key)
 #define REMEMBERED_SET (__thread_info__->remset)
@@ -891,7 +961,7 @@ extern __thread long *store_remset_buffer_index_addr;
 #ifndef DISABLE_CRITICAL_REGION
 
 #ifdef HAVE_KW_THREAD
-#define IN_CRITICAL_REGION thread_info->in_critical_region
+#define IN_CRITICAL_REGION sgen_thread_info->in_critical_region
 #else
 #define IN_CRITICAL_REGION (__thread_info__->in_critical_region)
 #endif
@@ -972,6 +1042,7 @@ typedef enum {
 
 void sgen_init_tlab_info (SgenThreadInfo* info);
 void sgen_clear_tlabs (void);
+void sgen_set_use_managed_allocator (gboolean flag);
 gboolean sgen_is_managed_allocator (MonoMethod *method);
 gboolean sgen_has_managed_allocator (void);
 
@@ -981,6 +1052,7 @@ void sgen_check_consistency (void);
 void sgen_check_major_refs (void);
 void sgen_check_whole_heap (void);
 void sgen_check_whole_heap_stw (void) MONO_INTERNAL;
+void sgen_check_objref (char *obj);
 
 /* Write barrier support */
 
@@ -1001,16 +1073,6 @@ sgen_dummy_use (gpointer v) {
 #endif
 }
 
-
-typedef struct {
-       int generation;
-       const char *reason;
-       gboolean is_overflow;
-       SGEN_TV_DECLARE (total_time);
-       SGEN_TV_DECLARE (stw_time);
-       SGEN_TV_DECLARE (bridge_time);
-} GGTimingInfo;
-
 #endif /* HAVE_SGEN_GC */
 
 #endif /* __MONO_SGENGC_H__ */