Skip to content

Commit 9fb8841

Browse files
torvaldsgitster
authored andcommitted
Ref-count the filespecs used by diffcore
Rather than copy the filespecs when introducing new versions of them (for rename or copy detection), use a refcount and increment the count when reusing the diff_filespec. This avoids unnecessary allocations, but the real reason behind this is a future enhancement: we will want to track shared data across the copy/rename detection. In order to efficiently notice when a filespec is used by a rename, the rename machinery wants to keep track of a rename usage count which is shared across all different users of the filespec. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent cb1491b commit 9fb8841

File tree

3 files changed

+19
-14
lines changed

3 files changed

+19
-14
lines changed

diff.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,9 +1440,18 @@ struct diff_filespec *alloc_filespec(const char *path)
14401440
memset(spec, 0, sizeof(*spec));
14411441
spec->path = (char *)(spec + 1);
14421442
memcpy(spec->path, path, namelen+1);
1443+
spec->count = 1;
14431444
return spec;
14441445
}
14451446

1447+
void free_filespec(struct diff_filespec *spec)
1448+
{
1449+
if (!--spec->count) {
1450+
diff_free_filespec_data(spec);
1451+
free(spec);
1452+
}
1453+
}
1454+
14461455
void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
14471456
unsigned short mode)
14481457
{
@@ -2435,10 +2444,8 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
24352444

24362445
void diff_free_filepair(struct diff_filepair *p)
24372446
{
2438-
diff_free_filespec_data(p->one);
2439-
diff_free_filespec_data(p->two);
2440-
free(p->one);
2441-
free(p->two);
2447+
free_filespec(p->one);
2448+
free_filespec(p->two);
24422449
free(p);
24432450
}
24442451

diffcore-rename.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -209,21 +209,19 @@ static int estimate_similarity(struct diff_filespec *src,
209209

210210
static void record_rename_pair(int dst_index, int src_index, int score)
211211
{
212-
struct diff_filespec *one, *two, *src, *dst;
212+
struct diff_filespec *src, *dst;
213213
struct diff_filepair *dp;
214214

215215
if (rename_dst[dst_index].pair)
216216
die("internal error: dst already matched.");
217217

218218
src = rename_src[src_index].one;
219-
one = alloc_filespec(src->path);
220-
fill_filespec(one, src->sha1, src->mode);
219+
src->count++;
221220

222221
dst = rename_dst[dst_index].two;
223-
two = alloc_filespec(dst->path);
224-
fill_filespec(two, dst->sha1, dst->mode);
222+
dst->count++;
225223

226-
dp = diff_queue(NULL, one, two);
224+
dp = diff_queue(NULL, src, dst);
227225
dp->renamed_pair = 1;
228226
if (!strcmp(src->path, dst->path))
229227
dp->score = rename_src[src_index].score;
@@ -526,10 +524,8 @@ void diffcore_rename(struct diff_options *options)
526524
}
527525
}
528526

529-
for (i = 0; i < rename_dst_nr; i++) {
530-
diff_free_filespec_data(rename_dst[i].two);
531-
free(rename_dst[i].two);
532-
}
527+
for (i = 0; i < rename_dst_nr; i++)
528+
free_filespec(rename_dst[i].two);
533529

534530
free(rename_dst);
535531
rename_dst = NULL;

diffcore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct diff_filespec {
2929
void *cnt_data;
3030
const char *funcname_pattern_ident;
3131
unsigned long size;
32+
int count; /* Reference count */
3233
int xfrm_flags; /* for use by the xfrm */
3334
unsigned short mode; /* file mode */
3435
unsigned sha1_valid : 1; /* if true, use sha1 and trust mode;
@@ -43,6 +44,7 @@ struct diff_filespec {
4344
};
4445

4546
extern struct diff_filespec *alloc_filespec(const char *);
47+
extern void free_filespec(struct diff_filespec *);
4648
extern void fill_filespec(struct diff_filespec *, const unsigned char *,
4749
unsigned short);
4850

0 commit comments

Comments
 (0)