Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mono / metadata / sgen-gc.h
index 31a83d53101d3782150a77860c25006dc510f4e0..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__
@@ -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,12 +193,22 @@ 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
 #define SGEN_ATOMIC_ADD(x,i)   do {                                    \
                int __old_x;                                            \
@@ -215,6 +216,13 @@ typedef struct _SgenPinnedChunk SgenPinnedChunk;
                        __old_x = (x);                                  \
                } while (InterlockedCompareExchange (&(x), __old_x + (i), __old_x) != __old_x); \
        } while (0)
+#define SGEN_ATOMIC_ADD_P(x,i) do { \
+               size_t __old_x;                                            \
+               do {                                                    \
+                       __old_x = (x);                                  \
+               } while (InterlockedCompareExchangePointer ((void**)&(x), (void*)(__old_x + (i)), (void*)__old_x) != (void*)__old_x); \
+       } while (0)
+
 
 #ifndef HOST_WIN32
 /* we intercept pthread_create calls to know which threads exist */
@@ -232,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;
@@ -241,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
@@ -367,11 +407,26 @@ enum {
        SGEN_GC_BIT_BRIDGE_OBJECT = 1,
 };
 
-typedef void (*IterateObjectCallbackFunc) (char*, size_t, void*);
+/* 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;
+};
 
-void* sgen_alloc_os_memory (size_t size, int activate) MONO_INTERNAL;
-void* sgen_alloc_os_memory_aligned (mword size, mword alignment, gboolean activate) MONO_INTERNAL;
-void sgen_free_os_memory (void *addr, size_t size) MONO_INTERNAL;
+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;
 gboolean sgen_suspend_thread (SgenThreadInfo *info) MONO_INTERNAL;
@@ -386,13 +441,10 @@ gboolean sgen_is_worker_thread (MonoNativeThreadId thread) MONO_INTERNAL;
 
 void sgen_update_heap_boundaries (mword low, mword high) MONO_INTERNAL;
 
-void sgen_register_major_sections_alloced (int num_sections) MONO_INTERNAL;
-mword sgen_get_minor_collection_allowance (void) 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,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
@@ -457,15 +513,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;
@@ -553,9 +606,8 @@ sgen_nursery_is_to_space (char *object)
        int byte = idx / 8;
        int bit = idx & 0x7;
 
-       /* FIXME put those asserts under a non default level */
-       g_assert (sgen_ptr_in_nursery (object));
-       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;
 }
@@ -646,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);
@@ -657,6 +709,8 @@ struct _SgenMajorCollector {
        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);
 };
 
 extern SgenMajorCollector major_collector;
@@ -769,7 +823,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;
@@ -779,26 +833,56 @@ 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;
 
 enum {
+       SPACE_NURSERY,
        SPACE_MAJOR,
        SPACE_LOS
 };
 
-gboolean sgen_try_alloc_space (mword size, int space) MONO_INTERNAL;
-void sgen_release_space (mword size, int space) MONO_INTERNAL;
 void sgen_pin_object (void *object, SgenGrayQueue *queue) MONO_INTERNAL;
 void sgen_parallel_pin_or_update (void **ptr, void *obj, MonoVTable *vt, SgenGrayQueue *queue) MONO_INTERNAL;
-void sgen_collect_major_no_lock (const char *reason) MONO_INTERNAL;
-void sgen_collect_nursery_no_lock (size_t requested_size) MONO_INTERNAL;
-void sgen_minor_collect_or_expand_inner (size_t size) MONO_INTERNAL;
-gboolean sgen_need_major_collection (mword space_needed) MONO_INTERNAL;
 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 */
 
 typedef struct _LOSObject LOSObject;
@@ -823,7 +907,8 @@ 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;
 
 /* nursery allocator */
 
@@ -842,78 +927,17 @@ gboolean sgen_can_alloc_size (size_t size) MONO_INTERNAL;
 void sgen_nursery_retire_region (void *address, ptrdiff_t size) MONO_INTERNAL;
 
 void sgen_nursery_alloc_prepare_for_minor (void) MONO_INTERNAL;
-void sgen_nursery_alloc_prepare_for_major (const char *reason) MONO_INTERNAL;
+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;
@@ -925,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)
@@ -937,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
@@ -984,6 +1008,8 @@ extern __thread long *store_remset_buffer_index_addr;
 extern GCMemSection *nursery_section;
 extern int stat_major_gcs;
 extern guint32 collect_before_allocs;
+extern guint32 verify_before_allocs;
+extern gboolean has_per_allocation_action;
 extern int degraded_mode;
 extern int default_nursery_size;
 extern guint32 tlab_size;
@@ -1016,13 +1042,17 @@ 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 */
 
 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 */