Enable monitor enter/exit wrappers under sgen.
[mono.git] / mono / metadata / sgen-los.c
index 6ff9364a1fd8fbb25c8465d991394a4c86f634bf..8d72007950e5a04d94832884109699f5d39aa46c 100644 (file)
  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#ifdef HAVE_SGEN_GC
+
+#include "metadata/sgen-gc.h"
+#include "metadata/sgen-protocol.h"
+#include "metadata/sgen-cardtable.h"
+#include "utils/mono-mmap.h"
+
 #define LOS_SECTION_SIZE       (1024 * 1024)
 
 /*
 
 #define LOS_NUM_FAST_SIZES             32
 
-typedef struct _LOSObject LOSObject;
-struct _LOSObject {
-       LOSObject *next;
-       mword size; /* this is the object size */
-       guint16 role;
-       int dummy; /* to have a sizeof (LOSObject) a multiple of ALLOC_ALIGN  and data starting at same alignment */
-       char data [MONO_ZERO_LEN_ARRAY];
-};
-
 typedef struct _LOSFreeChunks LOSFreeChunks;
 struct _LOSFreeChunks {
        LOSFreeChunks *next_size;
@@ -86,11 +84,11 @@ struct _LOSSection {
        unsigned char *free_chunk_map;
 };
 
+LOSObject *los_object_list = NULL;
+mword los_memory_usage = 0;
+
 static LOSSection *los_sections = NULL;
-static LOSObject *los_object_list = NULL;
 static LOSFreeChunks *los_fast_free_lists [LOS_NUM_FAST_SIZES]; /* 0 is for larger sizes */
-static mword los_memory_usage = 0;
-static mword last_los_memory_usage = 0;
 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 */
@@ -241,6 +239,9 @@ get_los_section_memory (size_t size)
        if (free_chunks)
                return (LOSObject*)free_chunks;
 
+       if (!mono_sgen_try_alloc_space (LOS_SECTION_SIZE, SPACE_LOS))
+               return NULL;
+
        section = mono_sgen_alloc_os_memory_aligned (LOS_SECTION_SIZE, LOS_SECTION_SIZE, TRUE);
 
        free_chunks = (LOSFreeChunks*)((char*)section + LOS_CHUNK_SIZE);
@@ -295,8 +296,10 @@ free_los_section_memory (LOSObject *obj, size_t size)
        add_free_chunk ((LOSFreeChunks*)obj, size);
 }
 
-static void
-free_large_object (LOSObject *obj)
+static int pagesize;
+
+void
+mono_sgen_los_free_object (LOSObject *obj)
 {
 #ifndef LOS_DUMMY
        size_t size = obj->size;
@@ -310,10 +313,13 @@ free_large_object (LOSObject *obj)
        free (obj);
 #else
        if (size > LOS_SECTION_OBJECT_LIMIT) {
+               if (!pagesize)
+                       pagesize = mono_pagesize ();
                size += sizeof (LOSObject);
                size += pagesize - 1;
                size &= ~(pagesize - 1);
                mono_sgen_free_os_memory (obj, size);
+               mono_sgen_release_space (size, SPACE_LOS);
        } else {
                free_los_section_memory (obj, size + sizeof (LOSObject));
 #ifdef LOS_CONSISTENCY_CHECKS
@@ -330,13 +336,13 @@ free_large_object (LOSObject *obj)
  * They don't move, so there is no need to pin them during collection
  * and we avoid the memcpy overhead.
  */
-static void* __attribute__((noinline))
-alloc_large_inner (MonoVTable *vtable, size_t size)
+void*
+mono_sgen_los_alloc_large_inner (MonoVTable *vtable, size_t size)
 {
-       LOSObject *obj;
+       LOSObject *obj = NULL;
        void **vtslot;
 
-       g_assert (size > MAX_SMALL_OBJ_SIZE);
+       g_assert (size > SGEN_MAX_SMALL_OBJ_SIZE);
 
 #ifdef LOS_DUMMY
        if (!los_segment)
@@ -347,11 +353,9 @@ alloc_large_inner (MonoVTable *vtable, size_t size)
        los_segment_index += size + sizeof (LOSObject);
        g_assert (los_segment_index <= LOS_SEGMENT_SIZE);
 #else
-       if (need_major_collection ()) {
+       if (mono_sgen_need_major_collection (size)) {
                DEBUG (4, fprintf (gc_debug_file, "Should trigger major collection: req size %zd (los already: %lu, limit: %lu)\n", size, (unsigned long)los_memory_usage, (unsigned long)next_los_collection));
-               stop_world ();
-               major_collection ("LOS overflow");
-               restart_world ();
+               sgen_collect_major_no_lock ("LOS overflow");
        }
 
 #ifdef USE_MALLOC
@@ -360,19 +364,25 @@ alloc_large_inner (MonoVTable *vtable, size_t size)
 #else
        if (size > LOS_SECTION_OBJECT_LIMIT) {
                size_t alloc_size = size;
+               if (!pagesize)
+                       pagesize = mono_pagesize ();
                alloc_size += sizeof (LOSObject);
                alloc_size += pagesize - 1;
                alloc_size &= ~(pagesize - 1);
-               /* FIXME: handle OOM */
-               obj = mono_sgen_alloc_os_memory (alloc_size, TRUE);
+               if (mono_sgen_try_alloc_space (alloc_size, SPACE_LOS)) {
+                       obj = mono_sgen_alloc_os_memory (alloc_size, TRUE);
+                       obj->huge_object = TRUE;
+               }
        } else {
                obj = get_los_section_memory (size + sizeof (LOSObject));
-               memset (obj, 0, size + sizeof (LOSObject));
+               if (obj)
+                       memset (obj, 0, size + sizeof (LOSObject));
        }
 #endif
 #endif
-
-       g_assert (!((mword)obj->data & (ALLOC_ALIGN - 1)));
+       if (!obj)
+               return NULL;
+       g_assert (!((mword)obj->data & (SGEN_ALLOC_ALIGN - 1)));
        obj->size = size;
        vtslot = (void**)obj->data;
        *vtslot = vtable;
@@ -391,8 +401,8 @@ alloc_large_inner (MonoVTable *vtable, size_t size)
        return obj->data;
 }
 
-static void
-los_sweep (void)
+void
+mono_sgen_los_sweep (void)
 {
        LOSSection *section, *prev;
        int i;
@@ -411,6 +421,7 @@ los_sweep (void)
                        else
                                los_sections = next;
                        mono_sgen_free_os_memory (section, LOS_SECTION_SIZE);
+                       mono_sgen_release_space (LOS_SECTION_SIZE, SPACE_LOS);
                        section = next;
                        --los_num_sections;
                        continue;
@@ -449,3 +460,54 @@ los_sweep (void)
 
        g_assert (los_num_sections == num_sections);
 }
+
+gboolean
+mono_sgen_ptr_is_in_los (char *ptr, char **start)
+{
+       LOSObject *obj;
+
+       *start = NULL;
+       for (obj = los_object_list; obj; obj = obj->next) {
+               char *end = obj->data + obj->size;
+
+               if (ptr >= obj->data && ptr < end) {
+                       *start = obj->data;
+                       return TRUE;
+               }
+       }
+       return FALSE;
+}
+
+void
+mono_sgen_los_iterate_objects (IterateObjectCallbackFunc cb, void *user_data)
+{
+       LOSObject *obj;
+
+       for (obj = los_object_list; obj; obj = obj->next)
+               cb (obj->data, obj->size, user_data);
+}
+
+void
+mono_sgen_los_iterate_live_block_ranges (sgen_cardtable_block_callback callback)
+{
+       LOSObject *obj;
+       for (obj = los_object_list; obj; obj = obj->next) {
+               MonoVTable *vt = (MonoVTable*)SGEN_LOAD_VTABLE (obj->data);
+               if (SGEN_VTABLE_HAS_REFERENCES (vt))
+                       callback ((mword)obj->data, (mword)obj->size);
+       }
+}
+
+#ifdef SGEN_HAVE_CARDTABLE
+void
+mono_sgen_los_scan_card_table (SgenGrayQueue *queue)
+{
+       LOSObject *obj;
+
+       for (obj = los_object_list; obj; obj = obj->next) {
+               sgen_cardtable_scan_object (obj->data, obj->size, NULL, queue);
+       }
+}
+#endif
+
+#endif /* HAVE_SGEN_GC */