[arm64] Add sgen support.
[mono.git] / mono / metadata / sgen-pinning.c
index dc50f2d168bc8958b328757f05b8ba9181a4f916..d0a38ef426eb94b8b90c82bcedd4490e3fc35ce2 100644 (file)
@@ -180,17 +180,14 @@ sgen_dump_pin_queue (void)
        }       
 }
 
-#define CEMENT_THRESHOLD       1000
-#define CEMENT_HASH_SIZE       61
-
 typedef struct _CementHashEntry CementHashEntry;
 struct _CementHashEntry {
        char *obj;
        unsigned int count;
 };
 
-static CementHashEntry cement_hash [CEMENT_HASH_SIZE];
-static CementHashEntry cement_hash_concurrent [CEMENT_HASH_SIZE];
+static CementHashEntry cement_hash [SGEN_CEMENT_HASH_SIZE];
+static CementHashEntry cement_hash_concurrent [SGEN_CEMENT_HASH_SIZE];
 
 static gboolean cement_enabled = TRUE;
 static gboolean cement_concurrent = FALSE;
@@ -249,7 +246,7 @@ sgen_cement_concurrent_finish (void)
 gboolean
 sgen_cement_lookup (char *obj)
 {
-       int i = mono_aligned_addr_hash (obj) % CEMENT_HASH_SIZE;
+       int i = mono_aligned_addr_hash (obj) % SGEN_CEMENT_HASH_SIZE;
 
        SGEN_ASSERT (5, sgen_ptr_in_nursery (obj), "Looking up cementing for non-nursery objects makes no sense");
 
@@ -261,14 +258,15 @@ sgen_cement_lookup (char *obj)
        if (cement_hash [i].obj != obj)
                return FALSE;
 
-       return cement_hash [i].count >= CEMENT_THRESHOLD;
+       return cement_hash [i].count >= SGEN_CEMENT_THRESHOLD;
 }
 
 gboolean
-sgen_cement_lookup_or_register (char *obj, gboolean concurrent_cementing)
+sgen_cement_lookup_or_register (char *obj)
 {
        int i;
        CementHashEntry *hash;
+       gboolean concurrent_cementing = sgen_concurrent_collection_in_progress ();
 
        if (!cement_enabled)
                return FALSE;
@@ -281,7 +279,17 @@ sgen_cement_lookup_or_register (char *obj, gboolean concurrent_cementing)
        else
                hash = cement_hash;
 
-       i = mono_aligned_addr_hash (obj) % CEMENT_HASH_SIZE;
+       /*
+        * 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;
 
        SGEN_ASSERT (5, sgen_ptr_in_nursery (obj), "Can only cement pointers to nursery objects");
 
@@ -292,16 +300,19 @@ sgen_cement_lookup_or_register (char *obj, gboolean concurrent_cementing)
                return FALSE;
        }
 
-       if (hash [i].count >= CEMENT_THRESHOLD)
+       if (hash [i].count >= SGEN_CEMENT_THRESHOLD)
                return TRUE;
 
        ++hash [i].count;
-#ifdef SGEN_BINARY_PROTOCOL
-       if (hash [i].count == CEMENT_THRESHOLD) {
+       if (hash [i].count == SGEN_CEMENT_THRESHOLD) {
+               if (G_UNLIKELY (MONO_GC_OBJ_CEMENTED_ENABLED())) {
+                       MonoVTable *vt G_GNUC_UNUSED = (MonoVTable*)SGEN_LOAD_VTABLE (obj);
+                       MONO_GC_OBJ_CEMENTED ((mword)obj, sgen_safe_object_get_size ((MonoObject*)obj),
+                                       vt->klass->name_space, vt->klass->name);
+               }
                binary_protocol_cement (obj, (gpointer)SGEN_LOAD_VTABLE (obj),
                                sgen_safe_object_get_size ((MonoObject*)obj));
        }
-#endif
 
        return FALSE;
 }
@@ -310,11 +321,11 @@ void
 sgen_cement_iterate (IterateObjectCallbackFunc callback, void *callback_data)
 {
        int i;
-       for (i = 0; i < CEMENT_HASH_SIZE; ++i) {
+       for (i = 0; i < SGEN_CEMENT_HASH_SIZE; ++i) {
                if (!cement_hash [i].count)
                        continue;
 
-               SGEN_ASSERT (5, cement_hash [i].count >= CEMENT_THRESHOLD, "Cementing hash inconsistent");
+               SGEN_ASSERT (5, cement_hash [i].count >= SGEN_CEMENT_THRESHOLD, "Cementing hash inconsistent");
 
                callback (cement_hash [i].obj, 0, callback_data);
        }
@@ -324,8 +335,8 @@ void
 sgen_cement_clear_below_threshold (void)
 {
        int i;
-       for (i = 0; i < CEMENT_HASH_SIZE; ++i) {
-               if (cement_hash [i].count < CEMENT_THRESHOLD) {
+       for (i = 0; i < SGEN_CEMENT_HASH_SIZE; ++i) {
+               if (cement_hash [i].count < SGEN_CEMENT_THRESHOLD) {
                        cement_hash [i].obj = NULL;
                        cement_hash [i].count = 0;
                }