X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fsgen%2Fsgen-array-list.c;h=2fd54d986d0d6ded4b26dc3efb5203198bd4d3ec;hb=2709ca7625d75e5b3cf8eac8a34b95395bd15c46;hp=f84868e0a6f5f8d8999ce2ffd4e7947884ad9d3a;hpb=b8893efbccd64f92c81082e42b8e480b74881927;p=mono.git diff --git a/mono/sgen/sgen-array-list.c b/mono/sgen/sgen-array-list.c index f84868e0a6f..2fd54d986d0 100644 --- a/mono/sgen/sgen-array-list.c +++ b/mono/sgen/sgen-array-list.c @@ -1,5 +1,6 @@ -/* - * sgen-array-list.c: A pointer array list that doesn't require reallocs +/** + * \file + * A pointer array list that doesn't require reallocs * * Copyright (C) 2016 Xamarin Inc * @@ -112,6 +113,32 @@ sgen_array_list_update_next_slot (SgenArrayList *array, guint32 new_index) } } +/* + * Extension for the array list that allows fast allocation and index based fetching + * of long lived memory of various sizes, without the need of realloc. Not thread safe. + */ +guint32 +sgen_array_list_alloc_block (SgenArrayList *array, guint32 slots_to_add) +{ + guint32 new_index = array->next_slot; + guint32 old_capacity = array->capacity; + + /* FIXME Don't allocate arrays that will be skipped */ + /* There are no empty arrays between next_slot and capacity because we allocate incrementally */ + while ((old_capacity - new_index) < slots_to_add) { + sgen_array_list_grow (array, old_capacity); + new_index = old_capacity; + old_capacity = array->capacity; + } + + SGEN_ASSERT (0, sgen_array_list_index_bucket (new_index) == sgen_array_list_index_bucket (new_index + slots_to_add - 1), + "We failed to allocate a continuous block of slots"); + + array->next_slot = new_index + slots_to_add; + /* The slot address will point to the allocated memory */ + return new_index; +} + guint32 sgen_array_list_add (SgenArrayList *array, gpointer ptr, int data, gboolean increase_size_before_set) { @@ -151,37 +178,56 @@ retry: } /* - * Removes all NULL pointers from the array. Not thread safe + * Does a linear search through the pointer array to find `ptr`. Returns the index if + * found, otherwise (guint32)-1. */ -void -sgen_array_list_remove_nulls (SgenArrayList *array) +guint32 +sgen_array_list_find (SgenArrayList *array, gpointer ptr) { - guint32 start = 0; volatile gpointer *slot; SGEN_ARRAY_LIST_FOREACH_SLOT (array, slot) { - if (*slot) - *sgen_array_list_get_slot (array, start++) = *slot; + if (*slot == ptr) + return __index; } SGEN_ARRAY_LIST_END_FOREACH_SLOT; + return (guint32)-1; +} - mono_memory_write_barrier (); - array->next_slot = start; +gboolean +sgen_array_list_default_cas_setter (volatile gpointer *slot, gpointer ptr, int data) +{ + if (InterlockedCompareExchangePointer (slot, ptr, NULL) == NULL) + return TRUE; + return FALSE; } -/* - * Does a linear search through the pointer array to find `ptr`. Returns the index if - * found, otherwise (guint32)-1. - */ -guint32 -sgen_array_list_find (SgenArrayList *array, gpointer ptr) +gboolean +sgen_array_list_default_is_slot_set (volatile gpointer *slot) +{ + return *slot != NULL; +} + +/* Removes all NULL pointers from the array. Not thread safe */ +void +sgen_array_list_remove_nulls (SgenArrayList *array) { + guint32 start = 0; volatile gpointer *slot; + gboolean skipped = FALSE; SGEN_ARRAY_LIST_FOREACH_SLOT (array, slot) { - if (*slot == ptr) - return __index; + if (*slot) { + *sgen_array_list_get_slot (array, start++) = *slot; + if (skipped) + *slot = NULL; + } else { + skipped = TRUE; + } } SGEN_ARRAY_LIST_END_FOREACH_SLOT; - return (guint32)-1; + + mono_memory_write_barrier (); + array->next_slot = start; + array->slot_hint = start; } #endif