From owner-svn-src-all@FreeBSD.ORG Sat Jan 17 18:57:12 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 998111065676; Sat, 17 Jan 2009 18:57:12 +0000 (UTC) (envelope-from das@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 876328FC17; Sat, 17 Jan 2009 18:57:12 +0000 (UTC) (envelope-from das@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n0HIvCGH050090; Sat, 17 Jan 2009 18:57:12 GMT (envelope-from das@svn.freebsd.org) Received: (from das@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n0HIvCfC050088; Sat, 17 Jan 2009 18:57:12 GMT (envelope-from das@svn.freebsd.org) Message-Id: <200901171857.n0HIvCfC050088@svn.freebsd.org> From: David Schultz Date: Sat, 17 Jan 2009 18:57:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r187369 - head/lib/libc/stdio X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 17 Jan 2009 18:57:13 -0000 Author: das Date: Sat Jan 17 18:57:12 2009 New Revision: 187369 URL: http://svn.freebsd.org/changeset/base/187369 Log: When f[w]printf() is called on an unbuffered file like stdout, it sets up a fake buffered FILE and then effectively calls itself recursively. Unfortunately, gcc doesn't know how to do tail call elimination in this case, and actually makes things worse by inlining __sbprintf(). This means that f[w]printf() to stderr was allocating about 5k of stack on 64-bit platforms, much of which was never used. I've reorganized things to eliminate the waste. In addition to saving some stack space, this improves performance in my tests by anywhere from 5% to 17% (depending on the test) when -fstack-protector is enabled. I found no statistically significant performance difference when stack protection is turned off. (The tests redirected stderr to /dev/null.) Modified: head/lib/libc/stdio/vfprintf.c head/lib/libc/stdio/vfwprintf.c Modified: head/lib/libc/stdio/vfprintf.c ============================================================================== --- head/lib/libc/stdio/vfprintf.c Sat Jan 17 17:40:44 2009 (r187368) +++ head/lib/libc/stdio/vfprintf.c Sat Jan 17 18:57:12 2009 (r187369) @@ -65,7 +65,8 @@ __FBSDID("$FreeBSD$"); #include "printflocal.h" static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0); +static int __sbprintf(FILE *, const char *, va_list) __printflike(2, 0) + __noinline; static char *__wcsconv(wchar_t *, int); #define CHAR char @@ -102,6 +103,10 @@ __sbprintf(FILE *fp, const char *fmt, va FILE fake; unsigned char buf[BUFSIZ]; + /* XXX This is probably not needed. */ + if (prepwrite(fp) != 0) + return (EOF); + /* copy the important variables */ fake._flags = fp->_flags & ~__SNBF; fake._file = fp->_file; @@ -193,7 +198,12 @@ vfprintf(FILE * __restrict fp, const cha int ret; FLOCKFILE(fp); - ret = __vfprintf(fp, fmt0, ap); + /* optimise fprintf(stderr) (and other unbuffered Unix files) */ + if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && + fp->_file >= 0) + ret = __sbprintf(fp, fmt0, ap); + else + ret = __vfprintf(fp, fmt0, ap); FUNLOCKFILE(fp); return (ret); } @@ -367,11 +377,6 @@ __vfprintf(FILE *fp, const char *fmt0, v if (prepwrite(fp) != 0) return (EOF); - /* optimise fprintf(stderr) (and other unbuffered Unix files) */ - if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && - fp->_file >= 0) - return (__sbprintf(fp, fmt0, ap)); - thousands_sep = '\0'; grouping = NULL; convbuf = NULL; Modified: head/lib/libc/stdio/vfwprintf.c ============================================================================== --- head/lib/libc/stdio/vfwprintf.c Sat Jan 17 17:40:44 2009 (r187368) +++ head/lib/libc/stdio/vfwprintf.c Sat Jan 17 18:57:12 2009 (r187369) @@ -67,7 +67,7 @@ __FBSDID("$FreeBSD$"); #include "printflocal.h" static int __sprint(FILE *, struct __suio *); -static int __sbprintf(FILE *, const wchar_t *, va_list); +static int __sbprintf(FILE *, const wchar_t *, va_list) __noinline; static wint_t __xfputwc(wchar_t, FILE *); static wchar_t *__mbsconv(char *, int); @@ -114,6 +114,10 @@ __sbprintf(FILE *fp, const wchar_t *fmt, FILE fake; unsigned char buf[BUFSIZ]; + /* XXX This is probably not needed. */ + if (prepwrite(fp) != 0) + return (EOF); + /* copy the important variables */ fake._flags = fp->_flags & ~__SNBF; fake._file = fp->_file; @@ -250,7 +254,12 @@ vfwprintf(FILE * __restrict fp, const wc int ret; FLOCKFILE(fp); - ret = __vfwprintf(fp, fmt0, ap); + /* optimise fprintf(stderr) (and other unbuffered Unix files) */ + if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && + fp->_file >= 0) + ret = __sbprintf(fp, fmt0, ap); + else + ret = __vfwprintf(fp, fmt0, ap); FUNLOCKFILE(fp); return (ret); } @@ -419,11 +428,6 @@ __vfwprintf(FILE *fp, const wchar_t *fmt if (prepwrite(fp) != 0) return (EOF); - /* optimise fprintf(stderr) (and other unbuffered Unix files) */ - if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && - fp->_file >= 0) - return (__sbprintf(fp, fmt0, ap)); - thousands_sep = '\0'; grouping = NULL; convbuf = NULL;