@@ -525,10 +525,15 @@ find_in_cache (int *insert_index)
525525
526526// Populate other_colors for a give color (other_colors represent the xrefs for this color)
527527static void
528- add_other_colors (ColorData * color , DynPtrArray * other_colors )
528+ add_other_colors (ColorData * color , DynPtrArray * other_colors , gboolean check_visited )
529529{
530530 for (int i = 0 ; i < dyn_array_ptr_size (other_colors ); ++ i ) {
531531 ColorData * points_to = (ColorData * )dyn_array_ptr_get (other_colors , i );
532+ if (check_visited ) {
533+ if (points_to -> visited )
534+ continue ;
535+ points_to -> visited = TRUE;
536+ }
532537 dyn_array_ptr_add (& color -> other_colors , points_to );
533538 // Inform targets
534539 points_to -> incoming_colors = MIN (points_to -> incoming_colors + 1 , INCOMING_COLORS_MAX );
@@ -552,7 +557,7 @@ new_color (gboolean has_bridges)
552557 cd = alloc_color_data ();
553558 cd -> api_index = -1 ;
554559
555- add_other_colors (cd , & color_merge_array );
560+ add_other_colors (cd , & color_merge_array , FALSE );
556561
557562 /* if cacheSlot >= 0, it means we prepared a given slot to receive the new color */
558563 if (cacheSlot >= 0 )
@@ -791,12 +796,18 @@ create_scc (ScanData *data)
791796 dyn_array_ptr_add (& color_data -> bridges , other -> obj );
792797 }
793798
794- // Maybe we should make sure we are not adding duplicates here. It is not really a problem
795- // since we will get rid of duplicates before submitting the SCCs to the client in gather_xrefs
796- if (color_data ) {
797- add_other_colors (color_data , & other -> xrefs );
798- } else {
799- g_assert (dyn_array_ptr_size (& other -> xrefs ) == 0 );
799+ if (dyn_array_ptr_size (& other -> xrefs ) > 0 ) {
800+ g_assert (color_data != NULL );
801+ g_assert (can_reduce_color == FALSE);
802+ // We need to eliminate duplicates early otherwise the heaviness property
803+ // can change in gather_xrefs and it breaks down the loop that reports the
804+ // xrefs to the client.
805+ //
806+ // We reuse the visited flag to mark the objects that are already part of
807+ // the color_data array. The array was created above with the new_color call
808+ // and xrefs were populated from color_merge_array, which is already
809+ // deduplicated and every entry is marked as visited.
810+ add_other_colors (color_data , & other -> xrefs , TRUE);
800811 }
801812 dyn_array_ptr_uninit (& other -> xrefs );
802813
@@ -807,6 +818,15 @@ create_scc (ScanData *data)
807818 }
808819 g_assert (found );
809820
821+ // Clear the visited flag on nodes that were added with add_other_colors in the loop above
822+ if (!can_reduce_color ) {
823+ for (i = dyn_array_ptr_size (& color_merge_array ); i < dyn_array_ptr_size (& color_data -> other_colors ); i ++ ) {
824+ ColorData * cd = (ColorData * )dyn_array_ptr_get (& color_data -> other_colors , i );
825+ g_assert (cd -> visited );
826+ cd -> visited = FALSE;
827+ }
828+ }
829+
810830#if DUMP_GRAPH
811831 if (color_data ) {
812832 printf ("\tpoints-to-colors: " );
@@ -1116,6 +1136,7 @@ processing_build_callback_data (int generation)
11161136 gather_xrefs (cd );
11171137 reset_xrefs (cd );
11181138 dyn_array_ptr_set_all (& cd -> other_colors , & color_merge_array );
1139+ g_assert (color_visible_to_client (cd ));
11191140 xref_count += dyn_array_ptr_size (& cd -> other_colors );
11201141 }
11211142 }
0 commit comments