Merge pull request #2820 from kumpera/license-change-rebased
[mono.git] / mono / sgen / sgen-pinning.c
index a94af9ddf4494db961697faac801a9273bece46b..eedd1f0343a93e720cac0838ec29ff70e8bd773e 100644 (file)
@@ -5,18 +5,7 @@
  * Copyright 2003-2010 Novell, Inc.
  * 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.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "config.h"
@@ -182,6 +171,7 @@ typedef struct _CementHashEntry CementHashEntry;
 struct _CementHashEntry {
        GCObject *obj;
        unsigned int count;
+       gboolean forced; /* if it should stay cemented after the finishing pause */
 };
 
 static CementHashEntry cement_hash [SGEN_CEMENT_HASH_SIZE];
@@ -197,10 +187,70 @@ sgen_cement_init (gboolean enabled)
 void
 sgen_cement_reset (void)
 {
-       memset (cement_hash, 0, sizeof (cement_hash));
+       int i;
+       for (i = 0; i < SGEN_CEMENT_HASH_SIZE; i++) {
+               if (cement_hash [i].forced) {
+                       cement_hash [i].forced = FALSE;
+               } else {
+                       cement_hash [i].obj = NULL;
+                       cement_hash [i].count = 0;
+               }
+       }
        binary_protocol_cement_reset ();
 }
 
+
+/*
+ * The pin_queue should be full and sorted, without entries from the cemented
+ * objects. We traverse the cement hash and check if each object is pinned in
+ * the pin_queue (the pin_queue contains entries between obj and obj+obj_len)
+ */
+void
+sgen_cement_force_pinned (void)
+{
+       int i;
+
+       if (!cement_enabled)
+               return;
+
+       for (i = 0; i < SGEN_CEMENT_HASH_SIZE; i++) {
+               GCObject *obj = cement_hash [i].obj;
+               size_t index;
+               if (!obj)
+                       continue;
+               if (cement_hash [i].count < SGEN_CEMENT_THRESHOLD)
+                       continue;
+               SGEN_ASSERT (0, !cement_hash [i].forced, "Why do we have a forced cemented object before forcing ?");
+
+               /* Returns the index of the target or of the first element greater than it */
+               index = sgen_pointer_queue_search (&pin_queue, obj);
+               if (index == pin_queue.next_slot)
+                       continue;
+               SGEN_ASSERT (0, pin_queue.data [index] >= (gpointer)obj, "Binary search should return a pointer greater than the search target");
+               if (pin_queue.data [index] < (gpointer)((char*)obj + sgen_safe_object_get_size (obj)))
+                       cement_hash [i].forced = TRUE;
+       }
+}
+
+gboolean
+sgen_cement_is_forced (GCObject *obj)
+{
+       guint hv = sgen_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");
+
+       if (!cement_enabled)
+               return FALSE;
+
+       if (!cement_hash [i].obj)
+               return FALSE;
+       if (cement_hash [i].obj != obj)
+               return FALSE;
+
+       return cement_hash [i].forced;
+}
+
 gboolean
 sgen_cement_lookup (GCObject *obj)
 {