diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index e976201030..8076e8af24 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -219,6 +219,19 @@ err_gettext(const char *str) #endif } +#if defined(HAVE_PG_ATTRIBUTE_HOT_AND_COLD) && defined(HAVE__BUILTIN_CONSTANT_P) +/* + * errstart_cold + * A simple wrapper around errstart, but hinted to be cold so that the + * compiler is more likely to put error code in a cold area away from the + * main function body. + */ +bool +pg_attribute_cold errstart_cold(int elevel, const char *domain) +{ + return errstart(elevel, domain); +} +#endif /* * errstart --- begin an error-reporting cycle diff --git a/src/include/c.h b/src/include/c.h index d72b23afe4..087b8af6cb 100644 --- a/src/include/c.h +++ b/src/include/c.h @@ -178,6 +178,21 @@ #define pg_noinline #endif +/* + * Marking certain functions as "hot" or "cold" can be useful to assist the + * compiler in arranging the assembly code in a more efficient way. + * These are supported from GCC >= 4.3 and clang >= 3.2 + */ +#if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) || \ + (defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 2))) +#define HAVE_PG_ATTRIBUTE_HOT_AND_COLD 1 +#define pg_attribute_hot __attribute__((hot)) +#define pg_attribute_cold __attribute__((cold)) +#else +#define pg_attribute_hot +#define pg_attribute_cold +#endif + /* * Mark a point as unreachable in a portable fashion. This should preferably * be something that the compiler understands, to aid code generation. diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 1e09ee0541..97fb4d74d2 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -121,6 +121,18 @@ *---------- */ #ifdef HAVE__BUILTIN_CONSTANT_P +#ifdef HAVE_PG_ATTRIBUTE_HOT_AND_COLD +#define ereport_domain(elevel, domain, ...) \ + do { \ + pg_prevent_errno_in_scope(); \ + if (__builtin_constant_p(elevel) && (elevel) >= ERROR ? \ + errstart_cold(elevel, domain) : \ + errstart(elevel, domain)) \ + __VA_ARGS__, errfinish(__FILE__, __LINE__, PG_FUNCNAME_MACRO); \ + if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \ + pg_unreachable(); \ + } while(0) +#else /* !HAVE_PG_ATTRIBUTE_HOT_AND_COLD */ #define ereport_domain(elevel, domain, ...) \ do { \ pg_prevent_errno_in_scope(); \ @@ -129,6 +141,7 @@ if (__builtin_constant_p(elevel) && (elevel) >= ERROR) \ pg_unreachable(); \ } while(0) +#endif /* HAVE_PG_ATTRIBUTE_HOT_AND_COLD */ #else /* !HAVE__BUILTIN_CONSTANT_P */ #define ereport_domain(elevel, domain, ...) \ do { \ @@ -146,6 +159,9 @@ #define TEXTDOMAIN NULL +#ifdef HAVE_PG_ATTRIBUTE_HOT_AND_COLD +extern bool pg_attribute_cold errstart_cold(int elevel, const char *domain); +#endif extern bool errstart(int elevel, const char *domain); extern void errfinish(const char *filename, int lineno, const char *funcname);