/** * \file * Object scanning in the nursery collectors. * * Copyright 2001-2003 Ximian, Inc * Copyright 2003-2010 Novell, Inc. * Copyright (C) 2012 Xamarin Inc * * Licensed under the MIT license. See LICENSE file in the project root for full license information. */ extern guint64 stat_scan_object_called_nursery; #undef SERIAL_SCAN_OBJECT #undef SERIAL_SCAN_VTYPE #undef SERIAL_SCAN_PTR_FIELD #undef SERIAL_DRAIN_GRAY_STACK #if defined(SGEN_SIMPLE_NURSERY) #ifdef SGEN_SIMPLE_PAR_NURSERY #ifdef SGEN_CONCURRENT_MAJOR #define SERIAL_SCAN_OBJECT simple_par_nursery_serial_with_concurrent_major_scan_object #define SERIAL_SCAN_VTYPE simple_par_nursery_serial_with_concurrent_major_scan_vtype #define SERIAL_SCAN_PTR_FIELD simple_par_nursery_serial_with_concurrent_major_scan_ptr_field #define SERIAL_DRAIN_GRAY_STACK simple_par_nursery_serial_with_concurrent_major_drain_gray_stack #else #define SERIAL_SCAN_OBJECT simple_par_nursery_serial_scan_object #define SERIAL_SCAN_VTYPE simple_par_nursery_serial_scan_vtype #define SERIAL_SCAN_PTR_FIELD simple_par_nursery_serial_scan_ptr_field #define SERIAL_DRAIN_GRAY_STACK simple_par_nursery_serial_drain_gray_stack #endif #else #ifdef SGEN_CONCURRENT_MAJOR #define SERIAL_SCAN_OBJECT simple_nursery_serial_with_concurrent_major_scan_object #define SERIAL_SCAN_VTYPE simple_nursery_serial_with_concurrent_major_scan_vtype #define SERIAL_SCAN_PTR_FIELD simple_nursery_serial_with_concurrent_major_scan_ptr_field #define SERIAL_DRAIN_GRAY_STACK simple_nursery_serial_with_concurrent_major_drain_gray_stack #else #define SERIAL_SCAN_OBJECT simple_nursery_serial_scan_object #define SERIAL_SCAN_VTYPE simple_nursery_serial_scan_vtype #define SERIAL_SCAN_PTR_FIELD simple_nursery_serial_scan_ptr_field #define SERIAL_DRAIN_GRAY_STACK simple_nursery_serial_drain_gray_stack #endif #endif #elif defined (SGEN_SPLIT_NURSERY) #ifdef SGEN_CONCURRENT_MAJOR #define SERIAL_SCAN_OBJECT split_nursery_serial_with_concurrent_major_scan_object #define SERIAL_SCAN_VTYPE split_nursery_serial_with_concurrent_major_scan_vtype #define SERIAL_SCAN_PTR_FIELD split_nursery_serial_with_concurrent_major_scan_ptr_field #define SERIAL_DRAIN_GRAY_STACK split_nursery_serial_with_concurrent_major_drain_gray_stack #else #define SERIAL_SCAN_OBJECT split_nursery_serial_scan_object #define SERIAL_SCAN_VTYPE split_nursery_serial_scan_vtype #define SERIAL_SCAN_PTR_FIELD split_nursery_serial_scan_ptr_field #define SERIAL_DRAIN_GRAY_STACK split_nursery_serial_drain_gray_stack #endif #else #error "No nursery configuration specified" #endif #undef HANDLE_PTR /* Global remsets are handled in SERIAL_COPY_OBJECT_FROM_OBJ */ #define HANDLE_PTR(ptr,obj) do { \ void *__old = *(ptr); \ SGEN_OBJECT_LAYOUT_STATISTICS_MARK_BITMAP ((obj), (ptr)); \ binary_protocol_scan_process_reference ((full_object), (ptr), __old); \ if (__old) { \ SERIAL_COPY_OBJECT_FROM_OBJ ((ptr), queue); \ SGEN_COND_LOG (9, __old != *(ptr), "Overwrote field at %p with %p (was: %p)", (ptr), *(ptr), __old); \ } \ } while (0) static void SERIAL_SCAN_OBJECT (GCObject *full_object, SgenDescriptor desc, SgenGrayQueue *queue) { char *start = (char*)full_object; SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP; #ifdef HEAVY_STATISTICS sgen_descriptor_count_scanned_object (desc); #endif SGEN_ASSERT (9, sgen_get_current_collection_generation () == GENERATION_NURSERY, "Must not use minor scan during major collection."); #define SCAN_OBJECT_PROTOCOL #include "sgen-scan-object.h" SGEN_OBJECT_LAYOUT_STATISTICS_COMMIT_BITMAP; HEAVY_STAT (++stat_scan_object_called_nursery); } static void SERIAL_SCAN_VTYPE (GCObject *full_object, char *start, SgenDescriptor desc, SgenGrayQueue *queue BINARY_PROTOCOL_ARG (size_t size)) { SGEN_OBJECT_LAYOUT_STATISTICS_DECLARE_BITMAP; SGEN_ASSERT (9, sgen_get_current_collection_generation () == GENERATION_NURSERY, "Must not use minor scan during major collection."); /* The descriptors include info about the MonoObject header as well */ start -= SGEN_CLIENT_OBJECT_HEADER_SIZE; #define SCAN_OBJECT_NOVTABLE #define SCAN_OBJECT_PROTOCOL #include "sgen-scan-object.h" } static void SERIAL_SCAN_PTR_FIELD (GCObject *full_object, GCObject **ptr, SgenGrayQueue *queue) { HANDLE_PTR (ptr, NULL); } static gboolean SERIAL_DRAIN_GRAY_STACK (SgenGrayQueue *queue) { #ifdef SGEN_SIMPLE_PAR_NURSERY int i; /* * We do bounded iteration so we can switch to optimized context * when we are the last worker remaining. */ for (i = 0; i < 32; i++) { #else for (;;) { #endif GCObject *obj; SgenDescriptor desc; #ifdef SGEN_SIMPLE_PAR_NURSERY GRAY_OBJECT_DEQUEUE_PARALLEL (queue, &obj, &desc); #else GRAY_OBJECT_DEQUEUE_SERIAL (queue, &obj, &desc); #endif if (!obj) return TRUE; SERIAL_SCAN_OBJECT (obj, desc, queue); } return FALSE; } #define FILL_MINOR_COLLECTOR_SCAN_OBJECT(ops) do { \ (ops)->scan_object = SERIAL_SCAN_OBJECT; \ (ops)->scan_vtype = SERIAL_SCAN_VTYPE; \ (ops)->scan_ptr_field = SERIAL_SCAN_PTR_FIELD; \ (ops)->drain_gray_stack = SERIAL_DRAIN_GRAY_STACK; \ } while (0)