@@ -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+
1844typedef void (* register_object_callback ) (gpointer * arr , int size , void * callback_userdata );
1945typedef void (* WorldStateChanged ) ();
2046typedef void * (* ReallocateArray ) (void * ptr , int size , void * callback_userdata );
2147
2248struct _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
90179void
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);
177266void
178267mono_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)
262348static gboolean
263349mono_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)
433520void
434521mono_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
548634void
549635mono_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
558646void
559647mono_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