/*
- * 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"
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
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;
{
#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;
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));
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);
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));
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
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;
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;
}
}
}
-#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 */