@@ -15,13 +15,38 @@ typedef struct _custom_growable_array {
15
15
guint size ; // reserved
16
16
} custom_growable_array ;
17
17
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
+
18
44
typedef void (* register_object_callback ) (gpointer * arr , int size , void * callback_userdata );
19
45
typedef void (* WorldStateChanged ) ();
20
46
typedef void * (* ReallocateArray ) (void * ptr , int size , void * callback_userdata );
21
47
22
48
struct _LivenessState {
23
- gint first_index_in_all_objects ;
24
- custom_growable_array * all_objects ;
49
+ custom_growable_block_array * all_objects ;
25
50
26
51
MonoClass * filter ;
27
52
@@ -32,9 +57,73 @@ struct _LivenessState {
32
57
33
58
register_object_callback filter_callback ;
34
59
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
36
61
};
37
62
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
+
38
127
#define array_at_index (array , index ) (array)->pdata[(index)]
39
128
40
129
#if defined(HAVE_SGEN_GC )
@@ -88,7 +177,7 @@ array_create (LivenessState *state, guint reserved_size)
88
177
}
89
178
90
179
void
91
- array_destroy (LivenessState * state , custom_growable_array * array )
180
+ array_destroy (custom_growable_array * array , LivenessState * state )
92
181
{
93
182
array -> pdata = state -> reallocateArray (array -> pdata , 0 , state -> callback_userdata );
94
183
g_free (array );
@@ -177,7 +266,6 @@ mono_filter_objects (LivenessState *state);
177
266
void
178
267
mono_reset_state (LivenessState * state )
179
268
{
180
- state -> first_index_in_all_objects = state -> all_objects -> len ;
181
269
array_clear (state -> process_array );
182
270
}
183
271
@@ -230,9 +318,7 @@ mono_add_process_object (MonoObject *object, LivenessState *state)
230
318
if (object && !IS_MARKED (object )) {
231
319
gboolean has_references = GET_VTABLE (object )-> klass -> has_references ;
232
320
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 );
236
322
MARK_OBJ (object );
237
323
}
238
324
// Check if klass has further references - if not skip adding
@@ -262,7 +348,7 @@ mono_field_can_contain_references (MonoClassField *field)
262
348
static gboolean
263
349
mono_traverse_object_internal (MonoObject * object , gboolean isStruct , MonoClass * klass , LivenessState * state )
264
350
{
265
- int i ;
351
+ guint32 i ;
266
352
MonoClassField * field ;
267
353
MonoClass * p ;
268
354
gboolean added_objects = FALSE;
@@ -362,7 +448,7 @@ mono_traverse_array (MonoArray *array, LivenessState *state)
362
448
gboolean has_references ;
363
449
MonoObject * object = (MonoObject * )array ;
364
450
MonoClass * element_class ;
365
- size_t elementClassSize ;
451
+ int32_t elementClassSize ;
366
452
size_t array_length ;
367
453
368
454
g_assert (object );
@@ -409,15 +495,16 @@ mono_filter_objects (LivenessState *state)
409
495
gpointer filtered_objects [64 ];
410
496
gint num_objects = 0 ;
411
497
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 ;
415
501
if (should_process_value (object , state -> filter ))
416
502
filtered_objects [num_objects ++ ] = object ;
417
503
if (num_objects == 64 ) {
418
504
state -> filter_callback (filtered_objects , 64 , state -> callback_userdata );
419
505
num_objects = 0 ;
420
506
}
507
+ value = block_array_next (state -> all_objects );
421
508
}
422
509
423
510
if (num_objects != 0 )
@@ -433,7 +520,7 @@ mono_filter_objects (LivenessState *state)
433
520
void
434
521
mono_unity_liveness_calculation_from_statics (LivenessState * liveness_state )
435
522
{
436
- int i , j ;
523
+ guint i , j ;
437
524
MonoDomain * domain = mono_domain_get ();
438
525
439
526
mono_reset_state (liveness_state );
@@ -531,15 +618,14 @@ mono_unity_liveness_allocate_struct (MonoClass *filter, guint max_count, registe
531
618
state = g_new0 (LivenessState , 1 );
532
619
max_count = max_count < 1000 ? 1000 : max_count ;
533
620
534
- state -> first_index_in_all_objects = 0 ;
535
621
state -> filter = filter ;
536
622
state -> traverse_depth = 0 ;
537
623
538
624
state -> callback_userdata = callback_userdata ;
539
625
state -> filter_callback = callback ;
540
626
state -> reallocateArray = reallocateArray ;
541
627
542
- state -> all_objects = array_create (state , max_count * 4 );
628
+ state -> all_objects = block_array_create (state );
543
629
state -> process_array = array_create (state , max_count );
544
630
545
631
return state ;
@@ -548,19 +634,21 @@ mono_unity_liveness_allocate_struct (MonoClass *filter, guint max_count, registe
548
634
void
549
635
mono_unity_liveness_finalize (LivenessState * state )
550
636
{
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 ;
554
641
CLEAR_OBJ (object );
642
+ it = block_array_next (state -> all_objects );
555
643
}
556
644
}
557
645
558
646
void
559
647
mono_unity_liveness_free_struct (LivenessState * state )
560
648
{
561
649
//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 );
564
652
g_free (state );
565
653
}
566
654
0 commit comments