[sgen] Number of major objects marked in concurrent DTrace probes.
[mono.git] / mono / metadata / sgen-gc.h
index 06a8b633f9f402a337ebbeea5801bcb49db5d83f..6233786c6851d32c6a9df1a8bff2d498b0216184 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__
@@ -40,6 +37,8 @@ typedef struct _SgenThreadInfo SgenThreadInfo;
 #include <signal.h>
 #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>
@@ -47,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.
@@ -103,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;
@@ -128,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;
@@ -202,11 +193,20 @@ typedef struct _SgenPinnedChunk SgenPinnedChunk;
 /* if changing LOCK_INIT to something that isn't idempotent, look at
    its use in mono_gc_base_init in sgen-gc.c */
 #define LOCK_INIT(name)        mono_mutex_init (&(name), NULL)
-#define LOCK_GC mono_mutex_lock (&gc_mutex)
+#define LOCK_GC do {                                           \
+               mono_mutex_lock (&gc_mutex);                    \
+               MONO_GC_LOCKED ();                              \
+       } while (0)
 #define TRYLOCK_GC (mono_mutex_trylock (&gc_mutex) == 0)
-#define UNLOCK_GC mono_mutex_unlock (&gc_mutex)
-#define LOCK_INTERRUPTION mono_mutex_lock (&interruption_mutex)
-#define UNLOCK_INTERRUPTION mono_mutex_unlock (&interruption_mutex)
+#define UNLOCK_GC do {                                         \
+               mono_mutex_unlock (&gc_mutex);                  \
+               MONO_GC_UNLOCKED ();                            \
+       } while (0)
+
+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
@@ -240,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;
@@ -249,11 +269,23 @@ extern int current_collection_generation;
 
 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
@@ -347,7 +379,7 @@ typedef struct {
  */
 #define SGEN_LOAD_VTABLE(addr) ((*(mword*)(addr)) & ~SGEN_VTABLE_BITS_MASK)
 
-#if SGEN_MAX_DEBUG_LEVEL >= 9
+#if defined(SGEN_GRAY_OBJECT_ENQUEUE) || SGEN_MAX_DEBUG_LEVEL >= 9
 #define GRAY_OBJECT_ENQUEUE sgen_gray_object_enqueue
 #define GRAY_OBJECT_DEQUEUE(queue,o) ((o) = sgen_gray_object_dequeue ((queue)))
 #else
@@ -375,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;
@@ -393,7 +444,7 @@ void sgen_update_heap_boundaries (mword low, mword high) MONO_INTERNAL;
 void sgen_scan_area_with_callback (char *start, char *end, IterateObjectCallbackFunc callback, void *data, gboolean allow_flags) MONO_INTERNAL;
 void sgen_check_section_scan_starts (GCMemSection *section) MONO_INTERNAL;
 
-/* Keep in sync with sgen_dump_internal_mem_usage() in dump_heap()! */
+/* Keep in sync with description_for_type() in sgen-internal.c! */
 enum {
        INTERNAL_MEM_PIN_QUEUE,
        INTERNAL_MEM_FRAGMENT,
@@ -416,9 +467,15 @@ enum {
        INTERNAL_MEM_MS_BLOCK_INFO,
        INTERNAL_MEM_EPHEMERON_LINK,
        INTERNAL_MEM_WORKER_DATA,
+       INTERNAL_MEM_WORKER_JOB_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_CARDTABLE_MOD_UNION,
        INTERNAL_MEM_MAX
 };
 
@@ -445,6 +502,10 @@ struct _ObjectList {
        ObjectList *next;
 };
 
+typedef void (*CopyOrMarkObjectFunc) (void**, SgenGrayQueue*);
+typedef void (*ScanObjectFunc) (char*, SgenGrayQueue*);
+typedef void (*ScanVTypeFunc) (char*, mword desc, SgenGrayQueue*);
+
 void sgen_report_internal_mem_usage (void) MONO_INTERNAL;
 void sgen_report_pinned_mem_usage (SgenPinnedAllocator *alc) MONO_INTERNAL;
 void sgen_dump_internal_mem_usage (FILE *heap_dump_file) MONO_INTERNAL;
@@ -458,15 +519,12 @@ void sgen_register_fixed_internal_mem_type (int type, size_t size) MONO_INTERNAL
 void* sgen_alloc_internal (int type) MONO_INTERNAL;
 void sgen_free_internal (void *addr, int type) MONO_INTERNAL;
 
-void* sgen_alloc_internal_dynamic (size_t size, int type) MONO_INTERNAL;
+void* sgen_alloc_internal_dynamic (size_t size, int type, gboolean assert_on_failure) MONO_INTERNAL;
 void sgen_free_internal_dynamic (void *addr, size_t size, int type) MONO_INTERNAL;
 
 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;
@@ -476,7 +534,7 @@ void sgen_pinned_update_heap_boundaries (SgenPinnedAllocator *alc) MONO_INTERNAL
 
 void** sgen_find_optimized_pin_queue_area (void *start, void *end, int *num) MONO_INTERNAL;
 void sgen_find_section_pin_queue_start_end (GCMemSection *section) MONO_INTERNAL;
-void sgen_pin_objects_in_section (GCMemSection *section, SgenGrayQueue *queue) MONO_INTERNAL;
+void sgen_pin_objects_in_section (GCMemSection *section, SgenGrayQueue *queue, ScanObjectFunc scan_func) MONO_INTERNAL;
 
 void sgen_pin_stats_register_object (char *obj, size_t size);
 void sgen_pin_stats_register_global_remset (char *obj);
@@ -485,12 +543,12 @@ void sgen_pin_stats_print_class_stats (void);
 void sgen_sort_addresses (void **array, int size) MONO_INTERNAL;
 void sgen_add_to_global_remset (gpointer ptr) MONO_INTERNAL;
 
-typedef void (*CopyOrMarkObjectFunc) (void**, SgenGrayQueue*);
-typedef void (*ScanObjectFunc) (char*, SgenGrayQueue*);
-typedef void (*ScanVTypeFunc) (char*, mword desc, SgenGrayQueue*);
-
 int sgen_get_current_collection_generation (void) MONO_INTERNAL;
 gboolean sgen_collection_is_parallel (void) MONO_INTERNAL;
+gboolean sgen_collection_is_concurrent (void) MONO_INTERNAL;
+gboolean sgen_concurrent_collection_in_progress (void) MONO_INTERNAL;
+
+gboolean sgen_remember_major_object_for_concurrent_mark (char *obj) MONO_INTERNAL;
 
 typedef struct {
        CopyOrMarkObjectFunc copy_or_mark_object;
@@ -554,8 +612,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;
 }
@@ -582,8 +640,8 @@ sgen_nursery_is_object_alive (char *obj)
 }
 
 typedef struct {
-       char* (*alloc_for_promotion) (char *obj, size_t objsize, gboolean has_references);
-       char* (*par_alloc_for_promotion) (char *obj, size_t objsize, gboolean has_references);
+       char* (*alloc_for_promotion) (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references);
+       char* (*par_alloc_for_promotion) (MonoVTable *vtable, char *obj, size_t objsize, gboolean has_references);
 
        SgenObjectOperations serial_ops;
        SgenObjectOperations parallel_ops;
@@ -611,7 +669,9 @@ typedef struct _SgenMajorCollector SgenMajorCollector;
 struct _SgenMajorCollector {
        size_t section_size;
        gboolean is_parallel;
+       gboolean is_concurrent;
        gboolean supports_cardtable;
+       gboolean sweeps_lazily;
 
        /*
         * This is set to TRUE if the sweep for the last major
@@ -621,21 +681,22 @@ struct _SgenMajorCollector {
 
        void* (*alloc_heap) (mword nursery_size, mword nursery_align, int nursery_bits);
        gboolean (*is_object_live) (char *obj);
-       void* (*alloc_small_pinned_obj) (size_t size, gboolean has_references);
+       void* (*alloc_small_pinned_obj) (MonoVTable *vtable, size_t size, gboolean has_references);
        void* (*alloc_degraded) (MonoVTable *vtable, size_t size);
 
        SgenObjectOperations major_ops;
 
-       void* (*alloc_object) (int size, gboolean has_references);
-       void* (*par_alloc_object) (int size, gboolean has_references);
+       void* (*alloc_object) (MonoVTable *vtable, int size, gboolean has_references);
+       void* (*par_alloc_object) (MonoVTable *vtable, int size, gboolean has_references);
        void (*free_pinned_object) (char *obj, size_t size);
        void (*iterate_objects) (gboolean non_pinned, gboolean pinned, IterateObjectCallbackFunc callback, void *data);
        void (*free_non_pinned_object) (char *obj, size_t size);
        void (*find_pin_queue_start_ends) (SgenGrayQueue *queue);
        void (*pin_objects) (SgenGrayQueue *queue);
        void (*pin_major_object) (char *obj, SgenGrayQueue *queue);
-       void (*scan_card_table) (SgenGrayQueue *queue);
+       void (*scan_card_table) (gboolean mod_union, SgenGrayQueue *queue);
        void (*iterate_live_block_ranges) (sgen_cardtable_block_callback callback);
+       void (*update_cardtable_mod_union) (void);
        void (*init_to_space) (void);
        void (*sweep) (void);
        void (*check_scan_starts) (void);
@@ -646,19 +707,20 @@ 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);
        gboolean (*handle_gc_param) (const char *opt);
        void (*print_gc_param_usage) (void);
        gboolean (*is_worker_thread) (MonoNativeThreadId thread);
-       void (*post_param_init) (void);
+       void (*post_param_init) (SgenMajorCollector *collector);
        void* (*alloc_worker_data) (void);
        void (*init_worker_thread) (void *data);
        void (*reset_worker_data) (void *data);
        gboolean (*is_valid_object) (char *object);
        gboolean (*describe_pointer) (char *pointer);
+       long long (*get_and_reset_num_major_objects_marked) (void);
 };
 
 extern SgenMajorCollector major_collector;
@@ -667,6 +729,7 @@ void sgen_marksweep_init (SgenMajorCollector *collector) MONO_INTERNAL;
 void sgen_marksweep_fixed_init (SgenMajorCollector *collector) MONO_INTERNAL;
 void sgen_marksweep_par_init (SgenMajorCollector *collector) MONO_INTERNAL;
 void sgen_marksweep_fixed_par_init (SgenMajorCollector *collector) MONO_INTERNAL;
+void sgen_marksweep_conc_init (SgenMajorCollector *collector) MONO_INTERNAL;
 void sgen_copying_init (SgenMajorCollector *collector) MONO_INTERNAL;
 SgenMajorCollector* sgen_get_major_collector (void) MONO_INTERNAL;
 
@@ -771,7 +834,7 @@ gboolean sgen_object_is_live (void *obj) MONO_INTERNAL;
 gboolean sgen_need_bridge_processing (void) MONO_INTERNAL;
 void sgen_bridge_reset_data (void) MONO_INTERNAL;
 void sgen_bridge_processing_stw_step (void) MONO_INTERNAL;
-void sgen_bridge_processing_finish (void) MONO_INTERNAL;
+void sgen_bridge_processing_finish (int generation) MONO_INTERNAL;
 void sgen_register_test_bridge_callbacks (const char *bridge_class_name) MONO_INTERNAL;
 gboolean sgen_is_bridge_object (MonoObject *obj) MONO_INTERNAL;
 gboolean sgen_is_bridge_class (MonoClass *class) MONO_INTERNAL;
@@ -781,10 +844,28 @@ void sgen_bridge_register_finalized_object (MonoObject *object) MONO_INTERNAL;
 void sgen_scan_togglerefs (CopyOrMarkObjectFunc copy_func, char *start, char *end, SgenGrayQueue *queue) MONO_INTERNAL;
 void sgen_process_togglerefs (void) MONO_INTERNAL;
 
+typedef mono_bool (*WeakLinkAlivePredicateFunc) (MonoObject*, void*);
+
+void sgen_null_links_with_predicate (int generation, WeakLinkAlivePredicateFunc predicate, void *data) MONO_INTERNAL;
 
 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;
+
+gboolean sgen_drain_gray_stack (SgenGrayQueue *queue, ScanObjectFunc scan_func, int max_objs) MONO_INTERNAL;
 
 enum {
        SPACE_NURSERY,
@@ -797,17 +878,34 @@ void sgen_parallel_pin_or_update (void **ptr, void *obj, MonoVTable *vt, SgenGra
 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;
+void sgen_perform_collection (size_t requested_size, int generation_to_collect, const char *reason, gboolean wait_to_finish) 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 */
 
 typedef struct _LOSObject LOSObject;
 struct _LOSObject {
        LOSObject *next;
-       mword size; /* this is the object size */
-       guint16 huge_object;
-       int dummy; /* to have a sizeof (LOSObject) a multiple of ALLOC_ALIGN  and data starting at same alignment */
+       mword size; /* this is the object size, lowest bit used for pin/mark */
+       guint8 *cardtable_mod_union; /* only used by the concurrent collector */
+#ifdef SIZEOF_VOID_P < 8
+       mword dummy;            /* to align object to sizeof (double) */
+#endif
        char data [MONO_ZERO_LEN_ARRAY];
 };
 
@@ -822,11 +920,17 @@ void sgen_los_sweep (void) MONO_INTERNAL;
 gboolean sgen_ptr_is_in_los (char *ptr, char **start) MONO_INTERNAL;
 void sgen_los_iterate_objects (IterateObjectCallbackFunc cb, void *user_data) MONO_INTERNAL;
 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_los_scan_card_table (gboolean mod_union, SgenGrayQueue *queue) MONO_INTERNAL;
+void sgen_los_update_cardtable_mod_union (void) 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;
+LOSObject* sgen_los_header_for_object (char *data) MONO_INTERNAL;
+mword sgen_los_object_size (LOSObject *obj) MONO_INTERNAL;
+void sgen_los_pin_object (char *obj) MONO_INTERNAL;
+void sgen_los_unpin_object (char *obj) MONO_INTERNAL;
+gboolean sgen_los_object_is_pinned (char *obj) MONO_INTERNAL;
+
 
 /* nursery allocator */
 
@@ -850,73 +954,12 @@ void sgen_nursery_alloc_prepare_for_major (void) MONO_INTERNAL;
 char* sgen_alloc_for_promotion (char *obj, size_t objsize, gboolean has_references) MONO_INTERNAL;
 char* sgen_par_alloc_for_promotion (char *obj, size_t objsize, gboolean has_references) MONO_INTERNAL;
 
-/* hash tables */
-
-typedef struct _SgenHashTableEntry SgenHashTableEntry;
-struct _SgenHashTableEntry {
-       SgenHashTableEntry *next;
-       gpointer key;
-       char data [MONO_ZERO_LEN_ARRAY]; /* data is pointer-aligned */
-};
-
-typedef struct {
-       int table_mem_type;
-       int entry_mem_type;
-       size_t data_size;
-       GHashFunc hash_func;
-       GEqualFunc equal_func;
-       SgenHashTableEntry **table;
-       guint size;
-       guint num_entries;
-} SgenHashTable;
-
-#define SGEN_HASH_TABLE_INIT(table_type,entry_type,data_size,hash_func,equal_func)     { (table_type), (entry_type), (data_size), (hash_func), (equal_func), NULL, 0, 0 }
-#define SGEN_HASH_TABLE_ENTRY_SIZE(data_size)                  ((data_size) + sizeof (SgenHashTableEntry*) + sizeof (gpointer))
-
-gpointer sgen_hash_table_lookup (SgenHashTable *table, gpointer key) MONO_INTERNAL;
-gboolean sgen_hash_table_replace (SgenHashTable *table, gpointer key, gpointer new_value, gpointer old_value) MONO_INTERNAL;
-gboolean sgen_hash_table_set_value (SgenHashTable *table, gpointer key, gpointer new_value, gpointer old_value) MONO_INTERNAL;
-gboolean sgen_hash_table_set_key (SgenHashTable *hash_table, gpointer old_key, gpointer new_key) MONO_INTERNAL;
-gboolean sgen_hash_table_remove (SgenHashTable *table, gpointer key, gpointer data_return) MONO_INTERNAL;
-
-void sgen_hash_table_clean (SgenHashTable *table) MONO_INTERNAL;
-
-#define sgen_hash_table_num_entries(h) ((h)->num_entries)
-
-#define SGEN_HASH_TABLE_FOREACH(h,k,v) do {                            \
-               SgenHashTable *__hash_table = (h);                      \
-               SgenHashTableEntry **__table = __hash_table->table;     \
-               guint __i;                                              \
-               for (__i = 0; __i < (h)->size; ++__i) {                 \
-                       SgenHashTableEntry **__iter, **__next;                  \
-                       for (__iter = &__table [__i]; *__iter; __iter = __next) {       \
-                               SgenHashTableEntry *__entry = *__iter;  \
-                               __next = &__entry->next;        \
-                               (k) = __entry->key;                     \
-                               (v) = (gpointer)__entry->data;
-
-/* The loop must be continue'd after using this! */
-#define SGEN_HASH_TABLE_FOREACH_REMOVE(free)   do {                    \
-               *__iter = *__next;      \
-               __next = __iter;        \
-               --__hash_table->num_entries;                            \
-               if ((free))                                             \
-                       sgen_free_internal (__entry, __hash_table->entry_mem_type); \
-       } while (0)
-
-#define SGEN_HASH_TABLE_FOREACH_SET_KEY(k)     ((__entry)->key = (k))
-
-#define SGEN_HASH_TABLE_FOREACH_END                                    \
-                       }                                               \
-               }                                                       \
-       } while (0)
-
 /* TLS Data */
 
 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;
@@ -928,7 +971,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)
@@ -940,7 +983,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
@@ -1021,7 +1064,9 @@ 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);
 
 /* Debug support */
 
@@ -1029,6 +1074,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 */
 
@@ -1049,16 +1095,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__ */