18
18
#include "submodule-config.h"
19
19
#include "submodule.h"
20
20
#include "hashmap.h"
21
+ #include "mem-pool.h"
21
22
#include "ll-merge.h"
22
23
#include "string-list.h"
23
24
#include "strvec.h"
@@ -772,6 +773,7 @@ struct emitted_diff_symbol {
772
773
int flags ;
773
774
int indent_off ; /* Offset to first non-whitespace character */
774
775
int indent_width ; /* The visual width of the indentation */
776
+ unsigned id ;
775
777
enum diff_symbol s ;
776
778
};
777
779
#define EMITTED_DIFF_SYMBOL_INIT {NULL}
@@ -797,9 +799,9 @@ static void append_emitted_diff_symbol(struct diff_options *o,
797
799
}
798
800
799
801
struct moved_entry {
800
- struct hashmap_entry ent ;
801
802
const struct emitted_diff_symbol * es ;
802
803
struct moved_entry * next_line ;
804
+ struct moved_entry * next_match ;
803
805
};
804
806
805
807
struct moved_block {
@@ -865,24 +867,24 @@ static int cmp_in_block_with_wsd(const struct moved_entry *cur,
865
867
const struct emitted_diff_symbol * l ,
866
868
struct moved_block * pmb )
867
869
{
868
- int al = cur -> es -> len , bl = l -> len ;
869
- const char * a = cur -> es -> line ,
870
- * b = l -> line ;
871
- int a_off = cur -> es -> indent_off ,
872
- a_width = cur -> es -> indent_width ,
873
- b_off = l -> indent_off ,
874
- b_width = l -> indent_width ;
870
+ int a_width = cur -> es -> indent_width , b_width = l -> indent_width ;
875
871
int delta ;
876
872
877
- /* If 'l' and 'cur' are both blank then they match. */
878
- if (a_width == INDENT_BLANKLINE && b_width == INDENT_BLANKLINE )
873
+ /* The text of each line must match */
874
+ if (cur -> es -> id != l -> id )
875
+ return 1 ;
876
+
877
+ /*
878
+ * If 'l' and 'cur' are both blank then we don't need to check the
879
+ * indent. We only need to check cur as we know the strings match.
880
+ * */
881
+ if (a_width == INDENT_BLANKLINE )
879
882
return 0 ;
880
883
881
884
/*
882
885
* The indent changes of the block are known and stored in pmb->wsd;
883
886
* however we need to check if the indent changes of the current line
884
- * match those of the current block and that the text of 'l' and 'cur'
885
- * after the indentation match.
887
+ * match those of the current block.
886
888
*/
887
889
delta = b_width - a_width ;
888
890
@@ -893,78 +895,108 @@ static int cmp_in_block_with_wsd(const struct moved_entry *cur,
893
895
if (pmb -> wsd == INDENT_BLANKLINE )
894
896
pmb -> wsd = delta ;
895
897
896
- return !(delta == pmb -> wsd && al - a_off == bl - b_off &&
897
- !memcmp (a + a_off , b + b_off , al - a_off ));
898
+ return delta != pmb -> wsd ;
898
899
}
899
900
900
- static int moved_entry_cmp (const void * hashmap_cmp_fn_data ,
901
- const struct hashmap_entry * eptr ,
902
- const struct hashmap_entry * entry_or_key ,
903
- const void * keydata )
901
+ struct interned_diff_symbol {
902
+ struct hashmap_entry ent ;
903
+ struct emitted_diff_symbol * es ;
904
+ };
905
+
906
+ static int interned_diff_symbol_cmp (const void * hashmap_cmp_fn_data ,
907
+ const struct hashmap_entry * eptr ,
908
+ const struct hashmap_entry * entry_or_key ,
909
+ const void * keydata )
904
910
{
905
911
const struct diff_options * diffopt = hashmap_cmp_fn_data ;
906
912
const struct emitted_diff_symbol * a , * b ;
907
913
unsigned flags = diffopt -> color_moved_ws_handling
908
914
& XDF_WHITESPACE_FLAGS ;
909
915
910
- a = container_of (eptr , const struct moved_entry , ent )-> es ;
911
- b = container_of (entry_or_key , const struct moved_entry , ent )-> es ;
916
+ a = container_of (eptr , const struct interned_diff_symbol , ent )-> es ;
917
+ b = container_of (entry_or_key , const struct interned_diff_symbol , ent )-> es ;
912
918
913
919
return !xdiff_compare_lines (a -> line + a -> indent_off ,
914
920
a -> len - a -> indent_off ,
915
921
b -> line + b -> indent_off ,
916
922
b -> len - b -> indent_off , flags );
917
923
}
918
924
919
- static struct moved_entry * prepare_entry (struct diff_options * o ,
920
- int line_no )
925
+ static void prepare_entry (struct diff_options * o , struct emitted_diff_symbol * l ,
926
+ struct interned_diff_symbol * s )
921
927
{
922
- struct moved_entry * ret = xmalloc (sizeof (* ret ));
923
- struct emitted_diff_symbol * l = & o -> emitted_symbols -> buf [line_no ];
924
928
unsigned flags = o -> color_moved_ws_handling & XDF_WHITESPACE_FLAGS ;
925
929
unsigned int hash = xdiff_hash_string (l -> line + l -> indent_off ,
926
930
l -> len - l -> indent_off , flags );
927
931
928
- hashmap_entry_init (& ret -> ent , hash );
929
- ret -> es = l ;
930
- ret -> next_line = NULL ;
931
-
932
- return ret ;
932
+ hashmap_entry_init (& s -> ent , hash );
933
+ s -> es = l ;
933
934
}
934
935
935
- static void add_lines_to_move_detection (struct diff_options * o ,
936
- struct hashmap * add_lines ,
937
- struct hashmap * del_lines )
936
+ struct moved_entry_list {
937
+ struct moved_entry * add , * del ;
938
+ };
939
+
940
+ static struct moved_entry_list * add_lines_to_move_detection (struct diff_options * o ,
941
+ struct mem_pool * entry_mem_pool )
938
942
{
939
943
struct moved_entry * prev_line = NULL ;
940
-
944
+ struct mem_pool interned_pool ;
945
+ struct hashmap interned_map ;
946
+ struct moved_entry_list * entry_list = NULL ;
947
+ size_t entry_list_alloc = 0 ;
948
+ unsigned id = 0 ;
941
949
int n ;
950
+
951
+ hashmap_init (& interned_map , interned_diff_symbol_cmp , o , 8096 );
952
+ mem_pool_init (& interned_pool , 1024 * 1024 );
953
+
942
954
for (n = 0 ; n < o -> emitted_symbols -> nr ; n ++ ) {
943
- struct hashmap * hm ;
944
- struct moved_entry * key ;
955
+ struct interned_diff_symbol key ;
956
+ struct emitted_diff_symbol * l = & o -> emitted_symbols -> buf [n ];
957
+ struct interned_diff_symbol * s ;
958
+ struct moved_entry * entry ;
945
959
946
- switch (o -> emitted_symbols -> buf [n ].s ) {
947
- case DIFF_SYMBOL_PLUS :
948
- hm = add_lines ;
949
- break ;
950
- case DIFF_SYMBOL_MINUS :
951
- hm = del_lines ;
952
- break ;
953
- default :
960
+ if (l -> s != DIFF_SYMBOL_PLUS && l -> s != DIFF_SYMBOL_MINUS ) {
954
961
prev_line = NULL ;
955
962
continue ;
956
963
}
957
964
958
965
if (o -> color_moved_ws_handling &
959
966
COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE )
960
- fill_es_indent_data (& o -> emitted_symbols -> buf [n ]);
961
- key = prepare_entry (o , n );
962
- if (prev_line && prev_line -> es -> s == o -> emitted_symbols -> buf [n ].s )
963
- prev_line -> next_line = key ;
967
+ fill_es_indent_data (l );
964
968
965
- hashmap_add (hm , & key -> ent );
966
- prev_line = key ;
969
+ prepare_entry (o , l , & key );
970
+ s = hashmap_get_entry (& interned_map , & key , ent , & key .ent );
971
+ if (s ) {
972
+ l -> id = s -> es -> id ;
973
+ } else {
974
+ l -> id = id ;
975
+ ALLOC_GROW_BY (entry_list , id , 1 , entry_list_alloc );
976
+ hashmap_add (& interned_map ,
977
+ memcpy (mem_pool_alloc (& interned_pool ,
978
+ sizeof (key )),
979
+ & key , sizeof (key )));
980
+ }
981
+ entry = mem_pool_alloc (entry_mem_pool , sizeof (* entry ));
982
+ entry -> es = l ;
983
+ entry -> next_line = NULL ;
984
+ if (prev_line && prev_line -> es -> s == l -> s )
985
+ prev_line -> next_line = entry ;
986
+ prev_line = entry ;
987
+ if (l -> s == DIFF_SYMBOL_PLUS ) {
988
+ entry -> next_match = entry_list [l -> id ].add ;
989
+ entry_list [l -> id ].add = entry ;
990
+ } else {
991
+ entry -> next_match = entry_list [l -> id ].del ;
992
+ entry_list [l -> id ].del = entry ;
993
+ }
967
994
}
995
+
996
+ hashmap_clear (& interned_map );
997
+ mem_pool_discard (& interned_pool , 0 );
998
+
999
+ return entry_list ;
968
1000
}
969
1001
970
1002
static void pmb_advance_or_null (struct diff_options * o ,
@@ -973,7 +1005,6 @@ static void pmb_advance_or_null(struct diff_options *o,
973
1005
int * pmb_nr )
974
1006
{
975
1007
int i , j ;
976
- unsigned flags = o -> color_moved_ws_handling & XDF_WHITESPACE_FLAGS ;
977
1008
978
1009
for (i = 0 , j = 0 ; i < * pmb_nr ; i ++ ) {
979
1010
int match ;
@@ -986,9 +1017,8 @@ static void pmb_advance_or_null(struct diff_options *o,
986
1017
match = cur &&
987
1018
!cmp_in_block_with_wsd (cur , l , & pmb [i ]);
988
1019
else
989
- match = cur &&
990
- xdiff_compare_lines (cur -> es -> line , cur -> es -> len ,
991
- l -> line , l -> len , flags );
1020
+ match = cur && cur -> es -> id == l -> id ;
1021
+
992
1022
if (match ) {
993
1023
pmb [j ] = pmb [i ];
994
1024
pmb [j ++ ].match = cur ;
@@ -998,7 +1028,6 @@ static void pmb_advance_or_null(struct diff_options *o,
998
1028
}
999
1029
1000
1030
static void fill_potential_moved_blocks (struct diff_options * o ,
1001
- struct hashmap * hm ,
1002
1031
struct moved_entry * match ,
1003
1032
struct emitted_diff_symbol * l ,
1004
1033
struct moved_block * * pmb_p ,
@@ -1012,7 +1041,7 @@ static void fill_potential_moved_blocks(struct diff_options *o,
1012
1041
* The current line is the start of a new block.
1013
1042
* Setup the set of potential blocks.
1014
1043
*/
1015
- hashmap_for_each_entry_from ( hm , match , ent ) {
1044
+ for (; match ; match = match -> next_match ) {
1016
1045
ALLOC_GROW (pmb , pmb_nr + 1 , pmb_alloc );
1017
1046
if (o -> color_moved_ws_handling &
1018
1047
COLOR_MOVED_WS_ALLOW_INDENTATION_CHANGE )
@@ -1067,8 +1096,7 @@ static int adjust_last_block(struct diff_options *o, int n, int block_length)
1067
1096
1068
1097
/* Find blocks of moved code, delegate actual coloring decision to helper */
1069
1098
static void mark_color_as_moved (struct diff_options * o ,
1070
- struct hashmap * add_lines ,
1071
- struct hashmap * del_lines )
1099
+ struct moved_entry_list * entry_list )
1072
1100
{
1073
1101
struct moved_block * pmb = NULL ; /* potentially moved blocks */
1074
1102
int pmb_nr = 0 , pmb_alloc = 0 ;
@@ -1077,23 +1105,15 @@ static void mark_color_as_moved(struct diff_options *o,
1077
1105
1078
1106
1079
1107
for (n = 0 ; n < o -> emitted_symbols -> nr ; n ++ ) {
1080
- struct hashmap * hm = NULL ;
1081
- struct moved_entry * key ;
1082
1108
struct moved_entry * match = NULL ;
1083
1109
struct emitted_diff_symbol * l = & o -> emitted_symbols -> buf [n ];
1084
1110
1085
1111
switch (l -> s ) {
1086
1112
case DIFF_SYMBOL_PLUS :
1087
- hm = del_lines ;
1088
- key = prepare_entry (o , n );
1089
- match = hashmap_get_entry (hm , key , ent , NULL );
1090
- free (key );
1113
+ match = entry_list [l -> id ].del ;
1091
1114
break ;
1092
1115
case DIFF_SYMBOL_MINUS :
1093
- hm = add_lines ;
1094
- key = prepare_entry (o , n );
1095
- match = hashmap_get_entry (hm , key , ent , NULL );
1096
- free (key );
1116
+ match = entry_list [l -> id ].add ;
1097
1117
break ;
1098
1118
default :
1099
1119
flipped_block = 0 ;
@@ -1135,7 +1155,7 @@ static void mark_color_as_moved(struct diff_options *o,
1135
1155
*/
1136
1156
n -= block_length ;
1137
1157
else
1138
- fill_potential_moved_blocks (o , hm , match , l ,
1158
+ fill_potential_moved_blocks (o , match , l ,
1139
1159
& pmb , & pmb_alloc ,
1140
1160
& pmb_nr );
1141
1161
@@ -6253,20 +6273,18 @@ static void diff_flush_patch_all_file_pairs(struct diff_options *o)
6253
6273
6254
6274
if (o -> emitted_symbols ) {
6255
6275
if (o -> color_moved ) {
6256
- struct hashmap add_lines , del_lines ;
6257
-
6258
- hashmap_init (& del_lines , moved_entry_cmp , o , 0 );
6259
- hashmap_init (& add_lines , moved_entry_cmp , o , 0 );
6276
+ struct mem_pool entry_pool ;
6277
+ struct moved_entry_list * entry_list ;
6260
6278
6261
- add_lines_to_move_detection (o , & add_lines , & del_lines );
6262
- mark_color_as_moved (o , & add_lines , & del_lines );
6279
+ mem_pool_init (& entry_pool , 1024 * 1024 );
6280
+ entry_list = add_lines_to_move_detection (o ,
6281
+ & entry_pool );
6282
+ mark_color_as_moved (o , entry_list );
6263
6283
if (o -> color_moved == COLOR_MOVED_ZEBRA_DIM )
6264
6284
dim_moved_lines (o );
6265
6285
6266
- hashmap_clear_and_free (& add_lines , struct moved_entry ,
6267
- ent );
6268
- hashmap_clear_and_free (& del_lines , struct moved_entry ,
6269
- ent );
6286
+ mem_pool_discard (& entry_pool , 0 );
6287
+ free (entry_list );
6270
6288
}
6271
6289
6272
6290
for (i = 0 ; i < esm .nr ; i ++ )
0 commit comments