Bug 1125185 - Define MOZ_COLD for marking "cold" functions r=waldo
authorDan Gohman <sunfish@mozilla.com>
Mon, 26 Jan 2015 17:30:19 -0800
changeset 239224 780d7bb5eb822d16e34233005dd71fce07a0586c
parent 239223 17934cf98597980544700323ce132830cfcb03b2
child 239225 4761861c990084c7e986ac0df7828884cbae6b53
child 239271 ead7aa880dbe3c021242b5cd1333945e5937c501
push id489
push usermcmanus@ducksong.com
push dateTue, 27 Jan 2015 01:44:53 +0000
reviewerswaldo
bugs1125185
milestone38.0a1
Bug 1125185 - Define MOZ_COLD for marking "cold" functions r=waldo
js/public/Utility.h
js/src/ds/LifoAlloc.h
js/src/gc/StoreBuffer.h
js/src/jsinfer.h
js/src/jsutil.cpp
js/src/jsutil.h
js/src/vm/Runtime.h
mfbt/Assertions.h
mfbt/Attributes.h
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -48,17 +48,17 @@ namespace js {}
 #define JS_ALLOCATED_TENURED_PATTERN 0x4D
 #define JS_EMPTY_STOREBUFFER_PATTERN 0x1B
 #define JS_SWEPT_CODE_PATTERN 0x3B
 #define JS_SWEPT_FRAME_PATTERN 0x5B
 
 #define JS_STATIC_ASSERT(cond)           static_assert(cond, "JS_STATIC_ASSERT")
 #define JS_STATIC_ASSERT_IF(cond, expr)  MOZ_STATIC_ASSERT_IF(cond, expr, "JS_STATIC_ASSERT_IF")
 
-extern MOZ_NORETURN JS_PUBLIC_API(void)
+extern MOZ_NORETURN MOZ_COLD JS_PUBLIC_API(void)
 JS_Assert(const char *s, const char *file, int ln);
 
 /*
  * Custom allocator support for SpiderMonkey
  */
 #if defined JS_USE_CUSTOM_ALLOCATOR
 # include "jscustomallocator.h"
 #else
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -143,19 +143,16 @@ class BumpChunk
     }
 
     static BumpChunk *new_(size_t chunkSize);
     static void delete_(BumpChunk *chunk);
 };
 
 } // namespace detail
 
-MOZ_NORETURN void
-CrashAtUnhandlableOOM(const char *reason);
-
 // LIFO bump allocator: used for phase-oriented and fast LIFO allocations.
 //
 // Note: |latest| is not necessary "last". We leave BumpChunks latent in the
 // chain after they've been released to avoid thrashing before a GC.
 class LifoAlloc
 {
     typedef detail::BumpChunk BumpChunk;
 
--- a/js/src/gc/StoreBuffer.h
+++ b/js/src/gc/StoreBuffer.h
@@ -14,20 +14,16 @@
 #include "jsalloc.h"
 
 #include "ds/LifoAlloc.h"
 #include "gc/Nursery.h"
 #include "gc/Tracer.h"
 #include "js/MemoryMetrics.h"
 
 namespace js {
-
-MOZ_NORETURN void
-CrashAtUnhandlableOOM(const char *reason);
-
 namespace gc {
 
 /*
  * BufferableRef represents an abstract reference for use in the generational
  * GC's remembered set. Entries in the store buffer that cannot be represented
  * with the simple pointer-to-a-pointer scheme must derive from this class and
  * use the generic store buffer interface.
  */
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -1768,17 +1768,17 @@ inline const char * InferSpewColor(TypeC
 inline const char * InferSpewColor(TypeSet *types) { return nullptr; }
 inline void InferSpew(SpewChannel which, const char *fmt, ...) {}
 inline const char * TypeString(Type type) { return nullptr; }
 inline const char * TypeObjectString(TypeObject *type) { return nullptr; }
 
 #endif
 
 /* Print a warning, dump state and abort the program. */
-MOZ_NORETURN void TypeFailure(JSContext *cx, const char *fmt, ...);
+MOZ_NORETURN MOZ_COLD void TypeFailure(JSContext *cx, const char *fmt, ...);
 
 } /* namespace types */
 } /* namespace js */
 
 // JS::ubi::Nodes can point to js::LazyScripts; they're js::gc::Cell instances
 // with no associated compartment.
 namespace JS {
 namespace ubi {
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -45,17 +45,17 @@ JS_Assert(const char *s, const char *fil
 #include <malloc.h>
 #include <stdlib.h>
 
 namespace js {
 
 // This function calls all the vanilla heap allocation functions.  It is never
 // called, and exists purely to help config/check_vanilla_allocations.py.  See
 // that script for more details.
-extern void
+extern MOZ_COLD void
 AllTheNonBasicVanillaNewAllocations()
 {
     // posix_memalign and aligned_alloc aren't available on all Linux
     // configurations.
     // valloc was deprecated in Android 5.0
     //char *q;
     //posix_memalign((void**)&q, 16, 16);
 
--- a/js/src/jsutil.h
+++ b/js/src/jsutil.h
@@ -38,16 +38,19 @@ js_memcpy(void *dst_, const void *src_, 
     MOZ_ASSERT_IF(dst >= src, (size_t) (dst - src) >= len);
     MOZ_ASSERT_IF(src >= dst, (size_t) (src - dst) >= len);
 
     return memcpy(dst, src, len);
 }
 
 namespace js {
 
+MOZ_NORETURN MOZ_COLD void
+CrashAtUnhandlableOOM(const char *reason);
+
 template <class T>
 struct AlignmentTestStruct
 {
     char c;
     T t;
 };
 
 /* This macro determines the alignment requirements of a type. */
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -58,23 +58,23 @@ class TraceLoggerThread;
 
 /* Thread Local Storage slot for storing the runtime for a thread. */
 extern mozilla::ThreadLocal<PerThreadData*> TlsPerThreadData;
 
 } // namespace js
 
 struct DtoaState;
 
-extern void
+extern MOZ_COLD void
 js_ReportOutOfMemory(js::ExclusiveContext *cx);
 
-extern void
+extern MOZ_COLD void
 js_ReportAllocationOverflow(js::ExclusiveContext *maybecx);
 
-extern void
+extern MOZ_COLD void
 js_ReportOverRecursed(js::ExclusiveContext *cx);
 
 namespace js {
 
 class Activation;
 class ActivationIterator;
 class AsmJSActivation;
 class AsmJSModule;
--- a/mfbt/Assertions.h
+++ b/mfbt/Assertions.h
@@ -126,34 +126,34 @@ extern "C" {
 /*
  * Prints |aStr| as an assertion failure (using aFilename and aLine as the
  * location of the assertion) to the standard debug-output channel.
  *
  * Usually you should use MOZ_ASSERT or MOZ_CRASH instead of this method.  This
  * method is primarily for internal use in this header, and only secondarily
  * for use in implementing release-build assertions.
  */
-static MOZ_ALWAYS_INLINE void
+static MOZ_COLD MOZ_ALWAYS_INLINE void
 MOZ_ReportAssertionFailure(const char* aStr, const char* aFilename, int aLine)
   MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
 {
 #ifdef ANDROID
   __android_log_print(ANDROID_LOG_FATAL, "MOZ_Assert",
                       "Assertion failure: %s, at %s:%d\n",
                       aStr, aFilename, aLine);
 #else
   fprintf(stderr, "Assertion failure: %s, at %s:%d\n", aStr, aFilename, aLine);
 #ifdef MOZ_DUMP_ASSERTION_STACK
   nsTraceRefcnt::WalkTheStack(stderr);
 #endif
   fflush(stderr);
 #endif
 }
 
-static MOZ_ALWAYS_INLINE void
+static MOZ_COLD MOZ_ALWAYS_INLINE void
 MOZ_ReportCrash(const char* aStr, const char* aFilename, int aLine)
   MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS
 {
 #ifdef ANDROID
   __android_log_print(ANDROID_LOG_FATAL, "MOZ_CRASH",
                       "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
 #else
   fprintf(stderr, "Hit MOZ_CRASH(%s) at %s:%d\n", aStr, aFilename, aLine);
--- a/mfbt/Attributes.h
+++ b/mfbt/Attributes.h
@@ -186,16 +186,37 @@
  * This modifier does not affect the corresponding function's linking behavior.
  */
 #if defined(MOZ_HAVE_NORETURN)
 #  define MOZ_NORETURN          MOZ_HAVE_NORETURN
 #else
 #  define MOZ_NORETURN          /* no support */
 #endif
 
+/**
+ * MOZ_COLD tells the compiler that a function is "cold", meaning infrequently
+ * executed. This may lead it to optimize for size more aggressively than speed,
+ * or to allocate the body of the function in a distant part of the text segment
+ * to help keep it from taking up unnecessary icache when it isn't in use.
+ *
+ * Place this attribute at the very beginning of a function definition. For
+ * example, write
+ *
+ *   MOZ_COLD int foo();
+ *
+ * or
+ *
+ *   MOZ_COLD int foo() { return 42; }
+ */
+#if defined(__GNUC__) || defined(__clang__)
+#  define MOZ_COLD __attribute__ ((cold))
+#else
+#  define MOZ_COLD
+#endif
+
 /*
  * MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS, specified at the end of a function
  * declaration, indicates that for the purposes of static analysis, this
  * function does not return.  (The function definition does not need to be
  * annotated.)
  *
  * MOZ_ReportCrash(const char* s, const char* file, int ln)
  *   MOZ_PRETEND_NORETURN_FOR_STATIC_ANALYSIS