Portable alloca for Git

In the next patch we'll have to use alloca() for performance reasons, but since alloca is non-standardized and is not portable, let's have a trick with compatibility wrappers: 1. at configure time, determine, do we have working alloca() through alloca.h, and define #define HAVE_ALLOCA_H if yes. 2. in code #ifdef HAVE_ALLOCA_H # include <alloca.h> # define xalloca(size) (alloca(size)) # define xalloca_free(p) do {} while(0) #else # define xalloca(size) (xmalloc(size)) # define xalloca_free(p) (free(p)) #endif and use it like func() { p = xalloca(size); ... xalloca_free(p); } This way, for systems, where alloca is available, we'll have optimal on-stack allocations with fast executions. On the other hand, on systems, where alloca is not available, this gracefully fallbacks to xmalloc/free. Both autoconf and config.mak.uname configurations were updated. For autoconf, we are not bothering considering cases, when no alloca.h is available, but alloca() works some other way - its simply alloca.h is available and works or not, everything else is deep legacy. For config.mak.uname, I've tried to make my almost-sure guess for where alloca() is available, but since I only have access to Linux it is the only change I can be sure about myself, with relevant to other changed systems people Cc'ed. NOTE SunOS and Windows had explicit -DHAVE_ALLOCA_H in their configurations. I've changed that to now-common HAVE_ALLOCA_H=YesPlease which should be correct. Cc: Brandon Casey <drafnel@gmail.com> Cc: Marius Storm-Olsen <mstormo@gmail.com> Cc: Johannes Sixt <j6t@kdbg.org> Cc: Johannes Schindelin <Johannes.Schindelin@gmx.de> Cc: Ramsay Jones <ramsay@ramsay1.demon.co.uk> Cc: Gerrit Pape <pape@smarden.org> Cc: Petr Salinger <Petr.Salinger@seznam.cz> Cc: Jonathan Nieder <jrnieder@gmail.com> Acked-by: Thomas Schwinge <thomas@codesourcery.com> (GNU Hurd changes) Signed-off-by: Kirill Smelkov <kirr@mns.spb.ru> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Kirill Smelkov committed Mar 27, 2014 at 18:22 UTC 61f76a3612db199a9eb9090c2605d8fc35ffc41c
4 files changed +30 -2
Makefile
+6
@@ -30,6 +30,8 @@ all::
30 # Define LIBPCREDIR=/foo/bar if your libpcre header and library files are in
31 # /foo/bar/include and /foo/bar/lib directories.
32 #
33 +# Define HAVE_ALLOCA_H if you have working alloca(3) defined in that header.
34 +#
35 # Define NO_CURL if you do not have libcurl installed. git-http-fetch and
36 # git-http-push are not built, and you cannot use http:// and https://
37 # transports (neither smart nor dumb).
@@ -1099,6 +1101,10 @@ ifdef USE_LIBPCRE
1101 EXTLIBS += -lpcre
1102 endif
1103
1104 +ifdef HAVE_ALLOCA_H
1105 + BASIC_CFLAGS += -DHAVE_ALLOCA_H
1106 +endif
1107 +
1108 ifdef NO_CURL
1109 BASIC_CFLAGS += -DNO_CURL
1110 REMOTE_CURL_PRIMARY =
config.mak.uname
+8 -2
@@ -28,6 +28,7 @@ ifeq ($(uname_S),OSF1)
28 NO_NSEC = YesPlease
29 endif
30 ifeq ($(uname_S),Linux)
31 + HAVE_ALLOCA_H = YesPlease
32 NO_STRLCPY = YesPlease
33 NO_MKSTEMPS = YesPlease
34 HAVE_PATHS_H = YesPlease
@@ -35,6 +36,7 @@ ifeq ($(uname_S),Linux)
36 HAVE_DEV_TTY = YesPlease
37 endif
38 ifeq ($(uname_S),GNU/kFreeBSD)
39 + HAVE_ALLOCA_H = YesPlease
40 NO_STRLCPY = YesPlease
41 NO_MKSTEMPS = YesPlease
42 HAVE_PATHS_H = YesPlease
@@ -103,6 +105,7 @@ ifeq ($(uname_S),SunOS)
105 NEEDS_NSL = YesPlease
106 SHELL_PATH = /bin/bash
107 SANE_TOOL_PATH = /usr/xpg6/bin:/usr/xpg4/bin
108 + HAVE_ALLOCA_H = YesPlease
109 NO_STRCASESTR = YesPlease
110 NO_MEMMEM = YesPlease
111 NO_MKDTEMP = YesPlease
@@ -146,7 +149,7 @@ ifeq ($(uname_S),SunOS)
149 endif
150 INSTALL = /usr/ucb/install
151 TAR = gtar
149 - BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__ -DHAVE_ALLOCA_H
152 + BASIC_CFLAGS += -D__EXTENSIONS__ -D__sun__
153 endif
154 ifeq ($(uname_O),Cygwin)
155 ifeq ($(shell expr "$(uname_R)" : '1\.[1-6]\.'),4)
@@ -166,6 +169,7 @@ ifeq ($(uname_O),Cygwin)
169 else
170 NO_REGEX = UnfortunatelyYes
171 endif
172 + HAVE_ALLOCA_H = YesPlease
173 NEEDS_LIBICONV = YesPlease
174 NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
175 NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
@@ -239,6 +243,7 @@ ifeq ($(uname_S),AIX)
243 endif
244 ifeq ($(uname_S),GNU)
245 # GNU/Hurd
246 + HAVE_ALLOCA_H = YesPlease
247 NO_STRLCPY = YesPlease
248 NO_MKSTEMPS = YesPlease
249 HAVE_PATHS_H = YesPlease
@@ -316,6 +321,7 @@ endif
321 ifeq ($(uname_S),Windows)
322 GIT_VERSION := $(GIT_VERSION).MSVC
323 pathsep = ;
324 + HAVE_ALLOCA_H = YesPlease
325 NO_PREAD = YesPlease
326 NEEDS_CRYPTO_WITH_SSL = YesPlease
327 NO_LIBGEN_H = YesPlease
@@ -363,7 +369,7 @@ ifeq ($(uname_S),Windows)
369 COMPAT_OBJS = compat/msvc.o compat/winansi.o \
370 compat/win32/pthread.o compat/win32/syslog.o \
371 compat/win32/dirent.o
366 - COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
372 + COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -Icompat -Icompat/regex -Icompat/win32 -DSTRIP_EXTENSION=\".exe\"
373 BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib
374 EXTLIBS = user32.lib advapi32.lib shell32.lib wininet.lib ws2_32.lib
375 PTHREAD_LIBS =
configure.ac
+8
@@ -272,6 +272,14 @@ AS_HELP_STRING([], [ARG can be also prefix for libpcre library and hea
272 GIT_CONF_SUBST([LIBPCREDIR])
273 fi)
274 #
275 +# Define HAVE_ALLOCA_H if you have working alloca(3) defined in that header.
276 +AC_FUNC_ALLOCA
277 +case $ac_cv_working_alloca_h in
278 + yes) HAVE_ALLOCA_H=YesPlease;;
279 + *) HAVE_ALLOCA_H='';;
280 +esac
281 +GIT_CONF_SUBST([HAVE_ALLOCA_H])
282 +#
283 # Define NO_CURL if you do not have curl installed. git-http-pull and
284 # git-http-push are not built, and you cannot use http:// and https://
285 # transports.
git-compat-util.h
+8
@@ -526,6 +526,14 @@ extern void release_pack_memory(size_t);
526 typedef void (*try_to_free_t)(size_t);
527 extern try_to_free_t set_try_to_free_routine(try_to_free_t);
528
529 +#ifdef HAVE_ALLOCA_H
530 +# include <alloca.h>
531 +# define xalloca(size) (alloca(size))
532 +# define xalloca_free(p) do {} while (0)
533 +#else
534 +# define xalloca(size) (xmalloc(size))
535 +# define xalloca_free(p) (free(p))
536 +#endif
537 extern char *xstrdup(const char *str);
538 extern void *xmalloc(size_t size);
539 extern void *xmallocz(size_t size);