[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

[PATCH] svn_hash_gets multiply-evaluates KEY (was: Re: svn commit: r1507044 -)

From: Daniel Shahaf <danielsh_at_elego.de>
Date: Mon, 29 Jul 2013 20:41:20 +0300

Ben Reser wrote on Fri, Jul 26, 2013 at 09:56:26 -0700:
> On Fri, Jul 26, 2013 at 3:00 AM, Ivan Zhakov <ivan_at_visualsvn.com> wrote:
> > I really like idea go back to simple svn_hash_gets/svn_hash_sets()
> > implementation and remove these premature optimizations.
>
> I've left the improved svn_hash_sets() implementation in place. I'm
> not seeing any further harm from the current solution but if we find
> something else I'd support getting rid of it entirely.

There was some discussion on IRC today which resulted in the below.

[[[
Follow-up to r1507366: svn_hash_gets: compute the length of string literal
keys (common case) at compile-time, without multiply-evaluating dynamically-
computed keys.

* build/ac-macros/svn-macros.m4
  (SVN_CHECK_FOR_DUNDER_BUILTINS): New macro.

* configure.ac:
    Call SVN_CHECK_FOR_DUNDER_BUILTINS() and set -D SVN_HAS_DUNDER_BUILTINS.

* subversion/include/svn_hash.h
  (svn_hash_gets): Use __builtin_choose_expr() and __builtin_constant_p(),
    when available.
]]]

Index: build/ac-macros/svn-macros.m4
===================================================================
--- build/ac-macros/svn-macros.m4 (revision 1508134)
+++ build/ac-macros/svn-macros.m4 (working copy)
@@ -163,3 +163,17 @@ AC_DEFUN([SVN_CHECK_FOR_ATOMIC_BUILTINS],
       return 0;
   }], [svn_cv_atomic_builtins=yes], [svn_cv_atomic_builtins=no], [svn_cv_atomic_builtins=no])])
 ])
+
+AC_DEFUN([SVN_CHECK_FOR_DUNDER_BUILTINS],
+[
+ AC_CACHE_CHECK([whether the compiler provides dunder builtins], [svn_cv_dunder_builtins],
+ [
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+ int main(int argc)
+ {
+ return (!__builtin_choose_expr(__builtin_constant_p(argc), 1, 0)
+ && __builtin_choose_expr(__builtin_constant_p("foobar"), 1, 0))
+ ? 0 /* EXIT_SUCCESS */ : 1 /* EXIT_FAILURE */;
+ }]])], svn_cv_dunder_builtins="yes", svn_cv_dunder_builtins="no")
+ ])
+])
Index: configure.ac
===================================================================
--- configure.ac (revision 1508134)
+++ configure.ac (working copy)
@@ -167,11 +167,15 @@ if test -n "$sqlite_compat_ver" && test "$sqlite_c
 fi
 
 SVN_CHECK_FOR_ATOMIC_BUILTINS
-
 if test "$svn_cv_atomic_builtins" = "yes"; then
     AC_DEFINE(SVN_HAS_ATOMIC_BUILTINS, 1, [Define if compiler provides atomic builtins])
 fi
 
+SVN_CHECK_FOR_DUNDER_BUILTINS
+if test "$svn_cv_dunder_builtins" = "yes"; then
+ AC_DEFINE(SVN_HAS_DUNDER_BUILTINS, 1, [Define if compiler provides __builtin_constant_p and __builtin_choose_expr])
+fi
+
 dnl Set up a number of directories ---------------------
 
 dnl Create SVN_BINDIR for proper substitution
Index: subversion/include/svn_hash.h
===================================================================
--- subversion/include/svn_hash.h (revision 1508134)
+++ subversion/include/svn_hash.h (working copy)
@@ -244,8 +244,26 @@ svn_hash_from_cstring_keys(apr_hash_t **hash,
  *
  * @since New in 1.8.
  */
-#define svn_hash_gets(ht, key) \
+#if SVN_HAS_DUNDER_BUILTINS
+/* We have two use-cases:
+ 1. (common) KEY is a string literal.
+ 2. (rare) KEY is the result of an expensive function call.
+ For the former, we want to evaluate the string length at compile time. (We
+ use sizeof(), but strlen() would do.) For the latter, however, we want to
+ avoid having the macro multiply-evaluate KEY. So, if our compiler is smart
+ enough (that includes at least gcc and clang), we use __builtin_* to have
+ our cake and eat it too: */
+# define svn_hash_gets(ht, key) \
+ apr_hash_get(ht, key, \
+ __builtin_choose_expr(__builtin_constant_p(key), \
+ sizeof(key)-1, \
+ APR_HASH_KEY_STRING))
+#else
+/* ... and when our compiler is anything else, we take the hit and compute the
+ length of string literals at run-time. */
+# define svn_hash_gets(ht, key) \
             apr_hash_get(ht, key, APR_HASH_KEY_STRING)
+#endif
 
 /** Shortcut for apr_hash_set() with a const char * key.
  *
Received on 2013-07-29 19:41:59 CEST

This is an archived mail posted to the Subversion Dev mailing list.