Skip to content

Commit

Permalink
Ref-count the filespecs used by diffcore
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Linus Torvalds authored and Junio C Hamano committed Oct 27, 2007
1 parent cb1491b commit 9fb8841
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 14 deletions.
15 changes: 11 additions & 4 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1440,9 +1440,18 @@ struct diff_filespec *alloc_filespec(const char *path)
memset(spec, 0, sizeof(*spec));
spec->path = (char *)(spec + 1);
memcpy(spec->path, path, namelen+1);
spec->count = 1;
return spec;
}

void free_filespec(struct diff_filespec *spec)
{
if (!--spec->count) {
diff_free_filespec_data(spec);
free(spec);
}
}

void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
unsigned short mode)
{
Expand Down Expand Up @@ -2435,10 +2444,8 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue,

void diff_free_filepair(struct diff_filepair *p)
{
diff_free_filespec_data(p->one);
diff_free_filespec_data(p->two);
free(p->one);
free(p->two);
free_filespec(p->one);
free_filespec(p->two);
free(p);
}

Expand Down
16 changes: 6 additions & 10 deletions diffcore-rename.c
Original file line number Diff line number Diff line change
Expand Up @@ -209,21 +209,19 @@ static int estimate_similarity(struct diff_filespec *src,

static void record_rename_pair(int dst_index, int src_index, int score)
{
struct diff_filespec *one, *two, *src, *dst;
struct diff_filespec *src, *dst;
struct diff_filepair *dp;

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

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

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

dp = diff_queue(NULL, one, two);
dp = diff_queue(NULL, src, dst);
dp->renamed_pair = 1;
if (!strcmp(src->path, dst->path))
dp->score = rename_src[src_index].score;
Expand Down Expand Up @@ -526,10 +524,8 @@ void diffcore_rename(struct diff_options *options)
}
}

for (i = 0; i < rename_dst_nr; i++) {
diff_free_filespec_data(rename_dst[i].two);
free(rename_dst[i].two);
}
for (i = 0; i < rename_dst_nr; i++)
free_filespec(rename_dst[i].two);

free(rename_dst);
rename_dst = NULL;
Expand Down
2 changes: 2 additions & 0 deletions diffcore.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ struct diff_filespec {
void *cnt_data;
const char *funcname_pattern_ident;
unsigned long size;
int count; /* Reference count */
int xfrm_flags; /* for use by the xfrm */
unsigned short mode; /* file mode */
unsigned sha1_valid : 1; /* if true, use sha1 and trust mode;
Expand All @@ -43,6 +44,7 @@ struct diff_filespec {
};

extern struct diff_filespec *alloc_filespec(const char *);
extern void free_filespec(struct diff_filespec *);
extern void fill_filespec(struct diff_filespec *, const unsigned char *,
unsigned short);

Expand Down

0 comments on commit 9fb8841

Please sign in to comment.