@@ -116,6 +116,12 @@ static void on_gc_heap_resize (GC_word new_size);
116
116
117
117
#define ELEMENT_CHUNK_SIZE 256
118
118
#define VECTOR_PROC_INDEX 6
119
+
120
+ static unsigned GC_roots_proc_index ;
121
+
122
+ static mse *
123
+ GC_roots_proc (word * addr , mse * mark_stack_ptr , mse * mark_stack_limit , word env );
124
+
119
125
static mse * GC_gcj_vector_proc (word * addr , mse * mark_stack_ptr ,
120
126
mse * mark_stack_limit , word env )
121
127
{
@@ -205,6 +211,7 @@ mono_gc_base_init (void)
205
211
206
212
GC_init_gcj_malloc (5 , NULL );
207
213
GC_init_gcj_vector (VECTOR_PROC_INDEX , GC_gcj_vector_proc );
214
+ GC_roots_proc_index = GC_new_proc (GC_roots_proc );
208
215
GC_allow_register_threads ();
209
216
210
217
params_opts = mono_gc_params_get ();
@@ -685,12 +692,6 @@ mono_gc_deregister_root (char* addr)
685
692
MONO_PROFILER_RAISE (gc_root_unregister , ((const mono_byte * ) addr ));
686
693
}
687
694
688
- static void
689
- push_root (gpointer key , gpointer value , gpointer user_data )
690
- {
691
- GC_push_all (key , value );
692
- }
693
-
694
695
static void
695
696
push_handle_stack (HandleStack * stack )
696
697
{
@@ -709,10 +710,66 @@ push_handle_stack (HandleStack* stack)
709
710
}
710
711
}
711
712
713
+ static mse *
714
+ GC_roots_proc (word * addr , mse * mark_stack_ptr , mse * mark_stack_limit , word env )
715
+ {
716
+ GHashTableIter iter ;
717
+ guint size = g_hash_table_size (roots );
718
+ g_hash_table_iter_init (& iter , roots );
719
+ char * start ;
720
+ char * end ;
721
+
722
+ word capacity = (word )(mark_stack_limit - mark_stack_ptr ) - 1 ;
723
+ word start_index = env ;
724
+ word remaining = size - start_index ;
725
+ word skip = start_index ;
726
+
727
+ /* if we have more items than capacity, push remaining immediately. This allows pushed
728
+ * items to be processed on top of stack before we process remainder. If we push remainder
729
+ * at top, we have no mark stack space.
730
+ */
731
+ if (remaining > capacity ) {
732
+ capacity -- ;
733
+ mark_stack_ptr ++ ;
734
+ mark_stack_ptr -> mse_descr .w = GC_MAKE_PROC (GC_roots_proc_index , (start_index + capacity ) /* continue processing */ );
735
+ mark_stack_ptr -> mse_start = (ptr_t )0 ;
736
+ }
737
+
738
+ while (g_hash_table_iter_next (& iter , (void * * )& start , (void * * )& end ) && capacity > 0 ) {
739
+ void * bottom ;
740
+ void * top ;
741
+
742
+ if (skip ) {
743
+ skip -- ;
744
+ continue ;
745
+ }
746
+
747
+ /* taken from GC_push_all */
748
+ bottom = (void * )(((word )start + ALIGNMENT - 1 ) & ~(ALIGNMENT - 1 ));
749
+ top = (void * )((word )end & ~(ALIGNMENT - 1 ));
750
+
751
+ g_assert ((word )bottom < (word )top );
752
+
753
+ mark_stack_ptr ++ ;
754
+
755
+ if ((word )mark_stack_ptr >= (word )mark_stack_limit ) {
756
+ g_error ("Unexpected mark stack overflow\n" );
757
+ }
758
+ mark_stack_ptr -> mse_start = (ptr_t )bottom ;
759
+ mark_stack_ptr -> mse_descr .w = (word )top - (word )bottom ;
760
+ capacity -- ;
761
+ }
762
+ return mark_stack_ptr ;
763
+ }
764
+
712
765
static void
713
766
mono_push_other_roots (void )
714
767
{
715
- g_hash_table_foreach (roots , push_root , NULL );
768
+ if (GC_roots_proc_index ) {
769
+ GC_mark_stack_top ++ ;
770
+ GC_mark_stack_top -> mse_descr .w = GC_MAKE_PROC (GC_roots_proc_index , 0 /* continue processing */ );
771
+ GC_mark_stack_top -> mse_start = (ptr_t )0 ;
772
+ }
716
773
FOREACH_THREAD_EXCLUDE (info , MONO_THREAD_INFO_FLAGS_NO_GC ) {
717
774
HandleStack * stack = info -> handle_stack ;
718
775
if (stack )
0 commit comments