+MonoGHashTable*
+mono_g_hash_table_new_type (GHashFunc hash_func,
+ GEqualFunc key_equal_func,
+ MonoGHashGCType type)
+{
+ MonoGHashTable *table = mono_g_hash_table_new_full (hash_func, key_equal_func, NULL, NULL);
+ table->gc_type = type;
+#if defined(HAVE_SGEN_GC)
+ if (type < 0 || type > MONO_HASH_KEY_VALUE_GC)
+ g_error ("wrong type for gc hashtable");
+ /*
+ * We use a user defined marking function to avoid having to register a GC root for
+ * each hash node.
+ */
+ if (!hash_descr)
+ hash_descr = mono_gc_make_root_descr_user (mono_g_hash_mark);
+ if (type != MONO_HASH_CONSERVATIVE_GC)
+ mono_gc_register_root_wbarrier ((char*)table, sizeof (MonoGHashTable), hash_descr);
+#elif defined(HAVE_BOEHM_GC)
+ if (type < 0 || type > MONO_HASH_KEY_VALUE_GC)
+ g_error ("wrong type for gc hashtable");
+ if (!node_gc_descs [type] && type > MONO_HASH_CONSERVATIVE_GC) {
+ gsize bmap = 0;
+ if (type & MONO_HASH_KEY_GC)
+ bmap |= 1; /* the first field in the node is the key */
+ if (type & MONO_HASH_VALUE_GC)
+ bmap |= 2; /* the second is the value */
+ bmap |= 4; /* next */
+ node_gc_descs [type] = mono_gc_make_descr_from_bitmap (&bmap, 3);
+
+ MONO_GC_REGISTER_ROOT (node_free_lists [type]);
+ }
+#endif
+ return table;
+}
+
+