* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-#define GRAY_QUEUE_SECTION_SIZE (128 - 3)
-#define GRAY_QUEUE_LENGTH_LIMIT 64
+#include "config.h"
+#ifdef HAVE_SGEN_GC
-/*
- * This is a stack now instead of a queue, so the most recently added items are removed
- * first, improving cache locality, and keeping the stack size manageable.
- */
-typedef struct _GrayQueueSection GrayQueueSection;
-struct _GrayQueueSection {
- int end;
- GrayQueueSection *next, *prev;
- char *objects [GRAY_QUEUE_SECTION_SIZE];
-};
+#include "metadata/sgen-gc.h"
+#include "utils/mono-counters.h"
-static GrayQueueSection *gray_queue_start = NULL;
-static GrayQueueSection *gray_queue_end = NULL;
-
-static int gray_queue_balance = 0;
-static int num_gray_queue_sections = 0;
+#define GRAY_QUEUE_LENGTH_LIMIT 64
-static void
-gray_object_alloc_queue_section (void)
+void
+mono_sgen_gray_object_alloc_queue_section (SgenGrayQueue *queue)
{
GrayQueueSection *section;
- /* Use the previously allocated queue sections if possible */
- if (!gray_queue_end && gray_queue_start) {
- gray_queue_end = gray_queue_start;
- gray_queue_end->end = 0;
- return;
- }
- if (gray_queue_end && gray_queue_end->next) {
- gray_queue_end = gray_queue_end->next;
- gray_queue_end->end = 0;
- return;
- }
+ if (queue->alloc_prepare_func)
+ queue->alloc_prepare_func (queue);
- /* Allocate a new section */
- section = get_internal_mem (sizeof (GrayQueueSection), INTERNAL_MEM_GRAY_QUEUE);
- ++num_gray_queue_sections;
+ if (queue->free_list) {
+ /* Use the previously allocated queue sections if possible */
+ section = queue->free_list;
+ queue->free_list = section->next;
+ } else {
+ /* Allocate a new section */
+ section = mono_sgen_alloc_internal (INTERNAL_MEM_GRAY_QUEUE);
+ }
section->end = 0;
- section->next = NULL;
- section->prev = NULL;
/* Link it with the others */
- if (gray_queue_end) {
- gray_queue_end->next = section;
- section->prev = gray_queue_end;
- } else {
- g_assert (!gray_queue_start);
- gray_queue_start = section;
- }
- gray_queue_end = section;
+ section->next = queue->first;
+ queue->first = section;
}
-static void
-gray_object_free_queue_section (GrayQueueSection *section)
+void
+mono_sgen_gray_object_free_queue_section (GrayQueueSection *section)
{
- free_internal_mem (section, INTERNAL_MEM_GRAY_QUEUE);
- --num_gray_queue_sections;
-}
-
-static inline gboolean
-gray_object_queue_is_empty (void)
-{
- return gray_queue_end == NULL;
+ mono_sgen_free_internal (section, INTERNAL_MEM_GRAY_QUEUE);
}
/*
* The following two functions are called in the inner loops of the
* collector, so they need to be as fast as possible. We have macros
- * for them below.
+ * for them in sgen-gc.h.
*/
-static inline void
-gray_object_enqueue (char *obj)
+void
+mono_sgen_gray_object_enqueue (SgenGrayQueue *queue, char *obj)
{
DEBUG (9, g_assert (obj));
- if (G_UNLIKELY (!gray_queue_end || gray_queue_end->end == GRAY_QUEUE_SECTION_SIZE))
- gray_object_alloc_queue_section ();
- DEBUG (9, g_assert (gray_queue_end && gray_queue_end->end < GRAY_QUEUE_SECTION_SIZE));
- gray_queue_end->objects [gray_queue_end->end++] = obj;
+ if (G_UNLIKELY (!queue->first || queue->first->end == SGEN_GRAY_QUEUE_SECTION_SIZE))
+ mono_sgen_gray_object_alloc_queue_section (queue);
+ DEBUG (9, g_assert (queue->first && queue->first->end < SGEN_GRAY_QUEUE_SECTION_SIZE));
+ queue->first->objects [queue->first->end++] = obj;
- DEBUG (9, ++gray_queue_balance);
+ DEBUG (9, ++queue->balance);
}
-static inline char*
-gray_object_dequeue (void)
+char*
+mono_sgen_gray_object_dequeue (SgenGrayQueue *queue)
{
char *obj;
- if (gray_object_queue_is_empty ())
+ if (mono_sgen_gray_object_queue_is_empty (queue))
return NULL;
- DEBUG (9, g_assert (gray_queue_end->end));
+ DEBUG (9, g_assert (queue->first->end));
- obj = gray_queue_end->objects [--gray_queue_end->end];
+ obj = queue->first->objects [--queue->first->end];
- if (G_UNLIKELY (gray_queue_end->end == 0))
- gray_queue_end = gray_queue_end->prev;
+ if (G_UNLIKELY (queue->first->end == 0)) {
+ GrayQueueSection *section = queue->first;
+ queue->first = section->next;
+ section->next = queue->free_list;
+ queue->free_list = section;
+ }
- DEBUG (9, --gray_queue_balance);
+ DEBUG (9, --queue->balance);
return obj;
}
-#if MAX_DEBUG_LEVEL >= 9
-#define GRAY_OBJECT_ENQUEUE gray_object_enqueue
-#define GRAY_OBJECT_DEQUEUE(o) ((o) = gray_object_dequeue ())
-#else
-#define GRAY_OBJECT_ENQUEUE(o) do { \
- if (G_UNLIKELY (!gray_queue_end || gray_queue_end->end == GRAY_QUEUE_SECTION_SIZE)) \
- gray_object_alloc_queue_section (); \
- gray_queue_end->objects [gray_queue_end->end++] = (o); \
- } while (0)
-#define GRAY_OBJECT_DEQUEUE(o) do { \
- if (!gray_queue_end) { \
- (o) = NULL; \
- } else { \
- (o) = gray_queue_end->objects [--gray_queue_end->end]; \
- if (G_UNLIKELY (gray_queue_end->end == 0)) \
- gray_queue_end = gray_queue_end->prev; \
- } \
- } while (0)
-#endif
+GrayQueueSection*
+mono_sgen_gray_object_dequeue_section (SgenGrayQueue *queue)
+{
+ GrayQueueSection *section;
+
+ if (!queue->first)
+ return NULL;
+
+ section = queue->first;
+ queue->first = section->next;
+
+ section->next = NULL;
+
+ return section;
+}
-static void
-gray_object_queue_init (void)
+void
+mono_sgen_gray_object_enqueue_section (SgenGrayQueue *queue, GrayQueueSection *section)
+{
+ section->next = queue->first;
+ queue->first = section;
+}
+
+void
+mono_sgen_gray_object_queue_init (SgenGrayQueue *queue)
{
GrayQueueSection *section, *next;
int i;
- g_assert (gray_object_queue_is_empty ());
- g_assert (sizeof (GrayQueueSection) < MAX_FREELIST_SIZE);
- DEBUG (9, g_assert (gray_queue_balance == 0));
+ g_assert (mono_sgen_gray_object_queue_is_empty (queue));
+ DEBUG (9, g_assert (queue->balance == 0));
/* Free the extra sections allocated during the last collection */
i = 0;
- for (section = gray_queue_start; section && i < GRAY_QUEUE_LENGTH_LIMIT; section = section->next)
+ for (section = queue->free_list; section && i < GRAY_QUEUE_LENGTH_LIMIT - 1; section = section->next)
i ++;
- if (section) {
- if (section->prev)
- section->prev->next = NULL;
- for (; section; section = next) {
- next = section->next;
- gray_object_free_queue_section (section);
- }
+ if (!section)
+ return;
+ while (section->next) {
+ next = section->next;
+ section->next = next->next;
+ mono_sgen_gray_object_free_queue_section (next);
}
}
+
+void
+mono_sgen_gray_object_queue_init_with_alloc_prepare (SgenGrayQueue *queue, GrayQueueAllocPrepareFunc func, void *data)
+{
+ mono_sgen_gray_object_queue_init (queue);
+ queue->alloc_prepare_func = func;
+ queue->alloc_prepare_data = data;
+}
+
+#endif