/*
* Configurable cementing parameters.
*
- * The hash table size should be a prime. If there are too many
- * pinned nursery objects with many references from the major heap,
- * this number must be increased.
+ * If there are too many pinned nursery objects with many references
+ * from the major heap, the hash table size must be increased.
*
* The threshold is the number of references from the major heap to a
* pinned nursery object which triggers cementing: if there are more
* than that number of references, the pinned object is cemented until
* the next major collection.
*/
-#define SGEN_CEMENT_HASH_SIZE 61
+#define SGEN_CEMENT_HASH_SHIFT 6
+#define SGEN_CEMENT_HASH_SIZE (1 << SGEN_CEMENT_HASH_SHIFT)
+#define SGEN_CEMENT_HASH(hv) (((hv) ^ ((hv) >> SGEN_CEMENT_HASH_SHIFT)) & (SGEN_CEMENT_HASH_SIZE - 1))
#define SGEN_CEMENT_THRESHOLD 1000
#endif
gboolean
sgen_cement_lookup (char *obj)
{
- int i = mono_aligned_addr_hash (obj) % SGEN_CEMENT_HASH_SIZE;
+ guint hv = mono_aligned_addr_hash (obj);
+ int i = SGEN_CEMENT_HASH (hv);
SGEN_ASSERT (5, sgen_ptr_in_nursery (obj), "Looking up cementing for non-nursery objects makes no sense");
gboolean
sgen_cement_lookup_or_register (char *obj)
{
+ guint hv;
int i;
CementHashEntry *hash;
gboolean concurrent_cementing = sgen_concurrent_collection_in_progress ();
else
hash = cement_hash;
- /*
- * We use modulus hashing, which is fine with constants as gcc
- * can optimize them to multiplication, but with variable
- * values it would be a bad idea given armv7 has no hardware
- * for division, making it 20x slower than a multiplication.
- *
- * This code path can be quite hot, depending on the workload,
- * so if we make the hash size user-adjustable we should
- * figure out something not involving division.
- */
- i = mono_aligned_addr_hash (obj) % SGEN_CEMENT_HASH_SIZE;
+ hv = mono_aligned_addr_hash (obj);
+ i = SGEN_CEMENT_HASH (hv);
SGEN_ASSERT (5, sgen_ptr_in_nursery (obj), "Can only cement pointers to nursery objects");