return *sgen_card_table_get_shadow_card_address (address) != 0;
}
-gboolean
+static gboolean
sgen_card_table_region_begin_scanning (mword start, mword end)
{
while (start <= end) {
return FALSE;
}
+void
+sgen_card_table_get_card_data (guint8 *dest, mword address, mword cards)
+{
+ memcpy (dest, sgen_card_table_get_shadow_card_address (address), cards);
+}
+
#else
guint8*
return res;
}
-gboolean
+static gboolean
sgen_card_table_region_begin_scanning (mword start, mword size)
{
gboolean res = FALSE;
return res;
}
+void
+sgen_card_table_get_card_data (guint8 *dest, mword address, mword cards)
+{
+ int i;
+ guint8 *src = sgen_card_table_get_card_address (address);
+ memcpy (dest, src, cards);
+ memset (src, 0, cards);
+}
+
#endif
static gboolean
} while (address < end);
}
+static gboolean
+sgen_card_table_is_range_marked (guint8 *cards, mword size)
+{
+ mword start = 0;
+ while (start <= size) {
+ if (*cards++)
+ return TRUE;
+ start += CARD_SIZE_IN_BYTES;
+ }
+ return FALSE;
+
+}
+
static void
card_table_init (void)
{
void
-sgen_cardtable_scan_object (char *obj, mword obj_size, SgenGrayQueue *queue)
+sgen_cardtable_scan_object (char *obj, mword obj_size, guint8 *cards, SgenGrayQueue *queue)
{
MonoVTable *vt = (MonoVTable*)LOAD_VTABLE (obj);
MonoClass *klass = vt->klass;
char *elem, *card_end;
uintptr_t index;
- if (!sgen_card_table_card_begin_scanning ((mword)start))
+ if (cards) {
+ if (!*cards++)
+ continue;
+ } else if (!sgen_card_table_card_begin_scanning ((mword)start)) {
continue;
+ }
card_end = start + CARD_SIZE_IN_BYTES;
if (end < card_end)
}
}
} else {
- if (sgen_card_table_region_begin_scanning ((mword)obj, obj_size))
+ if (cards) {
+ if (sgen_card_table_is_range_marked (cards, obj_size))
+ major.minor_scan_object (obj, queue);
+ } else if (sgen_card_table_region_begin_scanning ((mword)obj, obj_size)) {
major.minor_scan_object (obj, queue);
+ }
}
}
void sgen_card_table_mark_address (mword address) MONO_INTERNAL;
void sgen_card_table_mark_range (mword address, mword size) MONO_INTERNAL;
gboolean sgen_card_table_card_begin_scanning (mword address) MONO_INTERNAL;
-gboolean sgen_card_table_region_begin_scanning (mword start, mword size) MONO_INTERNAL;
-void sgen_cardtable_scan_object (char *obj, mword obj_size, SgenGrayQueue *queue) MONO_INTERNAL;
+void sgen_cardtable_scan_object (char *obj, mword obj_size, guint8 *cards, SgenGrayQueue *queue) MONO_INTERNAL;
+void sgen_card_table_get_card_data (guint8 *dest, mword address, mword cards) MONO_INTERNAL;
typedef void (*sgen_cardtable_block_callback) (mword start, mword size);
#define CARD_BITS 9
LOSObject *obj;
for (obj = los_object_list; obj; obj = obj->next) {
- sgen_cardtable_scan_object (obj->data, obj->size, queue);
+ sgen_cardtable_scan_object (obj->data, obj->size, NULL, queue);
}
}
block_obj_size = block->obj_size;
start = block->block;
- for (i = 0; i < CARDS_PER_BLOCK; ++i, start += CARD_SIZE_IN_BYTES) {
- int index;
- char *obj, *end;
+ if (block_obj_size >= CARD_SIZE_IN_BYTES) {
+ guint8 cards [CARDS_PER_BLOCK];
+ char *obj = (char*)MS_BLOCK_OBJ (block, 0);
+ char *end = start + MS_BLOCK_SIZE;
+ char *base = sgen_card_table_align_pointer (obj);
- if (!sgen_card_table_card_begin_scanning ((mword)start))
- continue;
+ sgen_card_table_get_card_data (cards, (mword)start, CARDS_PER_BLOCK);
- end = start + CARD_SIZE_IN_BYTES;
- if (i == 0)
- index = 0;
- else
- index = MS_BLOCK_OBJ_INDEX (start, block);
-
- obj = (char*)MS_BLOCK_OBJ (block, index);
while (obj < end) {
- if (MS_OBJ_ALLOCED (obj, block))
- minor_scan_object (obj, queue);
+ if (MS_OBJ_ALLOCED (obj, block)) {
+ int card_offset = (obj - base) >> CARD_BITS;
+ sgen_cardtable_scan_object (obj, block_obj_size, cards + card_offset, queue);
+ }
obj += block_obj_size;
}
+ } else {
+ for (i = 0; i < CARDS_PER_BLOCK; ++i, start += CARD_SIZE_IN_BYTES) {
+ int index;
+ char *obj, *end;
+
+ if (!sgen_card_table_card_begin_scanning ((mword)start))
+ continue;
+
+ end = start + CARD_SIZE_IN_BYTES;
+ if (i == 0)
+ index = 0;
+ else
+ index = MS_BLOCK_OBJ_INDEX (start, block);
+
+ obj = (char*)MS_BLOCK_OBJ (block, index);
+ while (obj < end) {
+ if (MS_OBJ_ALLOCED (obj, block))
+ minor_scan_object (obj, queue);
+ obj += block_obj_size;
+ }
+ }
}
} END_FOREACH_BLOCK;
}