Skip to content

Commit b23643d

Browse files
committed
block_array container for all_objects in liveness
1 parent 4990702 commit b23643d

File tree

1 file changed

+109
-21
lines changed

1 file changed

+109
-21
lines changed

mono/metadata/unity-liveness.c

Lines changed: 109 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,38 @@ typedef struct _custom_growable_array {
1515
guint size; // reserved
1616
} custom_growable_array;
1717

18+
#define k_block_size (8 * 1024)
19+
#define k_array_elements_per_block ((k_block_size - 2 * sizeof (guint) - sizeof (gpointer)) / sizeof (gpointer))
20+
21+
typedef struct _custom_array_block custom_array_block;
22+
23+
typedef struct _custom_array_block {
24+
gpointer *next_item;
25+
custom_array_block *next_block;
26+
gpointer p_data[k_array_elements_per_block];
27+
} custom_array_block;
28+
29+
typedef struct _custom_block_array_iterator custom_block_array_iterator;
30+
31+
typedef struct _custom_growable_block_array {
32+
custom_array_block *first_block;
33+
custom_array_block *current_block;
34+
custom_block_array_iterator *iterator;
35+
} custom_growable_block_array;
36+
37+
typedef struct _custom_block_array_iterator {
38+
custom_growable_block_array *array;
39+
custom_array_block *current_block;
40+
gpointer *current_position;
41+
} custom_block_array_iterator;
42+
43+
1844
typedef void (*register_object_callback) (gpointer *arr, int size, void *callback_userdata);
1945
typedef void (*WorldStateChanged) ();
2046
typedef void *(*ReallocateArray) (void *ptr, int size, void *callback_userdata);
2147

2248
struct _LivenessState {
23-
gint first_index_in_all_objects;
24-
custom_growable_array *all_objects;
49+
custom_growable_block_array *all_objects;
2550

2651
MonoClass *filter;
2752

@@ -32,9 +57,73 @@ struct _LivenessState {
3257

3358
register_object_callback filter_callback;
3459
ReallocateArray reallocateArray;
35-
guint traverse_depth; // track recursion. Prevent stack overflow by limiting recurion
60+
guint traverse_depth; // track recursion. Prevent stack overflow by limiting recursion
3661
};
3762

63+
custom_growable_block_array *
64+
block_array_create (LivenessState *state)
65+
{
66+
custom_growable_block_array *array = g_new0 (custom_growable_block_array, 1);
67+
array->current_block = state->reallocateArray (NULL, k_block_size, state->callback_userdata);
68+
array->current_block->next_block = NULL;
69+
array->current_block->next_item = array->current_block->p_data;
70+
array->first_block = array->current_block;
71+
72+
array->iterator = g_new0 (custom_block_array_iterator, 1);
73+
array->iterator->array = array;
74+
array->iterator->current_block = array->first_block;
75+
array->iterator->current_position = array->first_block->p_data;
76+
return array;
77+
}
78+
79+
void
80+
block_array_push_back (custom_growable_block_array *block_array, gpointer value, LivenessState *state)
81+
{
82+
if (block_array->current_block->next_item == block_array->current_block->p_data + k_array_elements_per_block) {
83+
block_array->current_block->next_block = state->reallocateArray (NULL, k_block_size, state->callback_userdata);
84+
block_array->current_block = block_array->current_block->next_block;
85+
block_array->current_block->next_block = NULL;
86+
block_array->current_block->next_item = block_array->current_block->p_data;
87+
}
88+
*block_array->current_block->next_item++ = value;
89+
}
90+
91+
void
92+
block_array_reset_iterator (custom_growable_block_array *array)
93+
{
94+
array->iterator->current_block = array->first_block;
95+
array->iterator->current_position = array->first_block->p_data;
96+
}
97+
98+
gpointer
99+
block_array_next (custom_growable_block_array *block_array)
100+
{
101+
custom_block_array_iterator *iterator = block_array->iterator;
102+
if (iterator->current_position != iterator->current_block->next_item)
103+
return *iterator->current_position++;
104+
if (iterator->current_block->next_block == NULL)
105+
return NULL;
106+
iterator->current_block = iterator->current_block->next_block;
107+
iterator->current_position = iterator->current_block->p_data;
108+
if (iterator->current_position == iterator->current_block->next_item)
109+
return NULL;
110+
return *iterator->current_position++;
111+
}
112+
113+
void
114+
block_array_destroy (custom_growable_block_array *block_array, LivenessState *state)
115+
{
116+
custom_array_block *block = block_array->first_block;
117+
while (block != NULL) {
118+
void *data_block = block;
119+
block = block->next_block;
120+
state->reallocateArray (data_block, 0, state->callback_userdata);
121+
}
122+
g_free (block_array->iterator);
123+
g_free (block_array);
124+
}
125+
126+
38127
#define array_at_index(array, index) (array)->pdata[(index)]
39128

40129
#if defined(HAVE_SGEN_GC)
@@ -88,7 +177,7 @@ array_create (LivenessState *state, guint reserved_size)
88177
}
89178

90179
void
91-
array_destroy (LivenessState *state, custom_growable_array *array)
180+
array_destroy (custom_growable_array *array, LivenessState *state)
92181
{
93182
array->pdata = state->reallocateArray (array->pdata, 0, state->callback_userdata);
94183
g_free (array);
@@ -177,7 +266,6 @@ mono_filter_objects (LivenessState *state);
177266
void
178267
mono_reset_state (LivenessState *state)
179268
{
180-
state->first_index_in_all_objects = state->all_objects->len;
181269
array_clear (state->process_array);
182270
}
183271

@@ -230,9 +318,7 @@ mono_add_process_object (MonoObject *object, LivenessState *state)
230318
if (object && !IS_MARKED (object)) {
231319
gboolean has_references = GET_VTABLE (object)->klass->has_references;
232320
if (has_references || should_process_value (object, state->filter)) {
233-
if (array_is_full (state->all_objects))
234-
array_safe_grow (state, state->all_objects);
235-
array_push_back (state->all_objects, object);
321+
block_array_push_back (state->all_objects, object, state);
236322
MARK_OBJ (object);
237323
}
238324
// Check if klass has further references - if not skip adding
@@ -262,7 +348,7 @@ mono_field_can_contain_references (MonoClassField *field)
262348
static gboolean
263349
mono_traverse_object_internal (MonoObject *object, gboolean isStruct, MonoClass *klass, LivenessState *state)
264350
{
265-
int i;
351+
guint32 i;
266352
MonoClassField *field;
267353
MonoClass *p;
268354
gboolean added_objects = FALSE;
@@ -362,7 +448,7 @@ mono_traverse_array (MonoArray *array, LivenessState *state)
362448
gboolean has_references;
363449
MonoObject *object = (MonoObject *)array;
364450
MonoClass *element_class;
365-
size_t elementClassSize;
451+
int32_t elementClassSize;
366452
size_t array_length;
367453

368454
g_assert (object);
@@ -409,15 +495,16 @@ mono_filter_objects (LivenessState *state)
409495
gpointer filtered_objects[64];
410496
gint num_objects = 0;
411497

412-
int i = state->first_index_in_all_objects;
413-
for (; i < state->all_objects->len; i++) {
414-
MonoObject *object = state->all_objects->pdata[i];
498+
gpointer value = block_array_next (state->all_objects);
499+
while (value != NULL) {
500+
MonoObject *object = value;
415501
if (should_process_value (object, state->filter))
416502
filtered_objects[num_objects++] = object;
417503
if (num_objects == 64) {
418504
state->filter_callback (filtered_objects, 64, state->callback_userdata);
419505
num_objects = 0;
420506
}
507+
value = block_array_next (state->all_objects);
421508
}
422509

423510
if (num_objects != 0)
@@ -433,7 +520,7 @@ mono_filter_objects (LivenessState *state)
433520
void
434521
mono_unity_liveness_calculation_from_statics (LivenessState *liveness_state)
435522
{
436-
int i, j;
523+
guint i, j;
437524
MonoDomain *domain = mono_domain_get ();
438525

439526
mono_reset_state (liveness_state);
@@ -531,15 +618,14 @@ mono_unity_liveness_allocate_struct (MonoClass *filter, guint max_count, registe
531618
state = g_new0 (LivenessState, 1);
532619
max_count = max_count < 1000 ? 1000 : max_count;
533620

534-
state->first_index_in_all_objects = 0;
535621
state->filter = filter;
536622
state->traverse_depth = 0;
537623

538624
state->callback_userdata = callback_userdata;
539625
state->filter_callback = callback;
540626
state->reallocateArray = reallocateArray;
541627

542-
state->all_objects = array_create (state, max_count * 4);
628+
state->all_objects = block_array_create (state);
543629
state->process_array = array_create (state, max_count);
544630

545631
return state;
@@ -548,19 +634,21 @@ mono_unity_liveness_allocate_struct (MonoClass *filter, guint max_count, registe
548634
void
549635
mono_unity_liveness_finalize (LivenessState *state)
550636
{
551-
int i;
552-
for (i = 0; i < state->all_objects->len; i++) {
553-
MonoObject *object = g_ptr_array_index (state->all_objects, i);
637+
block_array_reset_iterator (state->all_objects);
638+
gpointer it = block_array_next (state->all_objects);
639+
while (it != NULL) {
640+
MonoObject *object = it;
554641
CLEAR_OBJ (object);
642+
it = block_array_next (state->all_objects);
555643
}
556644
}
557645

558646
void
559647
mono_unity_liveness_free_struct (LivenessState *state)
560648
{
561649
//cleanup the liveness_state
562-
array_destroy (state, state->all_objects);
563-
array_destroy (state, state->process_array);
650+
block_array_destroy (state->all_objects, state);
651+
array_destroy (state->process_array, state);
564652
g_free (state);
565653
}
566654

0 commit comments

Comments
 (0)