block alloc: add lifecycle APIs for cache_entry structs

It has been observed that the time spent loading an index with a large number of entries is partly dominated by malloc() calls. This change is in preparation for using memory pools to reduce the number of malloc() calls made to allocate cahce entries when loading an index. Add an API to allocate and discard cache entries, abstracting the details of managing the memory backing the cache entries. This commit does actually change how memory is managed - this will be done in a later commit in the series. This change makes the distinction between cache entries that are associated with an index and cache entries that are not associated with an index. A main use of cache entries is with an index, and we can optimize the memory management around this. We still have other cases where a cache entry is not persisted with an index, and so we need to handle the "transient" use case as well. To keep the congnitive overhead of managing the cache entries, there will only be a single discard function. This means there must be enough information kept with the cache entry so that we know how to discard them. A summary of the main functions in the API is: make_cache_entry: create cache entry for use in an index. Uses specified parameters to populate cache_entry fields. make_empty_cache_entry: Create an empty cache entry for use in an index. Returns cache entry with empty fields. make_transient_cache_entry: create cache entry that is not used in an index. Uses specified parameters to populate cache_entry fields. make_empty_transient_cache_entry: create cache entry that is not used in an index. Returns cache entry with empty fields. discard_cache_entry: A single function that knows how to discard a cache entry regardless of how it was allocated. Signed-off-by: Jameson Miller <jamill@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jameson Miller committed Jul 2, 2018 at 19:49 UTC a849735bfbf159b98ead9ef4c843dc8acfd372f0
13 files changed +165 -92
apply.c
+11 -13
@@ -4090,12 +4090,12 @@ static int build_fake_ancestor(struct apply_state *state, struct patch *list)
4090 return error(_("sha1 information is lacking or useless "
4091 "(%s)."), name);
4092
4093 - ce = make_cache_entry(patch->old_mode, &oid, name, 0, 0);
4093 + ce = make_cache_entry(&result, patch->old_mode, &oid, name, 0, 0);
4094 if (!ce)
4095 return error(_("make_cache_entry failed for path '%s'"),
4096 name);
4097 if (add_index_entry(&result, ce, ADD_CACHE_OK_TO_ADD)) {
4098 - free(ce);
4098 + discard_cache_entry(ce);
4099 return error(_("could not add %s to temporary index"),
4100 name);
4101 }
@@ -4263,12 +4263,11 @@ static int add_index_file(struct apply_state *state,
4263 struct stat st;
4264 struct cache_entry *ce;
4265 int namelen = strlen(path);
4266 - unsigned ce_size = cache_entry_size(namelen);
4266
4267 if (!state->update_index)
4268 return 0;
4269
4271 - ce = xcalloc(1, ce_size);
4270 + ce = make_empty_cache_entry(&the_index, namelen);
4271 memcpy(ce->name, path, namelen);
4272 ce->ce_mode = create_ce_mode(mode);
4273 ce->ce_flags = create_ce_flags(0);
@@ -4278,13 +4277,13 @@ static int add_index_file(struct apply_state *state,
4277
4278 if (!skip_prefix(buf, "Subproject commit ", &s) ||
4279 get_oid_hex(s, &ce->oid)) {
4281 - free(ce);
4282 - return error(_("corrupt patch for submodule %s"), path);
4280 + discard_cache_entry(ce);
4281 + return error(_("corrupt patch for submodule %s"), path);
4282 }
4283 } else {
4284 if (!state->cached) {
4285 if (lstat(path, &st) < 0) {
4287 - free(ce);
4286 + discard_cache_entry(ce);
4287 return error_errno(_("unable to stat newly "
4288 "created file '%s'"),
4289 path);
@@ -4292,13 +4291,13 @@ static int add_index_file(struct apply_state *state,
4291 fill_stat_cache_info(ce, &st);
4292 }
4293 if (write_object_file(buf, size, blob_type, &ce->oid) < 0) {
4295 - free(ce);
4294 + discard_cache_entry(ce);
4295 return error(_("unable to create backing store "
4296 "for newly created file %s"), path);
4297 }
4298 }
4299 if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) {
4301 - free(ce);
4300 + discard_cache_entry(ce);
4301 return error(_("unable to add cache entry for %s"), path);
4302 }
4303
@@ -4422,27 +4421,26 @@ static int add_conflicted_stages_file(struct apply_state *state,
4421 struct patch *patch)
4422 {
4423 int stage, namelen;
4425 - unsigned ce_size, mode;
4424 + unsigned mode;
4425 struct cache_entry *ce;
4426
4427 if (!state->update_index)
4428 return 0;
4429 namelen = strlen(patch->new_name);
4431 - ce_size = cache_entry_size(namelen);
4430 mode = patch->new_mode ? patch->new_mode : (S_IFREG | 0644);
4431
4432 remove_file_from_cache(patch->new_name);
4433 for (stage = 1; stage < 4; stage++) {
4434 if (is_null_oid(&patch->threeway_stage[stage - 1]))
4435 continue;
4438 - ce = xcalloc(1, ce_size);
4436 + ce = make_empty_cache_entry(&the_index, namelen);
4437 memcpy(ce->name, patch->new_name, namelen);
4438 ce->ce_mode = create_ce_mode(mode);
4439 ce->ce_flags = create_ce_flags(stage);
4440 ce->ce_namelen = namelen;
4441 oidcpy(&ce->oid, &patch->threeway_stage[stage - 1]);
4442 if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD) < 0) {
4445 - free(ce);
4443 + discard_cache_entry(ce);
4444 return error(_("unable to add cache entry for %s"),
4445 patch->new_name);
4446 }
blame.c
+2 -3
@@ -154,7 +154,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
154 struct strbuf buf = STRBUF_INIT;
155 const char *ident;
156 time_t now;
157 - int size, len;
157 + int len;
158 struct cache_entry *ce;
159 unsigned mode;
160 struct strbuf msg = STRBUF_INIT;
@@ -252,8 +252,7 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,
252 /* Let's not bother reading from HEAD tree */
253 mode = S_IFREG | 0644;
254 }
255 - size = cache_entry_size(len);
256 - ce = xcalloc(1, size);
255 + ce = make_empty_cache_entry(&the_index, len);
256 oidcpy(&ce->oid, &origin->blob_oid);
257 memcpy(ce->name, path, len);
258 ce->ce_flags = create_ce_flags(0);
builtin/checkout.c
+4 -4
@@ -77,7 +77,7 @@ static int update_some(const struct object_id *oid, struct strbuf *base,
77 return READ_TREE_RECURSIVE;
78
79 len = base->len + strlen(pathname);
80 - ce = xcalloc(1, cache_entry_size(len));
80 + ce = make_empty_cache_entry(&the_index, len);
81 oidcpy(&ce->oid, oid);
82 memcpy(ce->name, base->buf, base->len);
83 memcpy(ce->name + base->len, pathname, len - base->len);
@@ -96,7 +96,7 @@ static int update_some(const struct object_id *oid, struct strbuf *base,
96 if (ce->ce_mode == old->ce_mode &&
97 !oidcmp(&ce->oid, &old->oid)) {
98 old->ce_flags |= CE_UPDATE;
99 - free(ce);
99 + discard_cache_entry(ce);
100 return 0;
101 }
102 }
@@ -230,11 +230,11 @@ static int checkout_merged(int pos, const struct checkout *state)
230 if (write_object_file(result_buf.ptr, result_buf.size, blob_type, &oid))
231 die(_("Unable to add merge result for '%s'"), path);
232 free(result_buf.ptr);
233 - ce = make_cache_entry(mode, &oid, path, 2, 0);
233 + ce = make_transient_cache_entry(mode, &oid, path, 2);
234 if (!ce)
235 die(_("make_cache_entry failed for path '%s'"), path);
236 status = checkout_entry(ce, state, NULL);
237 - free(ce);
237 + discard_cache_entry(ce);
238 return status;
239 }
240
builtin/difftool.c
+3 -3
@@ -321,10 +321,10 @@ static int checkout_path(unsigned mode, struct object_id *oid,
321 struct cache_entry *ce;
322 int ret;
323
324 - ce = make_cache_entry(mode, oid, path, 0, 0);
324 + ce = make_transient_cache_entry(mode, oid, path, 0);
325 ret = checkout_entry(ce, state, NULL);
326
327 - free(ce);
327 + discard_cache_entry(ce);
328 return ret;
329 }
330
@@ -488,7 +488,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
488 * index.
489 */
490 struct cache_entry *ce2 =
491 - make_cache_entry(rmode, &roid,
491 + make_cache_entry(&wtindex, rmode, &roid,
492 dst_path, 0, 0);
493
494 add_index_entry(&wtindex, ce2,
builtin/reset.c
+1 -1
@@ -134,7 +134,7 @@ static void update_index_from_diff(struct diff_queue_struct *q,
134 continue;
135 }
136
137 - ce = make_cache_entry(one->mode, &one->oid, one->path,
137 + ce = make_cache_entry(&the_index, one->mode, &one->oid, one->path,
138 0, 0);
139 if (!ce)
140 die(_("make_cache_entry failed for path '%s'"),
builtin/update-index.c
+11 -15
@@ -268,15 +268,14 @@ static int process_lstat_error(const char *path, int err)
268
269 static int add_one_path(const struct cache_entry *old, const char *path, int len, struct stat *st)
270 {
271 - int option, size;
271 + int option;
272 struct cache_entry *ce;
273
274 /* Was the old index entry already up-to-date? */
275 if (old && !ce_stage(old) && !ce_match_stat(old, st, 0))
276 return 0;
277
278 - size = cache_entry_size(len);
279 - ce = xcalloc(1, size);
278 + ce = make_empty_cache_entry(&the_index, len);
279 memcpy(ce->name, path, len);
280 ce->ce_flags = create_ce_flags(0);
281 ce->ce_namelen = len;
@@ -285,13 +284,13 @@ static int add_one_path(const struct cache_entry *old, const char *path, int len
284
285 if (index_path(&ce->oid, path, st,
286 info_only ? 0 : HASH_WRITE_OBJECT)) {
288 - free(ce);
287 + discard_cache_entry(ce);
288 return -1;
289 }
290 option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
291 option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
292 if (add_cache_entry(ce, option)) {
294 - free(ce);
293 + discard_cache_entry(ce);
294 return error("%s: cannot add to the index - missing --add option?", path);
295 }
296 return 0;
@@ -402,15 +401,14 @@ static int process_path(const char *path, struct stat *st, int stat_errno)
401 static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
402 const char *path, int stage)
403 {
405 - int size, len, option;
404 + int len, option;
405 struct cache_entry *ce;
406
407 if (!verify_path(path, mode))
408 return error("Invalid path '%s'", path);
409
410 len = strlen(path);
412 - size = cache_entry_size(len);
413 - ce = xcalloc(1, size);
411 + ce = make_empty_cache_entry(&the_index, len);
412
413 oidcpy(&ce->oid, oid);
414 memcpy(ce->name, path, len);
@@ -599,7 +597,6 @@ static struct cache_entry *read_one_ent(const char *which,
597 {
598 unsigned mode;
599 struct object_id oid;
602 - int size;
600 struct cache_entry *ce;
601
602 if (get_tree_entry(ent, path, &oid, &mode)) {
@@ -612,8 +609,7 @@ static struct cache_entry *read_one_ent(const char *which,
609 error("%s: not a blob in %s branch.", path, which);
610 return NULL;
611 }
615 - size = cache_entry_size(namelen);
616 - ce = xcalloc(1, size);
612 + ce = make_empty_cache_entry(&the_index, namelen);
613
614 oidcpy(&ce->oid, &oid);
615 memcpy(ce->name, path, namelen);
@@ -690,8 +686,8 @@ static int unresolve_one(const char *path)
686 error("%s: cannot add their version to the index.", path);
687 ret = -1;
688 free_return:
693 - free(ce_2);
694 - free(ce_3);
689 + discard_cache_entry(ce_2);
690 + discard_cache_entry(ce_3);
691 return ret;
692 }
693
@@ -758,7 +754,7 @@ static int do_reupdate(int ac, const char **av,
754 ce->name, ce_namelen(ce), 0);
755 if (old && ce->ce_mode == old->ce_mode &&
756 !oidcmp(&ce->oid, &old->oid)) {
761 - free(old);
757 + discard_cache_entry(old);
758 continue; /* unchanged */
759 }
760 /* Be careful. The working tree may not have the
@@ -769,7 +765,7 @@ static int do_reupdate(int ac, const char **av,
765 path = xstrdup(ce->name);
766 update_one(path);
767 free(path);
772 - free(old);
768 + discard_cache_entry(old);
769 if (save_nr != active_nr)
770 goto redo;
771 }
cache.h
+34 -6
@@ -339,6 +339,40 @@ extern void remove_name_hash(struct index_state *istate, struct cache_entry *ce)
339 extern void free_name_hash(struct index_state *istate);
340
341
342 +/* Cache entry creation and cleanup */
343 +
344 +/*
345 + * Create cache_entry intended for use in the specified index. Caller
346 + * is responsible for discarding the cache_entry with
347 + * `discard_cache_entry`.
348 + */
349 +struct cache_entry *make_cache_entry(struct index_state *istate,
350 + unsigned int mode,
351 + const struct object_id *oid,
352 + const char *path,
353 + int stage,
354 + unsigned int refresh_options);
355 +
356 +struct cache_entry *make_empty_cache_entry(struct index_state *istate,
357 + size_t name_len);
358 +
359 +/*
360 + * Create a cache_entry that is not intended to be added to an index.
361 + * Caller is responsible for discarding the cache_entry
362 + * with `discard_cache_entry`.
363 + */
364 +struct cache_entry *make_transient_cache_entry(unsigned int mode,
365 + const struct object_id *oid,
366 + const char *path,
367 + int stage);
368 +
369 +struct cache_entry *make_empty_transient_cache_entry(size_t name_len);
370 +
371 +/*
372 + * Discard cache entry.
373 + */
374 +void discard_cache_entry(struct cache_entry *ce);
375 +
376 #ifndef NO_THE_INDEX_COMPATIBILITY_MACROS
377 #define active_cache (the_index.cache)
378 #define active_nr (the_index.cache_nr)
@@ -698,12 +732,6 @@ extern int remove_file_from_index(struct index_state *, const char *path);
732 extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
733 extern int add_file_to_index(struct index_state *, const char *path, int flags);
734
701 -extern struct cache_entry *make_cache_entry(unsigned int mode,
702 - const struct object_id *oid,
703 - const char *path,
704 - int stage,
705 - unsigned int refresh_options);
706 -
735 extern int chmod_index_entry(struct index_state *, struct cache_entry *ce, char flip);
736 extern int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
737 extern void set_object_name_for_intent_to_add_entry(struct cache_entry *ce);
merge-recursive.c
+1 -1
@@ -315,7 +315,7 @@ static int add_cacheinfo(struct merge_options *o,
315 struct cache_entry *ce;
316 int ret;
317
318 - ce = make_cache_entry(mode, oid ? oid : &null_oid, path, stage, 0);
318 + ce = make_cache_entry(&the_index, mode, oid ? oid : &null_oid, path, stage, 0);
319 if (!ce)
320 return err(o, _("add_cacheinfo failed for path '%s'; merge aborting."), path);
321
read-cache.c
+65 -28
@@ -61,7 +61,7 @@ static void replace_index_entry(struct index_state *istate, int nr, struct cache
61
62 replace_index_entry_in_base(istate, old, ce);
63 remove_name_hash(istate, old);
64 - free(old);
64 + discard_cache_entry(old);
65 ce->ce_flags &= ~CE_HASHED;
66 set_index_entry(istate, nr, ce);
67 ce->ce_flags |= CE_UPDATE_IN_BASE;
@@ -74,7 +74,7 @@ void rename_index_entry_at(struct index_state *istate, int nr, const char *new_n
74 struct cache_entry *old_entry = istate->cache[nr], *new_entry;
75 int namelen = strlen(new_name);
76
77 - new_entry = xmalloc(cache_entry_size(namelen));
77 + new_entry = make_empty_cache_entry(istate, namelen);
78 copy_cache_entry(new_entry, old_entry);
79 new_entry->ce_flags &= ~CE_HASHED;
80 new_entry->ce_namelen = namelen;
@@ -623,7 +623,7 @@ static struct cache_entry *create_alias_ce(struct index_state *istate,
623
624 /* Ok, create the new entry using the name of the existing alias */
625 len = ce_namelen(alias);
626 - new_entry = xcalloc(1, cache_entry_size(len));
626 + new_entry = make_empty_cache_entry(istate, len);
627 memcpy(new_entry->name, alias->name, len);
628 copy_cache_entry(new_entry, ce);
629 save_or_free_index_entry(istate, ce);
@@ -640,7 +640,7 @@ void set_object_name_for_intent_to_add_entry(struct cache_entry *ce)
640
641 int add_to_index(struct index_state *istate, const char *path, struct stat *st, int flags)
642 {
643 - int size, namelen, was_same;
643 + int namelen, was_same;
644 mode_t st_mode = st->st_mode;
645 struct cache_entry *ce, *alias = NULL;
646 unsigned ce_option = CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE|CE_MATCH_RACY_IS_DIRTY;
@@ -662,8 +662,7 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
662 while (namelen && path[namelen-1] == '/')
663 namelen--;
664 }
665 - size = cache_entry_size(namelen);
666 - ce = xcalloc(1, size);
665 + ce = make_empty_cache_entry(istate, namelen);
666 memcpy(ce->name, path, namelen);
667 ce->ce_namelen = namelen;
668 if (!intent_only)
@@ -704,13 +703,13 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
703 ce_mark_uptodate(alias);
704 alias->ce_flags |= CE_ADDED;
705
707 - free(ce);
706 + discard_cache_entry(ce);
707 return 0;
708 }
709 }
710 if (!intent_only) {
711 if (index_path(&ce->oid, path, st, newflags)) {
713 - free(ce);
712 + discard_cache_entry(ce);
713 return error("unable to index file %s", path);
714 }
715 } else
@@ -727,9 +726,9 @@ int add_to_index(struct index_state *istate, const char *path, struct stat *st,
726 ce->ce_mode == alias->ce_mode);
727
728 if (pretend)
730 - free(ce);
729 + discard_cache_entry(ce);
730 else if (add_index_entry(istate, ce, add_option)) {
732 - free(ce);
731 + discard_cache_entry(ce);
732 return error("unable to add %s to index", path);
733 }
734 if (verbose && !was_same)
@@ -745,14 +744,25 @@ int add_file_to_index(struct index_state *istate, const char *path, int flags)
744 return add_to_index(istate, path, &st, flags);
745 }
746
748 -struct cache_entry *make_cache_entry(unsigned int mode,
747 +struct cache_entry *make_empty_cache_entry(struct index_state *istate, size_t len)
748 +{
749 + return xcalloc(1, cache_entry_size(len));
750 +}
751 +
752 +struct cache_entry *make_empty_transient_cache_entry(size_t len)
753 +{
754 + return xcalloc(1, cache_entry_size(len));
755 +}
756 +
757 +struct cache_entry *make_cache_entry(struct index_state *istate,
758 + unsigned int mode,
759 const struct object_id *oid,
760 const char *path,
761 int stage,
762 unsigned int refresh_options)
763 {
754 - int size, len;
764 struct cache_entry *ce, *ret;
765 + int len;
766
767 if (!verify_path(path, mode)) {
768 error("Invalid path '%s'", path);
@@ -760,8 +770,7 @@ struct cache_entry *make_cache_entry(unsigned int mode,
770 }
771
772 len = strlen(path);
763 - size = cache_entry_size(len);
764 - ce = xcalloc(1, size);
773 + ce = make_empty_cache_entry(istate, len);
774
775 oidcpy(&ce->oid, oid);
776 memcpy(ce->name, path, len);
@@ -771,10 +780,33 @@ struct cache_entry *make_cache_entry(unsigned int mode,
780
781 ret = refresh_cache_entry(&the_index, ce, refresh_options);
782 if (ret != ce)
774 - free(ce);
783 + discard_cache_entry(ce);
784 return ret;
785 }
786
787 +struct cache_entry *make_transient_cache_entry(unsigned int mode, const struct object_id *oid,
788 + const char *path, int stage)
789 +{
790 + struct cache_entry *ce;
791 + int len;
792 +
793 + if (!verify_path(path, mode)) {
794 + error("Invalid path '%s'", path);
795 + return NULL;
796 + }
797 +
798 + len = strlen(path);
799 + ce = make_empty_transient_cache_entry(len);
800 +
801 + oidcpy(&ce->oid, oid);
802 + memcpy(ce->name, path, len);
803 + ce->ce_flags = create_ce_flags(stage);
804 + ce->ce_namelen = len;
805 + ce->ce_mode = create_ce_mode(mode);
806 +
807 + return ce;
808 +}
809 +
810 /*
811 * Chmod an index entry with either +x or -x.
812 *
@@ -1270,7 +1302,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
1302 {
1303 struct stat st;
1304 struct cache_entry *updated;
1273 - int changed, size;
1305 + int changed;
1306 int refresh = options & CE_MATCH_REFRESH;
1307 int ignore_valid = options & CE_MATCH_IGNORE_VALID;
1308 int ignore_skip_worktree = options & CE_MATCH_IGNORE_SKIP_WORKTREE;
@@ -1350,8 +1382,7 @@ static struct cache_entry *refresh_cache_ent(struct index_state *istate,
1382 return NULL;
1383 }
1384
1353 - size = ce_size(ce);
1354 - updated = xmalloc(size);
1385 + updated = make_empty_cache_entry(istate, ce_namelen(ce));
1386 copy_cache_entry(updated, ce);
1387 memcpy(updated->name, ce->name, ce->ce_namelen + 1);
1388 fill_stat_cache_info(updated, &st);
@@ -1637,12 +1668,13 @@ int read_index(struct index_state *istate)
1668 return read_index_from(istate, get_index_file(), get_git_dir());
1669 }
1670
1640 -static struct cache_entry *cache_entry_from_ondisk(struct ondisk_cache_entry *ondisk,
1671 +static struct cache_entry *cache_entry_from_ondisk(struct index_state *istate,
1672 + struct ondisk_cache_entry *ondisk,
1673 unsigned int flags,
1674 const char *name,
1675 size_t len)
1676 {
1645 - struct cache_entry *ce = xmalloc(cache_entry_size(len));
1677 + struct cache_entry *ce = make_empty_cache_entry(istate, len);
1678
1679 ce->ce_stat_data.sd_ctime.sec = get_be32(&ondisk->ctime.sec);
1680 ce->ce_stat_data.sd_mtime.sec = get_be32(&ondisk->mtime.sec);
@@ -1684,7 +1716,8 @@ static unsigned long expand_name_field(struct strbuf *name, const char *cp_)
1716 return (const char *)ep + 1 - cp_;
1717 }
1718
1687 -static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk,
1719 +static struct cache_entry *create_from_disk(struct index_state *istate,
1720 + struct ondisk_cache_entry *ondisk,
1721 unsigned long *ent_size,
1722 struct strbuf *previous_name)
1723 {
@@ -1715,13 +1748,13 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk,
1748 /* v3 and earlier */
1749 if (len == CE_NAMEMASK)
1750 len = strlen(name);
1718 - ce = cache_entry_from_ondisk(ondisk, flags, name, len);
1751 + ce = cache_entry_from_ondisk(istate, ondisk, flags, name, len);
1752
1753 *ent_size = ondisk_ce_size(ce);
1754 } else {
1755 unsigned long consumed;
1756 consumed = expand_name_field(previous_name, name);
1724 - ce = cache_entry_from_ondisk(ondisk, flags,
1757 + ce = cache_entry_from_ondisk(istate, ondisk, flags,
1758 previous_name->buf,
1759 previous_name->len);
1760
@@ -1853,7 +1886,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
1886 unsigned long consumed;
1887
1888 disk_ce = (struct ondisk_cache_entry *)((char *)mmap + src_offset);
1856 - ce = create_from_disk(disk_ce, &consumed, previous_name);
1889 + ce = create_from_disk(istate, disk_ce, &consumed, previous_name);
1890 set_index_entry(istate, i, ce);
1891
1892 src_offset += consumed;
@@ -1959,7 +1992,7 @@ int discard_index(struct index_state *istate)
1992 istate->cache[i]->index <= istate->split_index->base->cache_nr &&
1993 istate->cache[i] == istate->split_index->base->cache[istate->cache[i]->index - 1])
1994 continue;
1962 - free(istate->cache[i]);
1995 + discard_cache_entry(istate->cache[i]);
1996 }
1997 resolve_undo_clear_index(istate);
1998 istate->cache_nr = 0;
@@ -2649,14 +2682,13 @@ int read_index_unmerged(struct index_state *istate)
2682 for (i = 0; i < istate->cache_nr; i++) {
2683 struct cache_entry *ce = istate->cache[i];
2684 struct cache_entry *new_ce;
2652 - int size, len;
2685 + int len;
2686
2687 if (!ce_stage(ce))
2688 continue;
2689 unmerged = 1;
2690 len = ce_namelen(ce);
2658 - size = cache_entry_size(len);
2659 - new_ce = xcalloc(1, size);
2691 + new_ce = make_empty_cache_entry(istate, len);
2692 memcpy(new_ce->name, ce->name, len);
2693 new_ce->ce_flags = create_ce_flags(0) | CE_CONFLICTED;
2694 new_ce->ce_namelen = len;
@@ -2765,3 +2797,8 @@ void move_index_extensions(struct index_state *dst, struct index_state *src)
2797 dst->untracked = src->untracked;
2798 src->untracked = NULL;
2799 }
2800 +
2801 +void discard_cache_entry(struct cache_entry *ce)
2802 +{
2803 + free(ce);
2804 +}
resolve-undo.c
+3 -1
@@ -146,7 +146,9 @@ int unmerge_index_entry_at(struct index_state *istate, int pos)
146 struct cache_entry *nce;
147 if (!ru->mode[i])
148 continue;
149 - nce = make_cache_entry(ru->mode[i], &ru->oid[i],
149 + nce = make_cache_entry(istate,
150 + ru->mode[i],
151 + &ru->oid[i],
152 name, i + 1, 0);
153 if (matched)
154 nce->ce_flags |= CE_MATCHED;
split-index.c
+4 -4
@@ -123,7 +123,7 @@ static void replace_entry(size_t pos, void *data)
123 src->ce_flags |= CE_UPDATE_IN_BASE;
124 src->ce_namelen = dst->ce_namelen;
125 copy_cache_entry(dst, src);
126 - free(src);
126 + discard_cache_entry(src);
127 si->nr_replacements++;
128 }
129
@@ -224,7 +224,7 @@ void prepare_to_write_split_index(struct index_state *istate)
224 base->ce_flags = base_flags;
225 if (ret)
226 ce->ce_flags |= CE_UPDATE_IN_BASE;
227 - free(base);
227 + discard_cache_entry(base);
228 si->base->cache[ce->index - 1] = ce;
229 }
230 for (i = 0; i < si->base->cache_nr; i++) {
@@ -301,7 +301,7 @@ void save_or_free_index_entry(struct index_state *istate, struct cache_entry *ce
301 ce == istate->split_index->base->cache[ce->index - 1])
302 ce->ce_flags |= CE_REMOVE;
303 else
304 - free(ce);
304 + discard_cache_entry(ce);
305 }
306
307 void replace_index_entry_in_base(struct index_state *istate,
@@ -314,7 +314,7 @@ void replace_index_entry_in_base(struct index_state *istate,
314 old_entry->index <= istate->split_index->base->cache_nr) {
315 new_entry->index = old_entry->index;
316 if (old_entry != istate->split_index->base->cache[new_entry->index - 1])
317 - free(istate->split_index->base->cache[new_entry->index - 1]);
317 + discard_cache_entry(istate->split_index->base->cache[new_entry->index - 1]);
318 istate->split_index->base->cache[new_entry->index - 1] = new_entry;
319 }
320 }
tree.c
+1 -3
@@ -16,15 +16,13 @@ static int read_one_entry_opt(struct index_state *istate,
16 unsigned mode, int stage, int opt)
17 {
18 int len;
19 - unsigned int size;
19 struct cache_entry *ce;
20
21 if (S_ISDIR(mode))
22 return READ_TREE_RECURSIVE;
23
24 len = strlen(pathname);
26 - size = cache_entry_size(baselen + len);
27 - ce = xcalloc(1, size);
25 + ce = make_empty_cache_entry(istate, baselen + len);
26
27 ce->ce_mode = create_ce_mode(mode);
28 ce->ce_flags = create_ce_flags(stage);
unpack-trees.c
+25 -10
@@ -203,10 +203,10 @@ static int do_add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
203 ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
204 }
205
206 -static struct cache_entry *dup_entry(const struct cache_entry *ce)
206 +static struct cache_entry *dup_entry(const struct cache_entry *ce, struct index_state *istate)
207 {
208 unsigned int size = ce_size(ce);
209 - struct cache_entry *new_entry = xmalloc(size);
209 + struct cache_entry *new_entry = make_empty_cache_entry(istate, ce_namelen(ce));
210
211 memcpy(new_entry, ce, size);
212 return new_entry;
@@ -216,7 +216,7 @@ static void add_entry(struct unpack_trees_options *o,
216 const struct cache_entry *ce,
217 unsigned int set, unsigned int clear)
218 {
219 - do_add_entry(o, dup_entry(ce), set, clear);
219 + do_add_entry(o, dup_entry(ce, &o->result), set, clear);
220 }
221
222 /*
@@ -797,10 +797,17 @@ static int ce_in_traverse_path(const struct cache_entry *ce,
797 return (info->pathlen < ce_namelen(ce));
798 }
799
800 -static struct cache_entry *create_ce_entry(const struct traverse_info *info, const struct name_entry *n, int stage)
800 +static struct cache_entry *create_ce_entry(const struct traverse_info *info,
801 + const struct name_entry *n,
802 + int stage,
803 + struct index_state *istate,
804 + int is_transient)
805 {
806 int len = traverse_path_len(info, n);
803 - struct cache_entry *ce = xcalloc(1, cache_entry_size(len));
807 + struct cache_entry *ce =
808 + is_transient ?
809 + make_empty_transient_cache_entry(len) :
810 + make_empty_cache_entry(istate, len);
811
812 ce->ce_mode = create_ce_mode(n->mode);
813 ce->ce_flags = create_ce_flags(stage);
@@ -846,7 +853,15 @@ static int unpack_nondirectories(int n, unsigned long mask,
853 stage = 3;
854 else
855 stage = 2;
849 - src[i + o->merge] = create_ce_entry(info, names + i, stage);
856 +
857 + /*
858 + * If the merge bit is set, then the cache entries are
859 + * discarded in the following block. In this case,
860 + * construct "transient" cache_entries, as they are
861 + * not stored in the index. otherwise construct the
862 + * cache entry from the index aware logic.
863 + */
864 + src[i + o->merge] = create_ce_entry(info, names + i, stage, &o->result, o->merge);
865 }
866
867 if (o->merge) {
@@ -855,7 +870,7 @@ static int unpack_nondirectories(int n, unsigned long mask,
870 for (i = 0; i < n; i++) {
871 struct cache_entry *ce = src[i + o->merge];
872 if (ce != o->df_conflict_entry)
858 - free(ce);
873 + discard_cache_entry(ce);
874 }
875 return rc;
876 }
@@ -1787,7 +1802,7 @@ static int merged_entry(const struct cache_entry *ce,
1802 struct unpack_trees_options *o)
1803 {
1804 int update = CE_UPDATE;
1790 - struct cache_entry *merge = dup_entry(ce);
1805 + struct cache_entry *merge = dup_entry(ce, &o->result);
1806
1807 if (!old) {
1808 /*
@@ -1807,7 +1822,7 @@ static int merged_entry(const struct cache_entry *ce,
1822
1823 if (verify_absent(merge,
1824 ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) {
1810 - free(merge);
1825 + discard_cache_entry(merge);
1826 return -1;
1827 }
1828 invalidate_ce_path(merge, o);
@@ -1833,7 +1848,7 @@ static int merged_entry(const struct cache_entry *ce,
1848 update = 0;
1849 } else {
1850 if (verify_uptodate(old, o)) {
1836 - free(merge);
1851 + discard_cache_entry(merge);
1852 return -1;
1853 }
1854 /* Migrate old flags over */