+/* nursery allocator */
+
+void mono_sgen_clear_nursery_fragments (void) MONO_INTERNAL;
+void mono_sgen_nursery_allocator_prepare_for_pinning (void) MONO_INTERNAL;
+void mono_sgen_clear_current_nursery_fragment (void) MONO_INTERNAL;
+void mono_sgen_nursery_allocator_set_nursery_bounds (char *nursery_start, char *nursery_end) MONO_INTERNAL;
+mword mono_sgen_build_nursery_fragments (GCMemSection *nursery_section, void **start, int num_entries) MONO_INTERNAL;
+void mono_sgen_init_nursery_allocator (void) MONO_INTERNAL;
+void mono_sgen_nursery_allocator_init_heavy_stats (void) MONO_INTERNAL;
+char* mono_sgen_nursery_alloc_get_upper_alloc_bound (void) MONO_INTERNAL;
+void* mono_sgen_nursery_alloc (size_t size) MONO_INTERNAL;
+void* mono_sgen_nursery_alloc_range (size_t size, size_t min_size, int *out_alloc_size) MONO_INTERNAL;
+MonoVTable* mono_sgen_get_array_fill_vtable (void) MONO_INTERNAL;
+gboolean mono_sgen_can_alloc_size (size_t size) MONO_INTERNAL;
+void mono_sgen_nursery_retire_region (void *address, ptrdiff_t size) 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 mono_sgen_hash_table_lookup (SgenHashTable *table, gpointer key) MONO_INTERNAL;
+gboolean mono_sgen_hash_table_replace (SgenHashTable *table, gpointer key, gpointer data) MONO_INTERNAL;
+gboolean mono_sgen_hash_table_set_value (SgenHashTable *table, gpointer key, gpointer data) MONO_INTERNAL;
+gboolean mono_sgen_hash_table_set_key (SgenHashTable *hash_table, gpointer old_key, gpointer new_key) MONO_INTERNAL;
+gboolean mono_sgen_hash_table_remove (SgenHashTable *table, gpointer key, gpointer data_return) MONO_INTERNAL;
+
+void mono_sgen_hash_table_clean (SgenHashTable *table) MONO_INTERNAL;
+
+#define mono_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; \
+ SgenHashTableEntry *__entry, *__prev; \
+ guint __i; \
+ for (__i = 0; __i < (h)->size; ++__i) { \
+ __prev = NULL; \
+ for (__entry = __table [__i]; __entry; ) { \
+ (k) = __entry->key; \
+ (v) = (gpointer)__entry->data;
+
+/* The loop must be continue'd after using this! */
+#define SGEN_HASH_TABLE_FOREACH_REMOVE(free) do { \
+ SgenHashTableEntry *__next = __entry->next; \
+ if (__prev) \
+ __prev->next = __next; \
+ else \
+ __table [__i] = __next; \
+ if ((free)) \
+ mono_sgen_free_internal (__entry, __hash_table->entry_mem_type); \
+ __entry = __next; \
+ --__hash_table->num_entries; \
+ } while (0)
+
+#define SGEN_HASH_TABLE_FOREACH_SET_KEY(k) ((__entry)->key = (k))
+
+#define SGEN_HASH_TABLE_FOREACH_END \
+ __prev = __entry; \
+ __entry = __entry->next; \
+ } \
+ } \
+ } while (0)
+