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>
This commit is contained in:

committed by
Junio C Hamano

parent
cb1491b6bf
commit
9fb88419ba
15
diff.c
15
diff.c
@ -1440,9 +1440,18 @@ struct diff_filespec *alloc_filespec(const char *path)
|
|||||||
memset(spec, 0, sizeof(*spec));
|
memset(spec, 0, sizeof(*spec));
|
||||||
spec->path = (char *)(spec + 1);
|
spec->path = (char *)(spec + 1);
|
||||||
memcpy(spec->path, path, namelen+1);
|
memcpy(spec->path, path, namelen+1);
|
||||||
|
spec->count = 1;
|
||||||
return spec;
|
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,
|
void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
|
||||||
unsigned short mode)
|
unsigned short mode)
|
||||||
{
|
{
|
||||||
@ -2435,10 +2444,8 @@ struct diff_filepair *diff_queue(struct diff_queue_struct *queue,
|
|||||||
|
|
||||||
void diff_free_filepair(struct diff_filepair *p)
|
void diff_free_filepair(struct diff_filepair *p)
|
||||||
{
|
{
|
||||||
diff_free_filespec_data(p->one);
|
free_filespec(p->one);
|
||||||
diff_free_filespec_data(p->two);
|
free_filespec(p->two);
|
||||||
free(p->one);
|
|
||||||
free(p->two);
|
|
||||||
free(p);
|
free(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
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;
|
struct diff_filepair *dp;
|
||||||
|
|
||||||
if (rename_dst[dst_index].pair)
|
if (rename_dst[dst_index].pair)
|
||||||
die("internal error: dst already matched.");
|
die("internal error: dst already matched.");
|
||||||
|
|
||||||
src = rename_src[src_index].one;
|
src = rename_src[src_index].one;
|
||||||
one = alloc_filespec(src->path);
|
src->count++;
|
||||||
fill_filespec(one, src->sha1, src->mode);
|
|
||||||
|
|
||||||
dst = rename_dst[dst_index].two;
|
dst = rename_dst[dst_index].two;
|
||||||
two = alloc_filespec(dst->path);
|
dst->count++;
|
||||||
fill_filespec(two, dst->sha1, dst->mode);
|
|
||||||
|
|
||||||
dp = diff_queue(NULL, one, two);
|
dp = diff_queue(NULL, src, dst);
|
||||||
dp->renamed_pair = 1;
|
dp->renamed_pair = 1;
|
||||||
if (!strcmp(src->path, dst->path))
|
if (!strcmp(src->path, dst->path))
|
||||||
dp->score = rename_src[src_index].score;
|
dp->score = rename_src[src_index].score;
|
||||||
@ -526,10 +524,8 @@ void diffcore_rename(struct diff_options *options)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < rename_dst_nr; i++) {
|
for (i = 0; i < rename_dst_nr; i++)
|
||||||
diff_free_filespec_data(rename_dst[i].two);
|
free_filespec(rename_dst[i].two);
|
||||||
free(rename_dst[i].two);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(rename_dst);
|
free(rename_dst);
|
||||||
rename_dst = NULL;
|
rename_dst = NULL;
|
||||||
|
@ -29,6 +29,7 @@ struct diff_filespec {
|
|||||||
void *cnt_data;
|
void *cnt_data;
|
||||||
const char *funcname_pattern_ident;
|
const char *funcname_pattern_ident;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
int count; /* Reference count */
|
||||||
int xfrm_flags; /* for use by the xfrm */
|
int xfrm_flags; /* for use by the xfrm */
|
||||||
unsigned short mode; /* file mode */
|
unsigned short mode; /* file mode */
|
||||||
unsigned sha1_valid : 1; /* if true, use sha1 and trust mode;
|
unsigned sha1_valid : 1; /* if true, use sha1 and trust mode;
|
||||||
@ -43,6 +44,7 @@ struct diff_filespec {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern struct diff_filespec *alloc_filespec(const char *);
|
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 *,
|
extern void fill_filespec(struct diff_filespec *, const unsigned char *,
|
||||||
unsigned short);
|
unsigned short);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user