Merge branch 'jm/mem-pool'
authorJunio C Hamano <gitster@pobox.com>
Wed, 25 Apr 2018 04:29:06 +0000 (13:29 +0900)
committerJunio C Hamano <gitster@pobox.com>
Wed, 25 Apr 2018 04:29:06 +0000 (13:29 +0900)
An reusable "memory pool" implementation has been extracted from
fast-import.c, which in turn has become the first user of the
mem-pool API.

* jm/mem-pool:
mem-pool: move reusable parts of memory pool into its own file
fast-import: introduce mem_pool type
fast-import: rename mem_pool type to mp_block

1  2 
Makefile
fast-import.c
diff --combined Makefile
index e7191a7e60819465bf90d9fd062fa75e8aee6212,ddbe8788132a3ab95b4cdec7b2184f4b12a24d35..50da82b0169ad7569a900a5b7dbd0b98f147a7f0
+++ b/Makefile
@@@ -29,10 -29,10 +29,10 @@@ all:
  # Perl-compatible regular expressions instead of standard or extended
  # POSIX regular expressions.
  #
 -# Currently USE_LIBPCRE is a synonym for USE_LIBPCRE1, define
 -# USE_LIBPCRE2 instead if you'd like to use version 2 of the PCRE
 -# library. The USE_LIBPCRE flag will likely be changed to mean v2 by
 -# default in future releases.
 +# USE_LIBPCRE is a synonym for USE_LIBPCRE2, define USE_LIBPCRE1
 +# instead if you'd like to use the legacy version 1 of the PCRE
 +# library. Support for version 1 will likely be removed in some future
 +# release of Git, as upstream has all but abandoned it.
  #
  # When using USE_LIBPCRE1, define NO_LIBPCRE1_JIT if the PCRE v1
  # library is compiled without --enable-jit. We will auto-detect
  # when hardlinking a file to another name and unlinking the original file right
  # away (some NTFS drivers seem to zero the contents in that scenario).
  #
 +# Define INSTALL_SYMLINKS if you prefer to have everything that can be
 +# symlinked between bin/ and libexec/ to use relative symlinks between
 +# the two. This option overrides NO_CROSS_DIRECTORY_HARDLINKS and
 +# NO_INSTALL_HARDLINKS which will also use symlinking by indirection
 +# within the same directory in some cases, INSTALL_SYMLINKS will
 +# always symlink to the final target directly.
 +#
  # Define NO_CROSS_DIRECTORY_HARDLINKS if you plan to distribute the installed
  # programs as a tar, where bin/ and libexec/ might be on different file systems.
  #
@@@ -481,7 -474,8 +481,7 @@@ ARFLAGS = rc
  # This can help installing the suite in a relocatable way.
  
  prefix = $(HOME)
 -bindir_relative = bin
 -bindir = $(prefix)/$(bindir_relative)
 +bindir = $(prefix)/bin
  mandir = $(prefix)/share/man
  infodir = $(prefix)/share/info
  gitexecdir = libexec/git-core
@@@ -498,10 -492,8 +498,10 @@@ lib = li
  # DESTDIR =
  pathsep = :
  
 +bindir_relative = $(patsubst $(prefix)/%,%,$(bindir))
  mandir_relative = $(patsubst $(prefix)/%,%,$(mandir))
  infodir_relative = $(patsubst $(prefix)/%,%,$(infodir))
 +gitexecdir_relative = $(patsubst $(prefix)/%,%,$(gitexecdir))
  htmldir_relative = $(patsubst $(prefix)/%,%,$(htmldir))
  
  export prefix bindir sharedir sysconfdir gitwebdir perllibdir localedir
@@@ -554,7 -546,6 +554,7 @@@ SCRIPT_PERL 
  SCRIPT_PYTHON =
  SCRIPT_SH =
  SCRIPT_LIB =
 +TEST_BUILTINS_OBJS =
  TEST_PROGRAMS_NEED_X =
  
  # Having this variable in your environment would break pipelines because
@@@ -660,49 -651,47 +660,49 @@@ X 
  
  PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS))
  
 -TEST_PROGRAMS_NEED_X += test-chmtime
 -TEST_PROGRAMS_NEED_X += test-ctype
 -TEST_PROGRAMS_NEED_X += test-config
 -TEST_PROGRAMS_NEED_X += test-date
 -TEST_PROGRAMS_NEED_X += test-delta
 -TEST_PROGRAMS_NEED_X += test-drop-caches
 -TEST_PROGRAMS_NEED_X += test-dump-cache-tree
 +TEST_BUILTINS_OBJS += test-chmtime.o
 +TEST_BUILTINS_OBJS += test-config.o
 +TEST_BUILTINS_OBJS += test-ctype.o
 +TEST_BUILTINS_OBJS += test-date.o
 +TEST_BUILTINS_OBJS += test-delta.o
 +TEST_BUILTINS_OBJS += test-drop-caches.o
 +TEST_BUILTINS_OBJS += test-dump-cache-tree.o
 +TEST_BUILTINS_OBJS += test-dump-split-index.o
 +TEST_BUILTINS_OBJS += test-example-decorate.o
 +TEST_BUILTINS_OBJS += test-genrandom.o
 +TEST_BUILTINS_OBJS += test-hashmap.o
 +TEST_BUILTINS_OBJS += test-index-version.o
 +TEST_BUILTINS_OBJS += test-lazy-init-name-hash.o
 +TEST_BUILTINS_OBJS += test-match-trees.o
 +TEST_BUILTINS_OBJS += test-mergesort.o
 +TEST_BUILTINS_OBJS += test-mktemp.o
 +TEST_BUILTINS_OBJS += test-online-cpus.o
 +TEST_BUILTINS_OBJS += test-path-utils.o
 +TEST_BUILTINS_OBJS += test-prio-queue.o
 +TEST_BUILTINS_OBJS += test-read-cache.o
 +TEST_BUILTINS_OBJS += test-ref-store.o
 +TEST_BUILTINS_OBJS += test-regex.o
 +TEST_BUILTINS_OBJS += test-revision-walking.o
 +TEST_BUILTINS_OBJS += test-run-command.o
 +TEST_BUILTINS_OBJS += test-scrap-cache-tree.o
 +TEST_BUILTINS_OBJS += test-sha1-array.o
 +TEST_BUILTINS_OBJS += test-sha1.o
 +TEST_BUILTINS_OBJS += test-sigchain.o
 +TEST_BUILTINS_OBJS += test-strcmp-offset.o
 +TEST_BUILTINS_OBJS += test-string-list.o
 +TEST_BUILTINS_OBJS += test-submodule-config.o
 +TEST_BUILTINS_OBJS += test-subprocess.o
 +TEST_BUILTINS_OBJS += test-urlmatch-normalization.o
 +TEST_BUILTINS_OBJS += test-wildmatch.o
 +TEST_BUILTINS_OBJS += test-write-cache.o
 +
  TEST_PROGRAMS_NEED_X += test-dump-fsmonitor
 -TEST_PROGRAMS_NEED_X += test-dump-split-index
  TEST_PROGRAMS_NEED_X += test-dump-untracked-cache
 -TEST_PROGRAMS_NEED_X += test-example-decorate
  TEST_PROGRAMS_NEED_X += test-fake-ssh
 -TEST_PROGRAMS_NEED_X += test-genrandom
 -TEST_PROGRAMS_NEED_X += test-hashmap
 -TEST_PROGRAMS_NEED_X += test-index-version
 -TEST_PROGRAMS_NEED_X += test-lazy-init-name-hash
  TEST_PROGRAMS_NEED_X += test-line-buffer
 -TEST_PROGRAMS_NEED_X += test-match-trees
 -TEST_PROGRAMS_NEED_X += test-mergesort
 -TEST_PROGRAMS_NEED_X += test-mktemp
 -TEST_PROGRAMS_NEED_X += test-online-cpus
  TEST_PROGRAMS_NEED_X += test-parse-options
 -TEST_PROGRAMS_NEED_X += test-path-utils
 -TEST_PROGRAMS_NEED_X += test-prio-queue
 -TEST_PROGRAMS_NEED_X += test-read-cache
 -TEST_PROGRAMS_NEED_X += test-write-cache
 -TEST_PROGRAMS_NEED_X += test-ref-store
 -TEST_PROGRAMS_NEED_X += test-regex
 -TEST_PROGRAMS_NEED_X += test-revision-walking
 -TEST_PROGRAMS_NEED_X += test-run-command
 -TEST_PROGRAMS_NEED_X += test-scrap-cache-tree
 -TEST_PROGRAMS_NEED_X += test-sha1
 -TEST_PROGRAMS_NEED_X += test-sha1-array
 -TEST_PROGRAMS_NEED_X += test-sigchain
 -TEST_PROGRAMS_NEED_X += test-strcmp-offset
 -TEST_PROGRAMS_NEED_X += test-string-list
 -TEST_PROGRAMS_NEED_X += test-submodule-config
 -TEST_PROGRAMS_NEED_X += test-subprocess
  TEST_PROGRAMS_NEED_X += test-svn-fe
 -TEST_PROGRAMS_NEED_X += test-urlmatch-normalization
 -TEST_PROGRAMS_NEED_X += test-wildmatch
 +TEST_PROGRAMS_NEED_X += test-tool
  
  TEST_PROGRAMS = $(patsubst %,t/helper/%$X,$(TEST_PROGRAMS_NEED_X))
  
@@@ -783,7 -772,6 +783,7 @@@ LIB_OBJS += branch.
  LIB_OBJS += bulk-checkin.o
  LIB_OBJS += bundle.o
  LIB_OBJS += cache-tree.o
 +LIB_OBJS += chdir-notify.o
  LIB_OBJS += checkout.o
  LIB_OBJS += color.o
  LIB_OBJS += column.o
@@@ -819,7 -807,7 +819,7 @@@ LIB_OBJS += ewah/bitmap.
  LIB_OBJS += ewah/ewah_bitmap.o
  LIB_OBJS += ewah/ewah_io.o
  LIB_OBJS += ewah/ewah_rlw.o
 -LIB_OBJS += exec_cmd.o
 +LIB_OBJS += exec-cmd.o
  LIB_OBJS += fetch-object.o
  LIB_OBJS += fetch-pack.o
  LIB_OBJS += fsck.o
@@@ -845,6 -833,7 +845,7 @@@ LIB_OBJS += log-tree.
  LIB_OBJS += mailinfo.o
  LIB_OBJS += mailmap.o
  LIB_OBJS += match-trees.o
+ LIB_OBJS += mem-pool.o
  LIB_OBJS += merge.o
  LIB_OBJS += merge-blobs.o
  LIB_OBJS += merge-recursive.o
@@@ -889,7 -878,7 +890,7 @@@ LIB_OBJS += refs/packed-backend.
  LIB_OBJS += refs/ref-cache.o
  LIB_OBJS += ref-filter.o
  LIB_OBJS += remote.o
 -LIB_OBJS += replace_object.o
 +LIB_OBJS += replace-object.o
  LIB_OBJS += repository.o
  LIB_OBJS += rerere.o
  LIB_OBJS += resolve-undo.o
@@@ -901,8 -890,8 +902,8 @@@ LIB_OBJS += server-info.
  LIB_OBJS += setup.o
  LIB_OBJS += sha1-array.o
  LIB_OBJS += sha1-lookup.o
 -LIB_OBJS += sha1_file.o
 -LIB_OBJS += sha1_name.o
 +LIB_OBJS += sha1-file.o
 +LIB_OBJS += sha1-name.o
  LIB_OBJS += shallow.o
  LIB_OBJS += sideband.o
  LIB_OBJS += sigchain.o
@@@ -937,7 -926,7 +938,7 @@@ LIB_OBJS += walker.
  LIB_OBJS += wildmatch.o
  LIB_OBJS += worktree.o
  LIB_OBJS += wrapper.o
 -LIB_OBJS += write_or_die.o
 +LIB_OBJS += write-or-die.o
  LIB_OBJS += ws.o
  LIB_OBJS += wt-status.o
  LIB_OBJS += xdiff-interface.o
@@@ -1182,18 -1171,13 +1183,18 @@@ ifdef NO_LIBGEN_
        COMPAT_OBJS += compat/basename.o
  endif
  
 -USE_LIBPCRE1 ?= $(USE_LIBPCRE)
 +USE_LIBPCRE2 ?= $(USE_LIBPCRE)
  
 -ifneq (,$(USE_LIBPCRE1))
 -      ifdef USE_LIBPCRE2
 -$(error Only set USE_LIBPCRE1 (or its alias USE_LIBPCRE) or USE_LIBPCRE2, not both!)
 +ifneq (,$(USE_LIBPCRE2))
 +      ifdef USE_LIBPCRE1
 +$(error Only set USE_LIBPCRE2 (or its alias USE_LIBPCRE) or USE_LIBPCRE1, not both!)
        endif
  
 +      BASIC_CFLAGS += -DUSE_LIBPCRE2
 +      EXTLIBS += -lpcre2-8
 +endif
 +
 +ifdef USE_LIBPCRE1
        BASIC_CFLAGS += -DUSE_LIBPCRE1
        EXTLIBS += -lpcre
  
@@@ -1202,6 -1186,11 +1203,6 @@@ ifdef NO_LIBPCRE1_JI
  endif
  endif
  
 -ifdef USE_LIBPCRE2
 -      BASIC_CFLAGS += -DUSE_LIBPCRE2
 -      EXTLIBS += -lpcre2-8
 -endif
 -
  ifdef LIBPCREDIR
        BASIC_CFLAGS += -I$(LIBPCREDIR)/include
        EXTLIBS += -L$(LIBPCREDIR)/$(lib) $(CC_LD_DYNPATH)$(LIBPCREDIR)/$(lib)
@@@ -1753,7 -1742,6 +1754,7 @@@ infodir_relative_SQ = $(subst ','\'',$(
  perllibdir_SQ = $(subst ','\'',$(perllibdir))
  localedir_SQ = $(subst ','\'',$(localedir))
  gitexecdir_SQ = $(subst ','\'',$(gitexecdir))
 +gitexecdir_relative_SQ = $(subst ','\'',$(gitexecdir_relative))
  template_dir_SQ = $(subst ','\'',$(template_dir))
  htmldir_relative_SQ = $(subst ','\'',$(htmldir_relative))
  prefix_SQ = $(subst ','\'',$(prefix))
@@@ -2096,7 -2084,7 +2097,7 @@@ VCSSVN_OBJS += vcs-svn/fast_export.
  VCSSVN_OBJS += vcs-svn/svndiff.o
  VCSSVN_OBJS += vcs-svn/svndump.o
  
 -TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS))
 +TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS)) $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
  OBJECTS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \
        $(XDIFF_OBJS) \
        $(VCSSVN_OBJS) \
@@@ -2156,8 -2144,8 +2157,8 @@@ els
  $(OBJECTS): $(LIB_H)
  endif
  
 -exec_cmd.sp exec_cmd.s exec_cmd.o: GIT-PREFIX
 -exec_cmd.sp exec_cmd.s exec_cmd.o: EXTRA_CPPFLAGS = \
 +exec-cmd.sp exec-cmd.s exec-cmd.o: GIT-PREFIX
 +exec-cmd.sp exec-cmd.s exec-cmd.o: EXTRA_CPPFLAGS = \
        '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \
        '-DBINDIR="$(bindir_relative_SQ)"' \
        '-DPREFIX="$(prefix_SQ)"'
@@@ -2507,12 -2495,10 +2508,12 @@@ t/helper/test-svn-fe$X: $(VCSSVN_LIB
  
  .PRECIOUS: $(TEST_OBJS)
  
 +t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
 +
  t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)
  
 -check-sha1:: t/helper/test-sha1$X
 +check-sha1:: t/helper/test-tool$X
        t/helper/test-sha1.sh
  
  SP_OBJ = $(patsubst %.o,%.sp,$(C_OBJ))
@@@ -2621,44 -2607,35 +2622,44 @@@ endi
  
        bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
        execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
 +      destdir_from_execdir_SQ=$$(echo '$(gitexecdir_relative_SQ)' | sed -e 's|[^/][^/]*|..|g') && \
        { test "$$bindir/" = "$$execdir/" || \
          for p in git$X $(filter $(install_bindir_programs),$(ALL_PROGRAMS)); do \
                $(RM) "$$execdir/$$p" && \
 -              test -z "$(NO_INSTALL_HARDLINKS)$(NO_CROSS_DIRECTORY_HARDLINKS)" && \
 -              ln "$$bindir/$$p" "$$execdir/$$p" 2>/dev/null || \
 -              cp "$$bindir/$$p" "$$execdir/$$p" || exit; \
 +              test -n "$(INSTALL_SYMLINKS)" && \
 +              ln -s "$$destdir_from_execdir_SQ/$(bindir_relative_SQ)/$$p" "$$execdir/$$p" || \
 +              { test -z "$(NO_INSTALL_HARDLINKS)$(NO_CROSS_DIRECTORY_HARDLINKS)" && \
 +                ln "$$bindir/$$p" "$$execdir/$$p" 2>/dev/null || \
 +                cp "$$bindir/$$p" "$$execdir/$$p" || exit; } \
          done; \
        } && \
        for p in $(filter $(install_bindir_programs),$(BUILT_INS)); do \
                $(RM) "$$bindir/$$p" && \
 -              test -z "$(NO_INSTALL_HARDLINKS)" && \
 -              ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \
 -              ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \
 -              cp "$$bindir/git$X" "$$bindir/$$p" || exit; \
 +              test -n "$(INSTALL_SYMLINKS)" && \
 +              ln -s "git$X" "$$bindir/$$p" || \
 +              { test -z "$(NO_INSTALL_HARDLINKS)" && \
 +                ln "$$bindir/git$X" "$$bindir/$$p" 2>/dev/null || \
 +                ln -s "git$X" "$$bindir/$$p" 2>/dev/null || \
 +                cp "$$bindir/git$X" "$$bindir/$$p" || exit; } \
        done && \
        for p in $(BUILT_INS); do \
                $(RM) "$$execdir/$$p" && \
 -              test -z "$(NO_INSTALL_HARDLINKS)" && \
 -              ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
 -              ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
 -              cp "$$execdir/git$X" "$$execdir/$$p" || exit; \
 +              test -n "$(INSTALL_SYMLINKS)" && \
 +              ln -s "$$destdir_from_execdir_SQ/$(bindir_relative_SQ)/git$X" "$$execdir/$$p" || \
 +              { test -z "$(NO_INSTALL_HARDLINKS)" && \
 +                ln "$$execdir/git$X" "$$execdir/$$p" 2>/dev/null || \
 +                ln -s "git$X" "$$execdir/$$p" 2>/dev/null || \
 +                cp "$$execdir/git$X" "$$execdir/$$p" || exit; } \
        done && \
        remote_curl_aliases="$(REMOTE_CURL_ALIASES)" && \
        for p in $$remote_curl_aliases; do \
                $(RM) "$$execdir/$$p" && \
 -              test -z "$(NO_INSTALL_HARDLINKS)" && \
 -              ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
 -              ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
 -              cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; \
 +              test -n "$(INSTALL_SYMLINKS)" && \
 +              ln -s "git-remote-http$X" "$$execdir/$$p" || \
 +              { test -z "$(NO_INSTALL_HARDLINKS)" && \
 +                ln "$$execdir/git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
 +                ln -s "git-remote-http$X" "$$execdir/$$p" 2>/dev/null || \
 +                cp "$$execdir/git-remote-http$X" "$$execdir/$$p" || exit; } \
        done && \
        ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
  
diff --combined fast-import.c
index 99f8f56e8c4fbd20b6e6186e26d89eda1baff0d0,ba0cb4bdfb69c3127058a3b923c94f1ea613508b..05d1079d2380694eb53570ede6eaaed97fc4c8e0
@@@ -154,7 -154,6 +154,7 @@@ Format of STDIN stream
  
  #include "builtin.h"
  #include "cache.h"
 +#include "repository.h"
  #include "config.h"
  #include "lockfile.h"
  #include "object.h"
  #include "dir.h"
  #include "run-command.h"
  #include "packfile.h"
 +#include "object-store.h"
+ #include "mem-pool.h"
  
  #define PACK_ID_BITS 16
  #define MAX_PACK_ID ((1<<PACK_ID_BITS)-1)
@@@ -211,13 -210,6 +212,6 @@@ struct last_object 
        unsigned no_swap : 1;
  };
  
- struct mem_pool {
-       struct mem_pool *next_pool;
-       char *next_free;
-       char *end;
-       uintmax_t space[FLEX_ARRAY]; /* more */
- };
  struct atom_str {
        struct atom_str *next_atom;
        unsigned short str_len;
@@@ -306,9 -298,8 +300,8 @@@ static int global_argc
  static const char **global_argv;
  
  /* Memory pools */
- static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
- static size_t total_allocd;
- static struct mem_pool *mem_pool;
+ static struct mem_pool fi_mem_pool =  {NULL, 2*1024*1024 -
+                                      sizeof(struct mp_block), 0 };
  
  /* Atom management */
  static unsigned int atom_table_sz = 4451;
@@@ -343,6 -334,7 +336,7 @@@ static unsigned int tree_entry_alloc = 
  static void *avail_tree_entry;
  static unsigned int avail_tree_table_sz = 100;
  static struct avail_tree_content **avail_tree_table;
+ static size_t tree_entry_allocd;
  static struct strbuf old_tree = STRBUF_INIT;
  static struct strbuf new_tree = STRBUF_INIT;
  
@@@ -636,49 -628,10 +630,10 @@@ static unsigned int hc_str(const char *
        return r;
  }
  
- static void *pool_alloc(size_t len)
- {
-       struct mem_pool *p;
-       void *r;
-       /* round up to a 'uintmax_t' alignment */
-       if (len & (sizeof(uintmax_t) - 1))
-               len += sizeof(uintmax_t) - (len & (sizeof(uintmax_t) - 1));
-       for (p = mem_pool; p; p = p->next_pool)
-               if ((p->end - p->next_free >= len))
-                       break;
-       if (!p) {
-               if (len >= (mem_pool_alloc/2)) {
-                       total_allocd += len;
-                       return xmalloc(len);
-               }
-               total_allocd += sizeof(struct mem_pool) + mem_pool_alloc;
-               p = xmalloc(st_add(sizeof(struct mem_pool), mem_pool_alloc));
-               p->next_pool = mem_pool;
-               p->next_free = (char *) p->space;
-               p->end = p->next_free + mem_pool_alloc;
-               mem_pool = p;
-       }
-       r = p->next_free;
-       p->next_free += len;
-       return r;
- }
- static void *pool_calloc(size_t count, size_t size)
- {
-       size_t len = count * size;
-       void *r = pool_alloc(len);
-       memset(r, 0, len);
-       return r;
- }
  static char *pool_strdup(const char *s)
  {
        size_t len = strlen(s) + 1;
-       char *r = pool_alloc(len);
+       char *r = mem_pool_alloc(&fi_mem_pool, len);
        memcpy(r, s, len);
        return r;
  }
@@@ -687,7 -640,7 +642,7 @@@ static void insert_mark(uintmax_t idnum
  {
        struct mark_set *s = marks;
        while ((idnum >> s->shift) >= 1024) {
-               s = pool_calloc(1, sizeof(struct mark_set));
+               s = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set));
                s->shift = marks->shift + 10;
                s->data.sets[0] = marks;
                marks = s;
                uintmax_t i = idnum >> s->shift;
                idnum -= i << s->shift;
                if (!s->data.sets[i]) {
-                       s->data.sets[i] = pool_calloc(1, sizeof(struct mark_set));
+                       s->data.sets[i] = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set));
                        s->data.sets[i]->shift = s->shift - 10;
                }
                s = s->data.sets[i];
@@@ -734,7 -687,7 +689,7 @@@ static struct atom_str *to_atom(const c
                if (c->str_len == len && !strncmp(s, c->str_dat, len))
                        return c;
  
-       c = pool_alloc(sizeof(struct atom_str) + len + 1);
+       c = mem_pool_alloc(&fi_mem_pool, sizeof(struct atom_str) + len + 1);
        c->str_len = len;
        memcpy(c->str_dat, s, len);
        c->str_dat[len] = 0;
@@@ -765,7 -718,7 +720,7 @@@ static struct branch *new_branch(const 
        if (check_refname_format(name, REFNAME_ALLOW_ONELEVEL))
                die("Branch name doesn't conform to GIT standards: %s", name);
  
-       b = pool_calloc(1, sizeof(struct branch));
+       b = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct branch));
        b->name = pool_strdup(name);
        b->table_next_branch = branch_table[hc];
        b->branch_tree.versions[0].mode = S_IFDIR;
@@@ -801,7 -754,7 +756,7 @@@ static struct tree_content *new_tree_co
                        avail_tree_table[hc] = f->next_avail;
        } else {
                cnt = cnt & 7 ? ((cnt / 8) + 1) * 8 : cnt;
-               f = pool_alloc(sizeof(*t) + sizeof(t->entries[0]) * cnt);
+               f = mem_pool_alloc(&fi_mem_pool, sizeof(*t) + sizeof(t->entries[0]) * cnt);
                f->entry_capacity = cnt;
        }
  
@@@ -846,7 -799,7 +801,7 @@@ static struct tree_entry *new_tree_entr
  
        if (!avail_tree_entry) {
                unsigned int n = tree_entry_alloc;
-               total_allocd += n * sizeof(struct tree_entry);
+               tree_entry_allocd += n * sizeof(struct tree_entry);
                ALLOC_ARRAY(e, n);
                avail_tree_entry = e;
                while (n-- > 1) {
@@@ -1038,7 -991,7 +993,7 @@@ static void end_packfile(void
                if (!new_p)
                        die("core git rejected index %s", idx_name);
                all_packs[pack_id] = new_p;
 -              install_packed_git(new_p);
 +              install_packed_git(the_repository, new_p);
                free(idx_name);
  
                /* Print the boundary */
@@@ -1112,8 -1065,7 +1067,8 @@@ static int store_object
        if (e->idx.offset) {
                duplicate_count_by_type[type]++;
                return 1;
 -      } else if (find_sha1_pack(oid.hash, packed_git)) {
 +      } else if (find_sha1_pack(oid.hash,
 +                                get_packed_git(the_repository))) {
                e->type = type;
                e->pack_id = MAX_PACK_ID;
                e->idx.offset = 1; /* just not zero! */
@@@ -1310,8 -1262,7 +1265,8 @@@ static void stream_blob(uintmax_t len, 
                duplicate_count_by_type[OBJ_BLOB]++;
                truncate_pack(&checkpoint);
  
 -      } else if (find_sha1_pack(oid.hash, packed_git)) {
 +      } else if (find_sha1_pack(oid.hash,
 +                                get_packed_git(the_repository))) {
                e->type = OBJ_BLOB;
                e->pack_id = MAX_PACK_ID;
                e->idx.offset = 1; /* just not zero! */
@@@ -1416,7 -1367,7 +1371,7 @@@ static void load_tree(struct tree_entr
                        die("Can't load tree %s", oid_to_hex(oid));
        } else {
                enum object_type type;
 -              buf = read_sha1_file(oid->hash, &type, &size);
 +              buf = read_object_file(oid, &type, &size);
                if (!buf || type != OBJ_TREE)
                        die("Can't load tree %s", oid_to_hex(oid));
        }
@@@ -1917,7 -1868,7 +1872,7 @@@ static void read_marks(void
                        die("corrupt mark line: %s", line);
                e = find_object(&oid);
                if (!e) {
 -                      enum object_type type = sha1_object_info(oid.hash, NULL);
 +                      enum object_type type = oid_object_info(&oid, NULL);
                        if (type < 0)
                                die("object not found: %s", oid_to_hex(&oid));
                        e = insert_object(&oid);
@@@ -2447,7 -2398,7 +2402,7 @@@ static void file_change_m(const char *p
                enum object_type expected = S_ISDIR(mode) ?
                                                OBJ_TREE: OBJ_BLOB;
                enum object_type type = oe ? oe->type :
 -                                      sha1_object_info(oid.hash, NULL);
 +                                      oid_object_info(&oid, NULL);
                if (type < 0)
                        die("%s not found: %s",
                                        S_ISDIR(mode) ?  "Tree" : "Blob",
@@@ -2587,9 -2538,8 +2542,9 @@@ static void note_change_n(const char *p
                oidcpy(&commit_oid, &commit_oe->idx.oid);
        } else if (!get_oid(p, &commit_oid)) {
                unsigned long size;
 -              char *buf = read_object_with_reference(commit_oid.hash,
 -                      commit_type, &size, commit_oid.hash);
 +              char *buf = read_object_with_reference(&commit_oid,
 +                                                     commit_type, &size,
 +                                                     &commit_oid);
                if (!buf || size < 46)
                        die("Not a valid commit: %s", p);
                free(buf);
                        die("Not a blob (actually a %s): %s",
                                type_name(oe->type), command_buf.buf);
        } else if (!is_null_oid(&oid)) {
 -              enum object_type type = sha1_object_info(oid.hash, NULL);
 +              enum object_type type = oid_object_info(&oid, NULL);
                if (type < 0)
                        die("Blob not found: %s", command_buf.buf);
                if (type != OBJ_BLOB)
@@@ -2658,8 -2608,9 +2613,8 @@@ static void parse_from_existing(struct 
                unsigned long size;
                char *buf;
  
 -              buf = read_object_with_reference(b->oid.hash,
 -                                               commit_type, &size,
 -                                               b->oid.hash);
 +              buf = read_object_with_reference(&b->oid, commit_type, &size,
 +                                               &b->oid);
                parse_from_commit(b, buf, size);
                free(buf);
        }
@@@ -2736,9 -2687,8 +2691,9 @@@ static struct hash_list *parse_merge(un
                        oidcpy(&n->oid, &oe->idx.oid);
                } else if (!get_oid(from, &n->oid)) {
                        unsigned long size;
 -                      char *buf = read_object_with_reference(n->oid.hash,
 -                              commit_type, &size, n->oid.hash);
 +                      char *buf = read_object_with_reference(&n->oid,
 +                                                             commit_type,
 +                                                             &size, &n->oid);
                        if (!buf || size < 46)
                                die("Not a valid commit: %s", from);
                        free(buf);
@@@ -2867,7 -2817,7 +2822,7 @@@ static void parse_new_tag(const char *a
        enum object_type type;
        const char *v;
  
-       t = pool_alloc(sizeof(struct tag));
+       t = mem_pool_alloc(&fi_mem_pool, sizeof(struct tag));
        memset(t, 0, sizeof(struct tag));
        t->name = pool_strdup(arg);
        if (last_tag)
        } else if (!get_oid(from, &oid)) {
                struct object_entry *oe = find_object(&oid);
                if (!oe) {
 -                      type = sha1_object_info(oid.hash, NULL);
 +                      type = oid_object_info(&oid, NULL);
                        if (type < 0)
                                die("Not a valid object: %s", from);
                } else
@@@ -2971,7 -2921,7 +2926,7 @@@ static void cat_blob(struct object_entr
        char *buf;
  
        if (!oe || oe->pack_id == MAX_PACK_ID) {
 -              buf = read_sha1_file(oid->hash, &type, &size);
 +              buf = read_object_file(oid, &type, &size);
        } else {
                type = oe->type;
                buf = gfi_unpack_entry(oe, &size);
@@@ -3053,7 -3003,7 +3008,7 @@@ static struct object_entry *dereference
        unsigned long size;
        char *buf = NULL;
        if (!oe) {
 -              enum object_type type = sha1_object_info(oid->hash, NULL);
 +              enum object_type type = oid_object_info(oid, NULL);
                if (type < 0)
                        die("object not found: %s", oid_to_hex(oid));
                /* cache it! */
                buf = gfi_unpack_entry(oe, &size);
        } else {
                enum object_type unused;
 -              buf = read_sha1_file(oid->hash, &unused, &size);
 +              buf = read_object_file(oid, &unused, &size);
        }
        if (!buf)
                die("Can't load object %s", oid_to_hex(oid));
@@@ -3466,16 -3416,17 +3421,16 @@@ int cmd_main(int argc, const char **arg
        atom_table = xcalloc(atom_table_sz, sizeof(struct atom_str*));
        branch_table = xcalloc(branch_table_sz, sizeof(struct branch*));
        avail_tree_table = xcalloc(avail_tree_table_sz, sizeof(struct avail_tree_content*));
-       marks = pool_calloc(1, sizeof(struct mark_set));
+       marks = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set));
  
        global_argc = argc;
        global_argv = argv;
  
-       rc_free = pool_alloc(cmd_save * sizeof(*rc_free));
+       rc_free = mem_pool_alloc(&fi_mem_pool, cmd_save * sizeof(*rc_free));
        for (i = 0; i < (cmd_save - 1); i++)
                rc_free[i].next = &rc_free[i + 1];
        rc_free[cmd_save - 1].next = NULL;
  
 -      prepare_packed_git();
        start_packfile();
        set_die_routine(die_nicely);
        set_checkpoint_signal();
                fprintf(stderr, "Total branches:  %10lu (%10lu loads     )\n", branch_count, branch_load_count);
                fprintf(stderr, "      marks:     %10" PRIuMAX " (%10" PRIuMAX " unique    )\n", (((uintmax_t)1) << marks->shift) * 1024, marks_set_count);
                fprintf(stderr, "      atoms:     %10u\n", atom_cnt);
-               fprintf(stderr, "Memory total:    %10" PRIuMAX " KiB\n", (total_allocd + alloc_count*sizeof(struct object_entry))/1024);
-               fprintf(stderr, "       pools:    %10lu KiB\n", (unsigned long)(total_allocd/1024));
+               fprintf(stderr, "Memory total:    %10" PRIuMAX " KiB\n", (tree_entry_allocd + fi_mem_pool.pool_alloc + alloc_count*sizeof(struct object_entry))/1024);
+               fprintf(stderr, "       pools:    %10lu KiB\n", (unsigned long)((tree_entry_allocd + fi_mem_pool.pool_alloc) /1024));
                fprintf(stderr, "     objects:    %10" PRIuMAX " KiB\n", (alloc_count*sizeof(struct object_entry))/1024);
                fprintf(stderr, "---------------------------------------------------------------------\n");
                pack_report();