Merge pull request #654 from alesliehughes/master
[mono.git] / mono / metadata / sgen-los.c
index c00611469abff28ce578593e461096a8947cfdbf..b273a5ab822bd0cf5f35c3a3590f6c5836723fff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * sgen-los.c: Simple generational GC.
+ * sgen-los.c: Large objects space.
  *
  * Author:
  *     Paolo Molaro (lupus@ximian.com)
  * Copyright (c) 1996 by Silicon Graphics.  All rights reserved.
  * Copyright (c) 1998 by Fergus Henderson.  All rights reserved.
  * Copyright (c) 2000-2004 by Hewlett-Packard Company.  All rights reserved.
- *
- * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
- * OR IMPLIED.  ANY USE IS AT YOUR OWN RISK.
- *
- * Permission is hereby granted to use or copy this program
- * for any purpose,  provided the above notices are retained on all copies.
- * Permission to modify the code and to distribute modified code is granted,
- * provided the above notices are retained, and a notice that the code was
- * modified is included with the above copyright notice.
- *
- *
  * Copyright 2001-2003 Ximian, Inc
  * Copyright 2003-2010 Novell, Inc.
+ * Copyright (C) 2012 Xamarin Inc
  *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
+ * 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;
  *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
+ * 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.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * 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.
  */
 
 #include "config.h"
@@ -94,7 +78,6 @@ static LOSSection *los_sections = NULL;
 static LOSFreeChunks *los_fast_free_lists [LOS_NUM_FAST_SIZES]; /* 0 is for larger sizes */
 static mword los_num_objects = 0;
 static int los_num_sections = 0;
-static mword next_los_collection = 2*1024*1024; /* 2 MB, need to tune */
 
 //#define USE_MALLOC
 //#define LOS_CONSISTENCY_CHECK
@@ -245,7 +228,7 @@ get_los_section_memory (size_t size)
        if (!sgen_memgov_try_alloc_space (LOS_SECTION_SIZE, SPACE_LOS))
                return NULL;
 
-       section = sgen_alloc_os_memory_aligned (LOS_SECTION_SIZE, LOS_SECTION_SIZE, TRUE);
+       section = sgen_alloc_os_memory_aligned (LOS_SECTION_SIZE, LOS_SECTION_SIZE, SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE, NULL);
 
        if (!section)
                return NULL;
@@ -309,7 +292,7 @@ sgen_los_free_object (LOSObject *obj)
 {
 #ifndef LOS_DUMMY
        size_t size = obj->size;
-       DEBUG (4, fprintf (gc_debug_file, "Freed large object %p, size %lu\n", obj->data, (unsigned long)obj->size));
+       SGEN_LOG (4, "Freed large object %p, size %lu", obj->data, (unsigned long)obj->size);
        binary_protocol_empty (obj->data, obj->size);
 
        los_memory_usage -= size;
@@ -324,7 +307,7 @@ sgen_los_free_object (LOSObject *obj)
                size += sizeof (LOSObject);
                size += pagesize - 1;
                size &= ~(pagesize - 1);
-               sgen_free_os_memory (obj, size);
+               sgen_free_os_memory (obj, size, SGEN_ALLOC_HEAP);
                sgen_memgov_release_space (size, SPACE_LOS);
        } else {
                free_los_section_memory (obj, size + sizeof (LOSObject));
@@ -349,10 +332,11 @@ sgen_los_alloc_large_inner (MonoVTable *vtable, size_t size)
        void **vtslot;
 
        g_assert (size > SGEN_MAX_SMALL_OBJ_SIZE);
+       g_assert ((size & 1) == 0);
 
 #ifdef LOS_DUMMY
        if (!los_segment)
-               los_segment = sgen_alloc_os_memory (LOS_SEGMENT_SIZE, TRUE);
+               los_segment = sgen_alloc_os_memory (LOS_SEGMENT_SIZE, SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE, NULL);
        los_segment_index = ALIGN_UP (los_segment_index);
 
        obj = (LOSObject*)(los_segment + los_segment_index);
@@ -373,9 +357,7 @@ sgen_los_alloc_large_inner (MonoVTable *vtable, size_t size)
                alloc_size += pagesize - 1;
                alloc_size &= ~(pagesize - 1);
                if (sgen_memgov_try_alloc_space (alloc_size, SPACE_LOS)) {
-                       obj = sgen_alloc_os_memory (alloc_size, TRUE);
-                       if (obj)
-                               obj->huge_object = TRUE;
+                       obj = sgen_alloc_os_memory (alloc_size, SGEN_ALLOC_HEAP | SGEN_ALLOC_ACTIVATE, NULL);
                }
        } else {
                obj = get_los_section_memory (size + sizeof (LOSObject));
@@ -395,7 +377,7 @@ sgen_los_alloc_large_inner (MonoVTable *vtable, size_t size)
        los_object_list = obj;
        los_memory_usage += size;
        los_num_objects++;
-       DEBUG (4, fprintf (gc_debug_file, "Allocated large object %p, vtable: %p (%s), size: %zd\n", obj->data, vtable, vtable->klass->name, size));
+       SGEN_LOG (4, "Allocated large object %p, vtable: %p (%s), size: %zd", obj->data, vtable, vtable->klass->name, size);
        binary_protocol_alloc (obj->data, vtable, size);
 
 #ifdef LOS_CONSISTENCY_CHECK
@@ -424,7 +406,7 @@ sgen_los_sweep (void)
                                prev->next = next;
                        else
                                los_sections = next;
-                       sgen_free_os_memory (section, LOS_SECTION_SIZE);
+                       sgen_free_os_memory (section, LOS_SECTION_SIZE, SGEN_ALLOC_HEAP);
                        sgen_memgov_release_space (LOS_SECTION_SIZE, SPACE_LOS);
                        section = next;
                        --los_num_sections;
@@ -510,23 +492,29 @@ mono_sgen_los_describe_pointer (char *ptr)
 
        for (obj = los_object_list; obj; obj = obj->next) {
                MonoVTable *vtable;
+               const char *los_kind;
+               mword size;
+               gboolean pinned;
+
                if (obj->data > ptr || obj->data + obj->size <= ptr)
                        continue;
 
-               if (obj->size > LOS_SECTION_OBJECT_LIMIT)
-                       fprintf (gc_debug_file, "huge-los-ptr ");
+               size = sgen_los_object_size (obj);
+               pinned = sgen_los_object_is_pinned (obj->data);
+
+               if (size > LOS_SECTION_OBJECT_LIMIT)
+                       los_kind = "huge-los-ptr";
                else
-                       fprintf (gc_debug_file, "los-ptr ");
+                       los_kind = "los-ptr";
 
                vtable = (MonoVTable*)SGEN_LOAD_VTABLE (obj->data);
 
-               if (obj->data == ptr)
-                       fprintf (gc_debug_file, "(object %s.%s size %d)", 
-                                        vtable->klass->name_space, vtable->klass->name, (int)obj->size);
-               else
-                       fprintf (gc_debug_file, "(interior-ptr offset %td of %p (%s.%s) size %d)",
-                                        ptr - obj->data, obj->data,
-                                        vtable->klass->name_space, vtable->klass->name, (int)obj->size);
+               if (obj->data == ptr) {
+                       SGEN_LOG (0, "%s (size %td pin %d)\n", los_kind, size, pinned ? 1 : 0);
+               } else {
+                       SGEN_LOG (0, "%s (interior-ptr offset %td size %td pin %d)",
+                                       los_kind, ptr - obj->data, size, pinned ? 1 : 0);
+               }
 
                return TRUE;
        }
@@ -544,16 +532,65 @@ sgen_los_iterate_live_block_ranges (sgen_cardtable_block_callback callback)
        }
 }
 
-#ifdef SGEN_HAVE_CARDTABLE
 void
-sgen_los_scan_card_table (SgenGrayQueue *queue)
+sgen_los_scan_card_table (gboolean mod_union, SgenGrayQueue *queue)
 {
        LOSObject *obj;
 
        for (obj = los_object_list; obj; obj = obj->next) {
-               sgen_cardtable_scan_object (obj->data, obj->size, NULL, queue);
+               guint8 *cards = NULL;
+               if (mod_union) {
+                       cards = obj->cardtable_mod_union;
+                       g_assert (cards);
+               }
+
+               sgen_cardtable_scan_object (obj->data, obj->size, cards, mod_union, queue);
        }
 }
-#endif
+
+void
+sgen_los_update_cardtable_mod_union (void)
+{
+       LOSObject *obj;
+
+       for (obj = los_object_list; obj; obj = obj->next) {
+               obj->cardtable_mod_union = sgen_card_table_update_mod_union (obj->cardtable_mod_union,
+                               obj->data, obj->size, NULL);
+       }
+}
+
+mword
+sgen_los_object_size (LOSObject *obj)
+{
+       return obj->size & ~1L;
+}
+
+LOSObject*
+sgen_los_header_for_object (char *data)
+{
+       return (LOSObject*)(data - sizeof (LOSObject));
+}
+
+void
+sgen_los_pin_object (char *data)
+{
+       LOSObject *obj = sgen_los_header_for_object (data);
+       obj->size = obj->size | 1;
+       binary_protocol_pin (data, (gpointer)SGEN_LOAD_VTABLE (data), sgen_safe_object_get_size ((MonoObject*)data));
+}
+
+void
+sgen_los_unpin_object (char *data)
+{
+       LOSObject *obj = sgen_los_header_for_object (data);
+       obj->size = sgen_los_object_size (obj);
+}
+
+gboolean
+sgen_los_object_is_pinned (char *data)
+{
+       LOSObject *obj = sgen_los_header_for_object (data);
+       return obj->size & 1;
+}
 
 #endif /* HAVE_SGEN_GC */