9
9
#include <mono/utils/mono-error.h>
10
10
11
11
typedef struct _LivenessState LivenessState ;
12
- typedef struct _custom_growable_array {
13
- gpointer * pdata ;
14
- guint len ; // used
15
- guint size ; // reserved
16
- } custom_growable_array ;
17
12
18
13
#define k_block_size (8 * 1024)
19
14
#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;
22
17
23
18
typedef struct _custom_array_block {
24
19
gpointer * next_item ;
20
+ custom_array_block * prev_block ;
25
21
custom_array_block * next_block ;
26
22
gpointer p_data [k_array_elements_per_block ];
27
23
} custom_array_block ;
@@ -50,7 +46,7 @@ struct _LivenessState {
50
46
51
47
MonoClass * filter ;
52
48
53
- custom_growable_array * process_array ;
49
+ custom_growable_block_array * process_array ;
54
50
guint initial_alloc_count ;
55
51
56
52
void * callback_userdata ;
@@ -64,6 +60,7 @@ custom_growable_block_array * block_array_create(LivenessState *state)
64
60
{
65
61
custom_growable_block_array * array = g_new0 (custom_growable_block_array , 1 );
66
62
array -> current_block = state -> reallocateArray (NULL , k_block_size , state -> callback_userdata );
63
+ array -> current_block -> prev_block = NULL ;
67
64
array -> current_block -> next_block = NULL ;
68
65
array -> current_block -> next_item = array -> current_block -> p_data ;
69
66
array -> first_block = array -> current_block ;
@@ -75,17 +72,39 @@ custom_growable_block_array * block_array_create(LivenessState *state)
75
72
return array ;
76
73
}
77
74
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
+
78
80
void block_array_push_back (custom_growable_block_array * block_array , gpointer value , LivenessState * state )
79
81
{
80
82
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 ;
85
93
}
86
94
* block_array -> current_block -> next_item ++ = value ;
87
95
}
88
96
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
+
89
108
void block_array_reset_iterator (custom_growable_block_array * array )
90
109
{
91
110
array -> iterator -> current_block = array -> first_block ;
@@ -106,6 +125,15 @@ gpointer block_array_next(custom_growable_block_array *block_array)
106
125
return * iterator -> current_position ++ ;
107
126
}
108
127
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
+
109
137
void block_array_destroy (custom_growable_block_array * block_array , LivenessState * state )
110
138
{
111
139
custom_array_block * block = block_array -> first_block ;
@@ -118,8 +146,6 @@ void block_array_destroy(custom_growable_block_array *block_array, LivenessState
118
146
g_free (block_array );
119
147
}
120
148
121
- #define array_at_index (array , index ) (array)->pdata[(index)]
122
-
123
149
#if defined(HAVE_SGEN_GC )
124
150
void sgen_stop_world (int generation );
125
151
void sgen_restart_world (int generation );
@@ -141,54 +167,6 @@ void GC_start_world_external()
141
167
#error need to implement liveness GC API
142
168
#endif
143
169
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
-
192
170
/* number of sub elements of an array to process before recursing
193
171
* we take a depth first approach to use stack space rather than re-allocating
194
172
* processing array which requires restarting world to ensure allocator lock is not held
@@ -228,12 +206,7 @@ void mono_filter_objects(LivenessState *state);
228
206
229
207
void mono_reset_state (LivenessState * state )
230
208
{
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 );
237
210
}
238
211
239
212
static gboolean should_process_value (MonoObject * val , MonoClass * filter )
@@ -277,9 +250,7 @@ static gboolean mono_add_process_object(MonoObject *object, LivenessState *state
277
250
}
278
251
// Check if klass has further references - if not skip adding
279
252
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 );
283
254
return TRUE;
284
255
}
285
256
}
@@ -377,8 +348,8 @@ static void mono_traverse_objects(LivenessState *state)
377
348
MonoObject * object = NULL ;
378
349
379
350
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 );
382
353
mono_traverse_generic_object (object , state );
383
354
}
384
355
state -> traverse_depth -- ;
@@ -524,16 +495,6 @@ void mono_unity_liveness_calculation_from_statics(LivenessState *liveness_state)
524
495
mono_filter_objects (liveness_state );
525
496
}
526
497
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
-
537
498
/**
538
499
* mono_unity_liveness_calculation_from_root:
539
500
*
@@ -544,7 +505,7 @@ void mono_unity_liveness_calculation_from_root(MonoObject *root, LivenessState *
544
505
{
545
506
mono_reset_state (liveness_state );
546
507
547
- array_push_back (liveness_state -> process_array , root );
508
+ block_array_push_back (liveness_state -> process_array , root , liveness_state );
548
509
549
510
mono_traverse_objects (liveness_state );
550
511
@@ -563,7 +524,6 @@ LivenessState * mono_unity_liveness_allocate_struct(MonoClass *filter, guint max
563
524
// 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.
564
525
565
526
state = g_new0 (LivenessState , 1 );
566
- max_count = max_count < 1000 ? 1000 : max_count ;
567
527
568
528
state -> filter = filter ;
569
529
state -> traverse_depth = 0 ;
@@ -573,7 +533,7 @@ LivenessState * mono_unity_liveness_allocate_struct(MonoClass *filter, guint max
573
533
state -> reallocateArray = reallocateArray ;
574
534
575
535
state -> all_objects = block_array_create (state );
576
- state -> process_array = array_create (state , max_count );
536
+ state -> process_array = block_array_create (state );
577
537
578
538
return state ;
579
539
}
@@ -593,7 +553,7 @@ void mono_unity_liveness_free_struct(LivenessState *state)
593
553
{
594
554
//cleanup the liveness_state
595
555
block_array_destroy (state -> all_objects , state );
596
- array_destroy (state -> process_array );
556
+ block_array_destroy (state -> process_array , state );
597
557
g_free (state );
598
558
}
599
559
0 commit comments