Ben Reser wrote on Fri, Jul 26, 2013 at 09:56:26 -0700:
> On Fri, Jul 26, 2013 at 3:00 AM, Ivan Zhakov <i...@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.
  *

Reply via email to