99#include <mono/utils/mono-error.h>
1010
1111typedef struct _LivenessState LivenessState ;
12- typedef struct _custom_growable_array {
13- gpointer * pdata ;
14- guint len ; // used
15- guint size ; // reserved
16- } custom_growable_array ;
1712
1813#define k_block_size (8 * 1024)
1914#define k_array_elements_per_block ((k_block_size - 2 * sizeof (guint) - sizeof (gpointer)) / sizeof (gpointer))
@@ -22,6 +17,7 @@ typedef struct _custom_array_block custom_array_block;
2217
2318typedef struct _custom_array_block {
2419 gpointer * next_item ;
20+ custom_array_block * prev_block ;
2521 custom_array_block * next_block ;
2622 gpointer p_data [k_array_elements_per_block ];
2723} custom_array_block ;
@@ -50,7 +46,7 @@ struct _LivenessState {
5046
5147 MonoClass * filter ;
5248
53- custom_growable_array * process_array ;
49+ custom_growable_block_array * process_array ;
5450 guint initial_alloc_count ;
5551
5652 void * callback_userdata ;
@@ -64,6 +60,7 @@ custom_growable_block_array * block_array_create(LivenessState *state)
6460{
6561 custom_growable_block_array * array = g_new0 (custom_growable_block_array , 1 );
6662 array -> current_block = state -> reallocateArray (NULL , k_block_size , state -> callback_userdata );
63+ array -> current_block -> prev_block = NULL ;
6764 array -> current_block -> next_block = NULL ;
6865 array -> current_block -> next_item = array -> current_block -> p_data ;
6966 array -> first_block = array -> current_block ;
@@ -75,17 +72,39 @@ custom_growable_block_array * block_array_create(LivenessState *state)
7572 return array ;
7673}
7774
75+ gboolean block_array_is_empty (custom_growable_block_array * block_array )
76+ {
77+ return block_array -> first_block -> next_item == block_array -> first_block -> p_data ;
78+ }
79+
7880void block_array_push_back (custom_growable_block_array * block_array , gpointer value , LivenessState * state )
7981{
8082 if (block_array -> current_block -> next_item == block_array -> current_block -> p_data + k_array_elements_per_block ) {
81- block_array -> current_block -> next_block = state -> reallocateArray (NULL , k_block_size , state -> callback_userdata );
82- block_array -> current_block = block_array -> current_block -> next_block ;
83- block_array -> current_block -> next_block = NULL ;
84- block_array -> current_block -> next_item = block_array -> current_block -> p_data ;
83+ custom_array_block * new_block = block_array -> current_block -> next_block ;
84+ if (block_array -> current_block -> next_block == NULL )
85+ {
86+ new_block = state -> reallocateArray (NULL , k_block_size , state -> callback_userdata );
87+ new_block -> next_block = NULL ;
88+ new_block -> prev_block = block_array -> current_block ;
89+ new_block -> next_item = new_block -> p_data ;
90+ block_array -> current_block -> next_block = new_block ;
91+ }
92+ block_array -> current_block = new_block ;
8593 }
8694 * block_array -> current_block -> next_item ++ = value ;
8795}
8896
97+ gpointer block_array_pop_back (custom_growable_block_array * block_array )
98+ {
99+ if (block_array -> current_block -> next_item == block_array -> current_block -> p_data ) {
100+ if (block_array -> current_block -> prev_block == NULL )
101+ return NULL ;
102+ block_array -> current_block = block_array -> current_block -> prev_block ;
103+ block_array -> current_block -> next_item = block_array -> current_block -> p_data + k_array_elements_per_block ;
104+ }
105+ return * -- block_array -> current_block -> next_item ;
106+ }
107+
89108void block_array_reset_iterator (custom_growable_block_array * array )
90109{
91110 array -> iterator -> current_block = array -> first_block ;
@@ -106,6 +125,15 @@ gpointer block_array_next(custom_growable_block_array *block_array)
106125 return * iterator -> current_position ++ ;
107126}
108127
128+ void block_array_clear (custom_growable_block_array * block_array )
129+ {
130+ custom_array_block * block = block_array -> first_block ;
131+ while (block != NULL ) {
132+ block -> next_item = block -> p_data ;
133+ block = block -> next_block ;
134+ }
135+ }
136+
109137void block_array_destroy (custom_growable_block_array * block_array , LivenessState * state )
110138{
111139 custom_array_block * block = block_array -> first_block ;
@@ -118,8 +146,6 @@ void block_array_destroy(custom_growable_block_array *block_array, LivenessState
118146 g_free (block_array );
119147}
120148
121- #define array_at_index (array , index ) (array)->pdata[(index)]
122-
123149#if defined(HAVE_SGEN_GC )
124150void sgen_stop_world (int generation );
125151void sgen_restart_world (int generation );
@@ -141,54 +167,6 @@ void GC_start_world_external()
141167#error need to implement liveness GC API
142168#endif
143169
144- custom_growable_array * array_create_and_initialize (guint capacity )
145- {
146- custom_growable_array * array = g_ptr_array_sized_new (capacity );
147- array -> len = 0 ;
148- return array ;
149- }
150-
151- gboolean array_is_full (custom_growable_array * array )
152- {
153- return g_ptr_array_capacity (array ) == array -> len ;
154- }
155-
156- void array_destroy (custom_growable_array * array )
157- {
158- g_ptr_array_free (array , TRUE);
159- g_free (array );
160- }
161-
162- void array_push_back (custom_growable_array * array , gpointer value )
163- {
164- g_assert (!array_is_full (array ));
165- array -> pdata [array -> len ] = value ;
166- array -> len ++ ;
167- }
168-
169- gpointer array_pop_back (custom_growable_array * array )
170- {
171- array -> len -- ;
172- return array -> pdata [array -> len ];
173- }
174-
175- void array_clear (custom_growable_array * array )
176- {
177- array -> len = 0 ;
178- }
179-
180- void array_reserve (LivenessState * state , custom_growable_array * array , guint size )
181- {
182- array -> pdata = state -> reallocateArray (array -> pdata , size * sizeof (gpointer ), state -> callback_userdata );
183- array -> size = size ;
184- }
185-
186- void array_grow (LivenessState * state , custom_growable_array * array )
187- {
188- array -> pdata = state -> reallocateArray (array -> pdata , array -> size * 2 * sizeof (gpointer ), state -> callback_userdata );
189- array -> size = array -> size * 2 ;
190- }
191-
192170/* number of sub elements of an array to process before recursing
193171 * we take a depth first approach to use stack space rather than re-allocating
194172 * processing array which requires restarting world to ensure allocator lock is not held
@@ -228,12 +206,7 @@ void mono_filter_objects(LivenessState *state);
228206
229207void mono_reset_state (LivenessState * state )
230208{
231- array_clear (state -> process_array );
232- }
233-
234- void array_safe_grow (LivenessState * state , custom_growable_array * array )
235- {
236- array_grow (state , array );
209+ block_array_clear (state -> process_array );
237210}
238211
239212static gboolean should_process_value (MonoObject * val , MonoClass * filter )
@@ -277,9 +250,7 @@ static gboolean mono_add_process_object(MonoObject *object, LivenessState *state
277250 }
278251 // Check if klass has further references - if not skip adding
279252 if (has_references ) {
280- if (array_is_full (state -> process_array ))
281- array_safe_grow (state , state -> process_array );
282- array_push_back (state -> process_array , object );
253+ block_array_push_back (state -> process_array , object , state );
283254 return TRUE;
284255 }
285256 }
@@ -377,8 +348,8 @@ static void mono_traverse_objects(LivenessState *state)
377348 MonoObject * object = NULL ;
378349
379350 state -> traverse_depth ++ ;
380- while (state -> process_array -> len > 0 ) {
381- object = array_pop_back (state -> process_array );
351+ while (! block_array_is_empty ( state -> process_array ) ) {
352+ object = block_array_pop_back (state -> process_array );
382353 mono_traverse_generic_object (object , state );
383354 }
384355 state -> traverse_depth -- ;
@@ -524,16 +495,6 @@ void mono_unity_liveness_calculation_from_statics(LivenessState *liveness_state)
524495 mono_filter_objects (liveness_state );
525496}
526497
527- void mono_unity_liveness_add_object_callback (gpointer * objs , gint count , void * arr )
528- {
529- int i ;
530- custom_growable_array * objects = (custom_growable_array * )arr ;
531- for (i = 0 ; i < count ; i ++ ) {
532- if (objects -> size > objects -> len )
533- objects -> pdata [objects -> len ++ ] = objs [i ];
534- }
535- }
536-
537498/**
538499 * mono_unity_liveness_calculation_from_root:
539500 *
@@ -544,7 +505,7 @@ void mono_unity_liveness_calculation_from_root(MonoObject *root, LivenessState *
544505{
545506 mono_reset_state (liveness_state );
546507
547- array_push_back (liveness_state -> process_array , root );
508+ block_array_push_back (liveness_state -> process_array , root , liveness_state );
548509
549510 mono_traverse_objects (liveness_state );
550511
@@ -563,7 +524,6 @@ LivenessState * mono_unity_liveness_allocate_struct(MonoClass *filter, guint max
563524 // if all_objects run out of space, run through list, add objects that match the filter, clear bit in vtable and then clear the array.
564525
565526 state = g_new0 (LivenessState , 1 );
566- max_count = max_count < 1000 ? 1000 : max_count ;
567527
568528 state -> filter = filter ;
569529 state -> traverse_depth = 0 ;
@@ -573,7 +533,7 @@ LivenessState * mono_unity_liveness_allocate_struct(MonoClass *filter, guint max
573533 state -> reallocateArray = reallocateArray ;
574534
575535 state -> all_objects = block_array_create (state );
576- state -> process_array = array_create (state , max_count );
536+ state -> process_array = block_array_create (state );
577537
578538 return state ;
579539}
@@ -593,7 +553,7 @@ void mono_unity_liveness_free_struct(LivenessState *state)
593553{
594554 //cleanup the liveness_state
595555 block_array_destroy (state -> all_objects , state );
596- array_destroy (state -> process_array );
556+ block_array_destroy (state -> process_array , state );
597557 g_free (state );
598558}
599559
0 commit comments