diff --git a/tree-diff.c b/tree-diff.c index edb4de9b72..e164e532b2 100644 --- a/tree-diff.c +++ b/tree-diff.c @@ -14,6 +14,16 @@ */ #define S_IFXMIN_NEQ S_DIFFTREE_IFXMIN_NEQ +#define FAST_ARRAY_ALLOC(x, nr) do { \ + if ((nr) <= 2) \ + (x) = xalloca((nr) * sizeof(*(x))); \ + else \ + ALLOC_ARRAY((x), nr); \ +} while(0) +#define FAST_ARRAY_FREE(x, nr) do { \ + if ((nr) > 2) \ + free((x)); \ +} while(0) static struct combine_diff_path *ll_diff_tree_paths( struct combine_diff_path *p, const unsigned char *sha1, @@ -265,7 +275,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p, if (recurse) { const unsigned char **parents_sha1; - parents_sha1 = xalloca(nparent * sizeof(parents_sha1[0])); + FAST_ARRAY_ALLOC(parents_sha1, nparent); for (i = 0; i < nparent; ++i) { /* same rule as in emitthis */ int tpi_valid = tp && !(tp[i].entry.mode & S_IFXMIN_NEQ); @@ -277,7 +287,7 @@ static struct combine_diff_path *emit_path(struct combine_diff_path *p, strbuf_add(base, path, pathlen); strbuf_addch(base, '/'); p = ll_diff_tree_paths(p, sha1, parents_sha1, nparent, base, opt); - xalloca_free(parents_sha1); + FAST_ARRAY_FREE(parents_sha1, nparent); } strbuf_setlen(base, old_baselen); @@ -402,8 +412,8 @@ static struct combine_diff_path *ll_diff_tree_paths( void *ttree, **tptree; int i; - tp = xalloca(nparent * sizeof(tp[0])); - tptree = xalloca(nparent * sizeof(tptree[0])); + FAST_ARRAY_ALLOC(tp, nparent); + FAST_ARRAY_ALLOC(tptree, nparent); /* * load parents first, as they are probably already cached. @@ -531,8 +541,8 @@ static struct combine_diff_path *ll_diff_tree_paths( free(ttree); for (i = nparent-1; i >= 0; i--) free(tptree[i]); - xalloca_free(tptree); - xalloca_free(tp); + FAST_ARRAY_FREE(tptree, nparent); + FAST_ARRAY_FREE(tp, nparent); return p; }