@@ -87,15 +87,69 @@ static int commit_pos_cmp(const void *va, const void *vb)
8787 commit_pos_at (& commit_pos , b );
8888}
8989
90+ define_commit_slab (commit_graph_data_slab , struct commit_graph_data );
91+ static struct commit_graph_data_slab commit_graph_data_slab =
92+ COMMIT_SLAB_INIT (1 , commit_graph_data_slab );
93+
94+ uint32_t commit_graph_position (const struct commit * c )
95+ {
96+ struct commit_graph_data * data =
97+ commit_graph_data_slab_peek (& commit_graph_data_slab , c );
98+
99+ return data ? data -> graph_pos : COMMIT_NOT_FROM_GRAPH ;
100+ }
101+
102+ uint32_t commit_graph_generation (const struct commit * c )
103+ {
104+ struct commit_graph_data * data =
105+ commit_graph_data_slab_peek (& commit_graph_data_slab , c );
106+
107+ if (!data )
108+ return GENERATION_NUMBER_INFINITY ;
109+ else if (data -> graph_pos == COMMIT_NOT_FROM_GRAPH )
110+ return GENERATION_NUMBER_INFINITY ;
111+
112+ return data -> generation ;
113+ }
114+
115+ static struct commit_graph_data * commit_graph_data_at (const struct commit * c )
116+ {
117+ unsigned int i , nth_slab ;
118+ struct commit_graph_data * data =
119+ commit_graph_data_slab_peek (& commit_graph_data_slab , c );
120+
121+ if (data )
122+ return data ;
123+
124+ nth_slab = c -> index / commit_graph_data_slab .slab_size ;
125+ data = commit_graph_data_slab_at (& commit_graph_data_slab , c );
126+
127+ /*
128+ * commit-slab initializes elements with zero, overwrite this with
129+ * COMMIT_NOT_FROM_GRAPH for graph_pos.
130+ *
131+ * We avoid initializing generation with checking if graph position
132+ * is not COMMIT_NOT_FROM_GRAPH.
133+ */
134+ for (i = 0 ; i < commit_graph_data_slab .slab_size ; i ++ ) {
135+ commit_graph_data_slab .slab [nth_slab ][i ].graph_pos =
136+ COMMIT_NOT_FROM_GRAPH ;
137+ }
138+
139+ return data ;
140+ }
141+
90142static int commit_gen_cmp (const void * va , const void * vb )
91143{
92144 const struct commit * a = * (const struct commit * * )va ;
93145 const struct commit * b = * (const struct commit * * )vb ;
94146
147+ uint32_t generation_a = commit_graph_generation (a );
148+ uint32_t generation_b = commit_graph_generation (b );
95149 /* lower generation commits first */
96- if (a -> generation < b -> generation )
150+ if (generation_a < generation_b )
97151 return -1 ;
98- else if (a -> generation > b -> generation )
152+ else if (generation_a > generation_b )
99153 return 1 ;
100154
101155 /* use date as a heuristic when generations are equal */
@@ -670,22 +724,25 @@ static struct commit_list **insert_parent_or_die(struct repository *r,
670724 c = lookup_commit (r , & oid );
671725 if (!c )
672726 die (_ ("could not find commit %s" ), oid_to_hex (& oid ));
673- c -> graph_pos = pos ;
727+ commit_graph_data_at ( c ) -> graph_pos = pos ;
674728 return & commit_list_insert (c , pptr )-> next ;
675729}
676730
677731static void fill_commit_graph_info (struct commit * item , struct commit_graph * g , uint32_t pos )
678732{
679733 const unsigned char * commit_data ;
734+ struct commit_graph_data * graph_data ;
680735 uint32_t lex_index ;
681736
682737 while (pos < g -> num_commits_in_base )
683738 g = g -> base_graph ;
684739
685740 lex_index = pos - g -> num_commits_in_base ;
686741 commit_data = g -> chunk_commit_data + GRAPH_DATA_WIDTH * lex_index ;
687- item -> graph_pos = pos ;
688- item -> generation = get_be32 (commit_data + g -> hash_len + 8 ) >> 2 ;
742+
743+ graph_data = commit_graph_data_at (item );
744+ graph_data -> graph_pos = pos ;
745+ graph_data -> generation = get_be32 (commit_data + g -> hash_len + 8 ) >> 2 ;
689746}
690747
691748static inline void set_commit_tree (struct commit * c , struct tree * t )
@@ -701,6 +758,7 @@ static int fill_commit_in_graph(struct repository *r,
701758 uint32_t * parent_data_ptr ;
702759 uint64_t date_low , date_high ;
703760 struct commit_list * * pptr ;
761+ struct commit_graph_data * graph_data ;
704762 const unsigned char * commit_data ;
705763 uint32_t lex_index ;
706764
@@ -714,7 +772,8 @@ static int fill_commit_in_graph(struct repository *r,
714772 * Store the "full" position, but then use the
715773 * "local" position for the rest of the calculation.
716774 */
717- item -> graph_pos = pos ;
775+ graph_data = commit_graph_data_at (item );
776+ graph_data -> graph_pos = pos ;
718777 lex_index = pos - g -> num_commits_in_base ;
719778
720779 commit_data = g -> chunk_commit_data + (g -> hash_len + 16 ) * lex_index ;
@@ -727,7 +786,7 @@ static int fill_commit_in_graph(struct repository *r,
727786 date_low = get_be32 (commit_data + g -> hash_len + 12 );
728787 item -> date = (timestamp_t )((date_high << 32 ) | date_low );
729788
730- item -> generation = get_be32 (commit_data + g -> hash_len + 8 ) >> 2 ;
789+ graph_data -> generation = get_be32 (commit_data + g -> hash_len + 8 ) >> 2 ;
731790
732791 pptr = & item -> parents ;
733792
@@ -759,8 +818,9 @@ static int fill_commit_in_graph(struct repository *r,
759818
760819static int find_commit_in_graph (struct commit * item , struct commit_graph * g , uint32_t * pos )
761820{
762- if (item -> graph_pos != COMMIT_NOT_FROM_GRAPH ) {
763- * pos = item -> graph_pos ;
821+ uint32_t graph_pos = commit_graph_position (item );
822+ if (graph_pos != COMMIT_NOT_FROM_GRAPH ) {
823+ * pos = graph_pos ;
764824 return 1 ;
765825 } else {
766826 struct commit_graph * cur_g = g ;
@@ -815,12 +875,13 @@ static struct tree *load_tree_for_commit(struct repository *r,
815875{
816876 struct object_id oid ;
817877 const unsigned char * commit_data ;
878+ uint32_t graph_pos = commit_graph_position (c );
818879
819- while (c -> graph_pos < g -> num_commits_in_base )
880+ while (graph_pos < g -> num_commits_in_base )
820881 g = g -> base_graph ;
821882
822883 commit_data = g -> chunk_commit_data +
823- GRAPH_DATA_WIDTH * (c -> graph_pos - g -> num_commits_in_base );
884+ GRAPH_DATA_WIDTH * (graph_pos - g -> num_commits_in_base );
824885
825886 hashcpy (oid .hash , commit_data );
826887 set_commit_tree (c , lookup_tree (r , & oid ));
@@ -834,7 +895,7 @@ static struct tree *get_commit_tree_in_graph_one(struct repository *r,
834895{
835896 if (c -> maybe_tree )
836897 return c -> maybe_tree ;
837- if (c -> graph_pos == COMMIT_NOT_FROM_GRAPH )
898+ if (commit_graph_position ( c ) == COMMIT_NOT_FROM_GRAPH )
838899 BUG ("get_commit_tree_in_graph_one called from non-commit-graph commit" );
839900
840901 return load_tree_for_commit (r , g , (struct commit * )c );
@@ -1020,7 +1081,7 @@ static void write_graph_chunk_data(struct hashfile *f, int hash_len,
10201081 else
10211082 packedDate [0 ] = 0 ;
10221083
1023- packedDate [0 ] |= htonl ((* list )-> generation << 2 );
1084+ packedDate [0 ] |= htonl (commit_graph_data_at (* list )-> generation << 2 );
10241085
10251086 packedDate [1 ] = htonl ((* list )-> date );
10261087 hashwrite (f , packedDate , 8 );
@@ -1219,7 +1280,7 @@ static void close_reachable(struct write_commit_graph_context *ctx)
12191280 continue ;
12201281 if (ctx -> split ) {
12211282 if ((!parse_commit (commit ) &&
1222- commit -> graph_pos == COMMIT_NOT_FROM_GRAPH ) ||
1283+ commit_graph_position ( commit ) == COMMIT_NOT_FROM_GRAPH ) ||
12231284 flags == COMMIT_GRAPH_SPLIT_REPLACE )
12241285 add_missing_parents (ctx , commit );
12251286 } else if (!parse_commit_no_graph (commit ))
@@ -1251,9 +1312,11 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
12511312 _ ("Computing commit graph generation numbers" ),
12521313 ctx -> commits .nr );
12531314 for (i = 0 ; i < ctx -> commits .nr ; i ++ ) {
1315+ uint32_t generation = commit_graph_data_at (ctx -> commits .list [i ])-> generation ;
1316+
12541317 display_progress (ctx -> progress , i + 1 );
1255- if (ctx -> commits . list [ i ] -> generation != GENERATION_NUMBER_INFINITY &&
1256- ctx -> commits . list [ i ] -> generation != GENERATION_NUMBER_ZERO )
1318+ if (generation != GENERATION_NUMBER_INFINITY &&
1319+ generation != GENERATION_NUMBER_ZERO )
12571320 continue ;
12581321
12591322 commit_list_insert (ctx -> commits .list [i ], & list );
@@ -1264,22 +1327,26 @@ static void compute_generation_numbers(struct write_commit_graph_context *ctx)
12641327 uint32_t max_generation = 0 ;
12651328
12661329 for (parent = current -> parents ; parent ; parent = parent -> next ) {
1267- if (parent -> item -> generation == GENERATION_NUMBER_INFINITY ||
1268- parent -> item -> generation == GENERATION_NUMBER_ZERO ) {
1330+ generation = commit_graph_data_at (parent -> item )-> generation ;
1331+
1332+ if (generation == GENERATION_NUMBER_INFINITY ||
1333+ generation == GENERATION_NUMBER_ZERO ) {
12691334 all_parents_computed = 0 ;
12701335 commit_list_insert (parent -> item , & list );
12711336 break ;
1272- } else if (parent -> item -> generation > max_generation ) {
1273- max_generation = parent -> item -> generation ;
1337+ } else if (generation > max_generation ) {
1338+ max_generation = generation ;
12741339 }
12751340 }
12761341
12771342 if (all_parents_computed ) {
1278- current -> generation = max_generation + 1 ;
1343+ struct commit_graph_data * data = commit_graph_data_at (current );
1344+
1345+ data -> generation = max_generation + 1 ;
12791346 pop_commit (& list );
12801347
1281- if (current -> generation > GENERATION_NUMBER_MAX )
1282- current -> generation = GENERATION_NUMBER_MAX ;
1348+ if (data -> generation > GENERATION_NUMBER_MAX )
1349+ data -> generation = GENERATION_NUMBER_MAX ;
12831350 }
12841351 }
12851352 }
@@ -1458,7 +1525,7 @@ static uint32_t count_distinct_commits(struct write_commit_graph_context *ctx)
14581525 if (ctx -> split ) {
14591526 struct commit * c = lookup_commit (ctx -> r , & ctx -> oids .list [i ]);
14601527
1461- if (!c || c -> graph_pos != COMMIT_NOT_FROM_GRAPH )
1528+ if (!c || commit_graph_position ( c ) != COMMIT_NOT_FROM_GRAPH )
14621529 continue ;
14631530 }
14641531
@@ -1492,7 +1559,7 @@ static void copy_oids_to_commits(struct write_commit_graph_context *ctx)
14921559 ctx -> commits .list [ctx -> commits .nr ] = lookup_commit (ctx -> r , & ctx -> oids .list [i ]);
14931560
14941561 if (ctx -> split && flags != COMMIT_GRAPH_SPLIT_REPLACE &&
1495- ctx -> commits .list [ctx -> commits .nr ]-> graph_pos != COMMIT_NOT_FROM_GRAPH )
1562+ commit_graph_position ( ctx -> commits .list [ctx -> commits .nr ]) != COMMIT_NOT_FROM_GRAPH )
14961563 continue ;
14971564
14981565 if (ctx -> split && flags == COMMIT_GRAPH_SPLIT_REPLACE )
@@ -2241,6 +2308,7 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags)
22412308 struct commit * graph_commit , * odb_commit ;
22422309 struct commit_list * graph_parents , * odb_parents ;
22432310 uint32_t max_generation = 0 ;
2311+ uint32_t generation ;
22442312
22452313 display_progress (progress , i + 1 );
22462314 hashcpy (cur_oid .hash , g -> chunk_oid_lookup + g -> hash_len * i );
@@ -2279,8 +2347,9 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags)
22792347 oid_to_hex (& graph_parents -> item -> object .oid ),
22802348 oid_to_hex (& odb_parents -> item -> object .oid ));
22812349
2282- if (graph_parents -> item -> generation > max_generation )
2283- max_generation = graph_parents -> item -> generation ;
2350+ generation = commit_graph_generation (graph_parents -> item );
2351+ if (generation > max_generation )
2352+ max_generation = generation ;
22842353
22852354 graph_parents = graph_parents -> next ;
22862355 odb_parents = odb_parents -> next ;
@@ -2290,7 +2359,7 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags)
22902359 graph_report (_ ("commit-graph parent list for commit %s terminates early" ),
22912360 oid_to_hex (& cur_oid ));
22922361
2293- if (!graph_commit -> generation ) {
2362+ if (!commit_graph_generation ( graph_commit ) ) {
22942363 if (generation_zero == GENERATION_NUMBER_EXISTS )
22952364 graph_report (_ ("commit-graph has generation number zero for commit %s, but non-zero elsewhere" ),
22962365 oid_to_hex (& cur_oid ));
@@ -2310,10 +2379,11 @@ int verify_commit_graph(struct repository *r, struct commit_graph *g, int flags)
23102379 if (max_generation == GENERATION_NUMBER_MAX )
23112380 max_generation -- ;
23122381
2313- if (graph_commit -> generation != max_generation + 1 )
2382+ generation = commit_graph_generation (graph_commit );
2383+ if (generation != max_generation + 1 )
23142384 graph_report (_ ("commit-graph generation for commit %s is %u != %u" ),
23152385 oid_to_hex (& cur_oid ),
2316- graph_commit -> generation ,
2386+ generation ,
23172387 max_generation + 1 );
23182388
23192389 if (graph_commit -> date != odb_commit -> date )
0 commit comments