Bug 891177 - Remove Vector.h's js/TemplateLib.h dependency by introducing mfbt/TemplateLib.h with the necessary bits. r=terrence
authorJeff Walden <jwalden@mit.edu>
Mon, 08 Jul 2013 12:42:13 -0700
changeset 151275 8abf922fb3ea4bb8af617666c64d165b9154eedd
parent 151274 ab78d649fde6dd65dfe23aa85cb95788ae261bbf
child 151276 7e972bc6d0f40d8546ed91ef22932682bcaa75dd
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs891177
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 891177 - Remove Vector.h's js/TemplateLib.h dependency by introducing mfbt/TemplateLib.h with the necessary bits. r=terrence
js/public/HashTable.h
js/public/RootingAPI.h
js/public/TemplateLib.h
js/public/Utility.h
js/public/Vector.h
js/src/ds/BitArray.h
js/src/ds/LifoAlloc.cpp
js/src/ds/LifoAlloc.h
js/src/gc/Marking.h
js/src/jsapi-tests/testIntTypesABI.cpp
js/src/jsgcinlines.h
js/src/jsobj.cpp
js/src/moz.build
js/src/vm/ObjectImpl-inl.h
js/src/vm/RegExpObject.h
js/src/vm/Runtime.h
js/src/vm/Shape.h
js/src/yarr/wtfbridge.h
mfbt/TemplateLib.h
mfbt/exported_headers.mk
--- a/js/public/HashTable.h
+++ b/js/public/HashTable.h
@@ -10,20 +10,20 @@
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Casting.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/ReentrancyGuard.h"
+#include "mozilla/TemplateLib.h"
 #include "mozilla/TypeTraits.h"
 #include "mozilla/Util.h"
 
-#include "js/TemplateLib.h"
 #include "js/Utility.h"
 
 namespace js {
 
 class TempAllocPolicy;
 template <class> struct DefaultHasher;
 template <class, class> class HashMapEntry;
 namespace detail {
@@ -535,17 +535,17 @@ struct DefaultHasher
         // Use builtin or overloaded operator==.
         return k == l;
     }
 };
 
 // Specialize hashing policy for pointer types. It assumes that the type is
 // at least word-aligned. For types with smaller size use PointerHasher.
 template <class T>
-struct DefaultHasher<T *> : PointerHasher<T *, tl::FloorLog2<sizeof(void *)>::result>
+struct DefaultHasher<T *> : PointerHasher<T *, mozilla::tl::FloorLog2<sizeof(void *)>::value>
 {};
 
 // For doubles, we can xor the two uint32s.
 template <>
 struct DefaultHasher<double>
 {
     typedef double Lookup;
     static HashNumber hash(double d) {
@@ -885,17 +885,17 @@ class HashTable : private AllocPolicy
     mozilla::DebugOnly<uint64_t>     mutationCount;
 
     // The default initial capacity is 32 (enough to hold 16 elements), but it
     // can be as low as 4.
     static const unsigned sMinCapacityLog2 = 2;
     static const unsigned sMinCapacity  = 1 << sMinCapacityLog2;
     static const unsigned sMaxInit      = JS_BIT(23);
     static const unsigned sMaxCapacity  = JS_BIT(24);
-    static const unsigned sHashBits     = tl::BitSize<HashNumber>::result;
+    static const unsigned sHashBits     = mozilla::tl::BitSize<HashNumber>::value;
     static const uint8_t  sMinAlphaFrac = 64;  // (0x100 * .25)
     static const uint8_t  sMaxAlphaFrac = 192; // (0x100 * .75)
     static const uint8_t  sInvMaxAlpha  = 171; // (ceil(0x100 / .75) >> 1)
     static const HashNumber sFreeKey = Entry::sFreeKey;
     static const HashNumber sRemovedKey = Entry::sRemovedKey;
     static const HashNumber sCollisionBit = Entry::sCollisionBit;
 
     static void staticAsserts()
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -6,17 +6,16 @@
 
 #ifndef js_RootingAPI_h
 #define js_RootingAPI_h
 
 #include "mozilla/GuardObjects.h"
 #include "mozilla/TypeTraits.h"
 
 #include "js/Utility.h"
-#include "js/TemplateLib.h"
 
 #include "jspubtd.h"
 
 /*
  * Moving GC Stack Rooting
  *
  * A moving GC may change the physical location of GC allocated things, even
  * when they are rooted, updating all pointers to the thing to refer to its new
deleted file mode 100644
--- a/js/public/TemplateLib.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * vim: set ts=8 sts=4 et sw=4 tw=99:
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef js_TemplateLib_h
-#define js_TemplateLib_h
-
-#include "jstypes.h"
-
-/*
- * Library of reusable template meta-functions (that is, functions on types and
- * compile-time values). Meta-functions are placed inside the 'tl' namespace to
- * avoid conflict with non-meta functions that logically have the same name
- * (e.g., js::tl::Min vs. js::Min).
- */
-
-namespace js {
-namespace tl {
-
-/* Compute min/max/clamp. */
-template <size_t i, size_t j> struct Min {
-    static const size_t result = i < j ? i : j;
-};
-template <size_t i, size_t j> struct Max {
-    static const size_t result = i > j ? i : j;
-};
-template <size_t i, size_t min, size_t max> struct Clamp {
-    static const size_t result = i < min ? min : (i > max ? max : i);
-};
-
-/* Compute x^y. */
-template <size_t x, size_t y> struct Pow {
-    static const size_t result = x * Pow<x, y - 1>::result;
-};
-template <size_t x> struct Pow<x,0> {
-    static const size_t result = 1;
-};
-
-/* Compute floor(log2(i)). */
-template <size_t i> struct FloorLog2 {
-    static const size_t result = 1 + FloorLog2<i / 2>::result;
-};
-template <> struct FloorLog2<0> { /* Error */ };
-template <> struct FloorLog2<1> { static const size_t result = 0; };
-
-/* Compute ceiling(log2(i)). */
-template <size_t i> struct CeilingLog2 {
-    static const size_t result = FloorLog2<2 * i - 1>::result;
-};
-
-/* Round up to the nearest power of 2. */
-template <size_t i> struct RoundUpPow2 {
-    static const size_t result = size_t(1) << CeilingLog2<i>::result;
-};
-template <> struct RoundUpPow2<0> {
-    static const size_t result = 1;
-};
-
-/* Compute the number of bits in the given unsigned type. */
-template <class T> struct BitSize {
-    static const size_t result = sizeof(T) * JS_BITS_PER_BYTE;
-};
-
-/*
- * Produce an N-bit mask, where N <= BitSize<size_t>::result.  Handle the
- * language-undefined edge case when N = BitSize<size_t>::result.
- */
-template <size_t N> struct NBitMask {
-    // Assert the precondition.  On success this evaluates to 0.  Otherwise it
-    // triggers divide-by-zero at compile time: a guaranteed compile error in
-    // C++11, and usually one in C++98.  Add this value to |result| to assure
-    // its computation.
-    static const size_t checkPrecondition = 0 / size_t(N < BitSize<size_t>::result);
-    static const size_t result = (size_t(1) << N) - 1 + checkPrecondition;
-};
-template <> struct NBitMask<BitSize<size_t>::result> {
-    static const size_t result = size_t(-1);
-};
-
-/*
- * For the unsigned integral type size_t, compute a mask M for N such that
- * for all X, !(X & M) implies X * N will not overflow (w.r.t size_t)
- */
-template <size_t N> struct MulOverflowMask {
-    static const size_t result =
-        ~NBitMask<BitSize<size_t>::result - CeilingLog2<N>::result>::result;
-};
-template <> struct MulOverflowMask<0> { /* Error */ };
-template <> struct MulOverflowMask<1> { static const size_t result = 0; };
-
-/*
- * Generate a mask for T such that if (X & sUnsafeRangeSizeMask), an X-sized
- * array of T's is big enough to cause a ptrdiff_t overflow when subtracting
- * a pointer to the end of the array from the beginning.
- */
-template <class T> struct UnsafeRangeSizeMask {
-    /*
-     * The '2' factor means the top bit is clear, sizeof(T) converts from
-     * units of elements to bytes.
-     */
-    static const size_t result = MulOverflowMask<2 * sizeof(T)>::result;
-};
-
-template <bool cond, typename T, T v1, T v2> struct If        { static const T result = v1; };
-template <typename T, T v1, T v2> struct If<false, T, v1, v2> { static const T result = v2; };
-
-} /* namespace tl */
-} /* namespace js */
-
-#endif  /* js_TemplateLib_h */
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -7,29 +7,28 @@
 #ifndef js_Utility_h
 #define js_Utility_h
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Compiler.h"
 #include "mozilla/Move.h"
 #include "mozilla/Scoped.h"
+#include "mozilla/TemplateLib.h"
 
 #include <stdlib.h>
 #include <string.h>
 
 #ifdef JS_OOM_DO_BACKTRACES
 #include <stdio.h>
 #include <execinfo.h>
 #endif
 
 #include "jstypes.h"
 
-#include "js/TemplateLib.h"
-
 /* The public JS engine namespace. */
 namespace JS {}
 
 /* The mozilla-shared reusable template/utility namespace. */
 namespace mozilla {}
 
 /* The private JS engine namespace. */
 namespace js {}
@@ -349,26 +348,26 @@ js_pod_calloc()
 {
     return (T *)js_calloc(sizeof(T));
 }
 
 template <class T>
 static JS_ALWAYS_INLINE T *
 js_pod_malloc(size_t numElems)
 {
-    if (numElems & js::tl::MulOverflowMask<sizeof(T)>::result)
+    if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
         return NULL;
     return (T *)js_malloc(numElems * sizeof(T));
 }
 
 template <class T>
 static JS_ALWAYS_INLINE T *
 js_pod_calloc(size_t numElems)
 {
-    if (numElems & js::tl::MulOverflowMask<sizeof(T)>::result)
+    if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
         return NULL;
     return (T *)js_calloc(numElems * sizeof(T));
 }
 
 namespace js {
 
 template<typename T>
 struct ScopedFreePtrTraits
--- a/js/public/Vector.h
+++ b/js/public/Vector.h
@@ -8,19 +8,19 @@
 #define js_Vector_h
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Move.h"
 #include "mozilla/ReentrancyGuard.h"
+#include "mozilla/TemplateLib.h"
 #include "mozilla/TypeTraits.h"
-
-#include "js/TemplateLib.h"
+#include "mozilla/Util.h"
 
 /* Silence dire "bugs in previous versions of MSVC have been fixed" warnings */
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4345)
 #endif
 
 namespace js {
@@ -222,29 +222,29 @@ class Vector : private AllocPolicy
      * of the element type is not visible here.
      *
      * Explicit specialization is only allowed at namespace scope, so
      * in order to keep everything here, we use a dummy template
      * parameter with partial specialization.
      */
     template <int M, int Dummy>
     struct ElemSize {
-        static const size_t result = sizeof(T);
+        static const size_t value = sizeof(T);
     };
     template <int Dummy>
     struct ElemSize<0, Dummy> {
-        static const size_t result = 1;
+        static const size_t value = 1;
     };
 
     static const size_t sInlineCapacity =
-        tl::Min<N, sMaxInlineBytes / ElemSize<N, 0>::result>::result;
+        mozilla::tl::Min<N, sMaxInlineBytes / ElemSize<N, 0>::value>::value;
 
     /* Calculate inline buffer size; avoid 0-sized array. */
     static const size_t sInlineBytes =
-        tl::Max<1, sInlineCapacity * ElemSize<N, 0>::result>::result;
+        mozilla::tl::Max<1, sInlineCapacity * ElemSize<N, 0>::value>::value;
 
     /* member data */
 
     /*
      * Pointer to the buffer, be it inline or heap-allocated. Only [mBegin,
      * mBegin + mLength) hold valid constructed T objects. The range [mBegin +
      * mLength, mBegin + mCapacity) holds uninitialized memory. The range
      * [mBegin + mLength, mBegin + mReserved) also holds uninitialized memory
@@ -643,17 +643,17 @@ Vector<T,N,AP>::growStorageBy(size_t inc
      * result in a non-2^N request size.
      */
 
     size_t newCap;
 
     if (incr == 1) {
         if (usingInlineStorage()) {
             /* This case occurs in ~70--80% of the calls to this function. */
-            size_t newSize = tl::RoundUpPow2<(sInlineCapacity + 1) * sizeof(T)>::result;
+            size_t newSize = mozilla::tl::RoundUpPow2<(sInlineCapacity + 1) * sizeof(T)>::value;
             newCap = newSize / sizeof(T);
             goto convert;
         }
 
         if (mLength == 0) {
             /* This case occurs in ~0--10% of the calls to this function. */
             newCap = 1;
             goto grow;
@@ -662,17 +662,17 @@ Vector<T,N,AP>::growStorageBy(size_t inc
         /* This case occurs in ~15--20% of the calls to this function. */
 
         /*
          * Will mLength*4*sizeof(T) overflow?  This condition limits a Vector
          * to 1GB of memory on a 32-bit system, which is a reasonable limit.
          * It also ensures that the ((char *)end() - (char *)begin()) does not
          * overflow ptrdiff_t (see Bug 510319).
          */
-        if (mLength & tl::MulOverflowMask<4 * sizeof(T)>::result) {
+        if (mLength & mozilla::tl::MulOverflowMask<4 * sizeof(T)>::value) {
             this->reportAllocOverflow();
             return false;
         }
 
         /*
          * If we reach here, the existing capacity will have a size that is
          * already as close to 2^N as sizeof(T) will allow.  Just double the
          * capacity, and then there might be space for one more element.
@@ -682,17 +682,17 @@ Vector<T,N,AP>::growStorageBy(size_t inc
             newCap += 1;
 
     } else {
         /* This case occurs in ~2% of the calls to this function. */
         size_t newMinCap = mLength + incr;
 
         /* Did mLength+incr overflow?  Will newCap*sizeof(T) overflow? */
         if (newMinCap < mLength ||
-            newMinCap & tl::MulOverflowMask<2 * sizeof(T)>::result)
+            newMinCap & mozilla::tl::MulOverflowMask<2 * sizeof(T)>::value)
         {
             this->reportAllocOverflow();
             return false;
         }
 
         size_t newMinSize = newMinCap * sizeof(T);
         size_t newSize = mozilla::RoundUpPow2(newMinSize);
         newCap = newSize / sizeof(T);
--- a/js/src/ds/BitArray.h
+++ b/js/src/ds/BitArray.h
@@ -2,19 +2,19 @@
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef ds_BitArray_h
 #define ds_BitArray_h
 
-#include "jstypes.h" 
+#include "mozilla/TemplateLib.h"
 
-#include "js/TemplateLib.h" 
+#include "jstypes.h"
 
 namespace js {
 
 template <size_t nbits>
 class BitArray {
   private:
     static const size_t numSlots =
         nbits / JS_BITS_PER_WORD + (nbits % JS_BITS_PER_WORD == 0 ? 0 : 1);
@@ -49,16 +49,16 @@ class BitArray {
                 return false;
         }
         return true;
     }
 
   private:
     inline void getMarkWordAndMask(size_t offset,
                                    uintptr_t *indexp, uintptr_t *maskp) const {
-        *indexp = offset >> tl::FloorLog2<JS_BITS_PER_WORD>::result;
+        *indexp = offset >> mozilla::tl::FloorLog2<JS_BITS_PER_WORD>::value;
         *maskp = uintptr_t(1) << (offset & (JS_BITS_PER_WORD - 1));
     }
 };
 
 } /* namespace js */
 
 #endif /* ds_BitArray_h */
--- a/js/src/ds/LifoAlloc.cpp
+++ b/js/src/ds/LifoAlloc.cpp
@@ -6,16 +6,17 @@
 
 #include "ds/LifoAlloc.h"
 
 #include "mozilla/MathAlgorithms.h"
 
 using namespace js;
 
 using mozilla::RoundUpPow2;
+using mozilla::tl::BitSize;
 
 namespace js {
 namespace detail {
 
 BumpChunk *
 BumpChunk::new_(size_t chunkSize)
 {
     JS_ASSERT(RoundUpPow2(chunkSize) == chunkSize);
@@ -86,17 +87,17 @@ LifoAlloc::getOrCreateChunk(size_t n)
 
     size_t defaultChunkFreeSpace = defaultChunkSize_ - sizeof(BumpChunk);
     size_t chunkSize;
     if (n > defaultChunkFreeSpace) {
         size_t allocSizeWithHeader = n + sizeof(BumpChunk);
 
         // Guard for overflow.
         if (allocSizeWithHeader < n ||
-            (allocSizeWithHeader & (size_t(1) << (tl::BitSize<size_t>::result - 1)))) {
+            (allocSizeWithHeader & (size_t(1) << (BitSize<size_t>::value - 1)))) {
             return NULL;
         }
 
         chunkSize = RoundUpPow2(allocSizeWithHeader);
     } else {
         chunkSize = defaultChunkSize_;
     }
 
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -7,16 +7,17 @@
 #ifndef ds_LifoAlloc_h
 #define ds_LifoAlloc_h
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/MemoryChecking.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
+#include "mozilla/TemplateLib.h"
 #include "mozilla/TypeTraits.h"
 
 // This data structure supports stacky LIFO allocation (mark/release and
 // LifoAllocScope). It does not maintain one contiguous segment; instead, it
 // maintains a bunch of linked memory segments. In order to prevent malloc/free
 // thrashing, unused segments are deallocated when garbage collection occurs.
 
 #include "jsutil.h"
@@ -26,18 +27,18 @@ namespace js {
 namespace detail {
 
 static const size_t LIFO_ALLOC_ALIGN = 8;
 
 JS_ALWAYS_INLINE
 char *
 AlignPtr(void *orig)
 {
-    MOZ_STATIC_ASSERT(tl::FloorLog2<LIFO_ALLOC_ALIGN>::result ==
-                      tl::CeilingLog2<LIFO_ALLOC_ALIGN>::result,
+    MOZ_STATIC_ASSERT(mozilla::tl::FloorLog2<LIFO_ALLOC_ALIGN>::value ==
+                      mozilla::tl::CeilingLog2<LIFO_ALLOC_ALIGN>::value,
                       "LIFO_ALLOC_ALIGN must be a power of two");
 
     char *result = (char *) ((uintptr_t(orig) + (LIFO_ALLOC_ALIGN - 1)) & (~LIFO_ALLOC_ALIGN + 1));
     JS_ASSERT(uintptr_t(result) % LIFO_ALLOC_ALIGN == 0);
     return result;
 }
 
 // Header for a chunk of memory wrangled by the LifoAlloc.
--- a/js/src/gc/Marking.h
+++ b/js/src/gc/Marking.h
@@ -7,17 +7,16 @@
 #ifndef gc_Marking_h
 #define gc_Marking_h
 
 #include "jsgc.h"
 #include "jslock.h"
 
 #include "gc/Barrier.h"
 #include "gc/Nursery.h"
-#include "js/TemplateLib.h"
 #include "ion/IonCode.h"
 
 extern "C" {
 struct JSContext;
 class JSFunction;
 class JSObject;
 class JSScript;
 }
--- a/js/src/jsapi-tests/testIntTypesABI.cpp
+++ b/js/src/jsapi-tests/testIntTypesABI.cpp
@@ -21,17 +21,16 @@
 #include "js/CallArgs.h"
 #include "js/CharacterEncoding.h"
 #include "js/Date.h"
 #include "js/GCAPI.h"
 #include "js/HashTable.h"
 #include "js/HeapAPI.h"
 #include "js/MemoryMetrics.h"
 #include "js/PropertyKey.h"
-#include "js/TemplateLib.h"
 #include "js/Utility.h"
 #include "js/Value.h"
 #include "js/Vector.h"
 
 /*
  * Verify that our public (and intended to be public, versus being that way
  * because we haven't made them private yet) headers don't define
  * {u,}int{8,16,32,64} or JS{Ui,I}nt{8,16,32,64} types.  If any do, they will
--- a/js/src/jsgcinlines.h
+++ b/js/src/jsgcinlines.h
@@ -8,17 +8,16 @@
 #define jsgcinlines_h
 
 #include "jsgc.h"
 #include "jscntxt.h"
 #include "jscompartment.h"
 #include "jslock.h"
 
 #include "js/RootingAPI.h"
-#include "js/TemplateLib.h"
 #include "vm/Shape.h"
 #include "vm/ForkJoin.h"
 
 namespace js {
 
 class Shape;
 
 /*
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -8,16 +8,17 @@
  * JS object implementation.
  */
 #include "jsobjinlines.h"
 
 #include <string.h>
 
 #include "mozilla/MathAlgorithms.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/TemplateLib.h"
 #include "mozilla/Util.h"
 
 #include "jstypes.h"
 #include "jsutil.h"
 #include "jsprf.h"
 #include "jsapi.h"
 #include "jsarray.h"
 #include "jsatom.h"
@@ -2065,17 +2066,17 @@ JSObject::TradeGuts(JSContext *cx, JSObj
     /* Trade the guts of the objects. */
     const size_t size = a->tenuredSizeOfThis();
     if (size == b->tenuredSizeOfThis()) {
         /*
          * If the objects are the same size, then we make no assumptions about
          * whether they have dynamically allocated slots and instead just copy
          * them over wholesale.
          */
-        char tmp[tl::Max<sizeof(JSFunction), sizeof(JSObject_Slots16)>::result];
+        char tmp[mozilla::tl::Max<sizeof(JSFunction), sizeof(JSObject_Slots16)>::value];
         JS_ASSERT(size <= sizeof(tmp));
 
         js_memcpy(tmp, a, size);
         js_memcpy(a, b, size);
         js_memcpy(b, tmp, size);
 
 #ifdef JSGC_GENERATIONAL
         /*
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -68,17 +68,16 @@ EXPORTS.js += [
     '../public/GCAPI.h',
     '../public/HashTable.h',
     '../public/HeapAPI.h',
     '../public/LegacyIntTypes.h',
     '../public/MemoryMetrics.h',
     '../public/PropertyKey.h',
     '../public/RequiredDefines.h',
     '../public/RootingAPI.h',
-    '../public/TemplateLib.h',
     '../public/Utility.h',
     '../public/Value.h',
     '../public/Vector.h',
 ]
 
 CPP_SOURCES += [
     'ArgumentsObject.cpp',
     'BytecodeCompiler.cpp',
--- a/js/src/vm/ObjectImpl-inl.h
+++ b/js/src/vm/ObjectImpl-inl.h
@@ -10,17 +10,16 @@
 #include "mozilla/Assertions.h"
 
 #include "jscompartment.h"
 #include "jsgc.h"
 #include "jsproxy.h"
 
 #include "gc/Heap.h"
 #include "gc/Marking.h"
-#include "js/TemplateLib.h"
 #include "vm/ObjectImpl.h"
 
 #include "gc/Barrier-inl.h"
 #include "vm/Interpreter.h"
 #include "vm/ObjectImpl.h"
 #include "vm/ProxyObject.h"
 
 inline JSCompartment *
--- a/js/src/vm/RegExpObject.h
+++ b/js/src/vm/RegExpObject.h
@@ -12,17 +12,16 @@
 
 #include <stddef.h>
 #include "jscntxt.h"
 #include "jsobj.h"
 #include "jsproxy.h"
 
 #include "gc/Barrier.h"
 #include "gc/Marking.h"
-#include "js/TemplateLib.h"
 #include "vm/MatchPairs.h"
 #include "vm/Runtime.h"
 #include "yarr/MatchResult.h"
 #include "yarr/Yarr.h"
 #if ENABLE_YARR_JIT
 #include "yarr/YarrJIT.h"
 #endif
 #include "yarr/YarrSyntaxChecker.h"
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef vm_Runtime_h
 #define vm_Runtime_h
 
 #include "mozilla/LinkedList.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
+#include "mozilla/TemplateLib.h"
 
 #include <string.h>
 #include <setjmp.h>
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "jsprvtd.h"
 #include "jsatom.h"
@@ -607,27 +608,27 @@ struct MallocProvider
 
     template <class T>
     T *pod_calloc() {
         return (T *)calloc_(sizeof(T));
     }
 
     template <class T>
     T *pod_malloc(size_t numElems) {
-        if (numElems & js::tl::MulOverflowMask<sizeof(T)>::result) {
+        if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
             Client *client = static_cast<Client *>(this);
             client->reportAllocationOverflow();
             return NULL;
         }
         return (T *)malloc_(numElems * sizeof(T));
     }
 
     template <class T>
     T *pod_calloc(size_t numElems, JSCompartment *comp = NULL, JSContext *cx = NULL) {
-        if (numElems & js::tl::MulOverflowMask<sizeof(T)>::result) {
+        if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
             Client *client = static_cast<Client *>(this);
             client->reportAllocationOverflow();
             return NULL;
         }
         return (T *)calloc_(numElems * sizeof(T));
     }
 
     JS_DECLARE_NEW_METHODS(new_, malloc_, JS_ALWAYS_INLINE)
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef vm_Shape_h
 #define vm_Shape_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/GuardObjects.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/TemplateLib.h"
 
 #include "jspropertytree.h"
 #include "jstypes.h"
 
 #include "gc/Heap.h"
 #include "js/HashTable.h"
 #include "js/RootingAPI.h"
 #include "vm/ObjectImpl.h"
@@ -103,17 +104,17 @@ class StaticBlockObject;
 static const uint32_t SHAPE_INVALID_SLOT = JS_BIT(24) - 1;
 static const uint32_t SHAPE_MAXIMUM_SLOT = JS_BIT(24) - 2;
 
 /*
  * Shapes use multiplicative hashing, but specialized to
  * minimize footprint.
  */
 struct ShapeTable {
-    static const uint32_t HASH_BITS     = tl::BitSize<HashNumber>::result;
+    static const uint32_t HASH_BITS     = mozilla::tl::BitSize<HashNumber>::value;
     static const uint32_t MIN_ENTRIES   = 7;
     static const uint32_t MIN_SIZE_LOG2 = 4;
     static const uint32_t MIN_SIZE      = JS_BIT(MIN_SIZE_LOG2);
 
     int             hashShift;          /* multiplicative hash shift */
 
     uint32_t        entryCount;         /* number of entries in table */
     uint32_t        removedCount;       /* removed entry sentinels in table */
--- a/js/src/yarr/wtfbridge.h
+++ b/js/src/yarr/wtfbridge.h
@@ -15,17 +15,16 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include "jsstr.h"
 #include "jsprvtd.h"
 #include "vm/String.h"
 #include "assembler/wtf/Platform.h"
 #include "assembler/jit/ExecutableAllocator.h"
 #include "yarr/CheckedArithmetic.h"
-#include "js/TemplateLib.h"
 
 namespace JSC { namespace Yarr {
 
 /*
  * Basic type definitions.
  */
 
 typedef char LChar;
new file mode 100644
--- /dev/null
+++ b/mfbt/TemplateLib.h
@@ -0,0 +1,111 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Reusable template meta-functions on types and compile-time values.  Meta-
+ * functions are placed inside the 'tl' namespace to avoid conflict with non-
+ * meta functions of the same name (e.g., mozilla::tl::FloorLog2 vs.
+ * mozilla::FloorLog2).
+ *
+ * When constexpr support becomes universal, we should probably use that instead
+ * of some of these templates, for simplicity.
+ */
+
+#ifndef mozilla_TemplateLib_h
+#define mozilla_TemplateLib_h
+
+#include <limits.h>
+#include <stddef.h>
+
+namespace mozilla {
+
+namespace tl {
+
+/** Compute min/max. */
+template<size_t I, size_t J>
+struct Min
+{
+    static const size_t value = I < J ? I : J;
+};
+template<size_t I, size_t J>
+struct Max
+{
+    static const size_t value = I > J ? I : J;
+};
+
+/** Compute floor(log2(i)). */
+template<size_t I>
+struct FloorLog2
+{
+    static const size_t value = 1 + FloorLog2<I / 2>::value;
+};
+template<> struct FloorLog2<0> { /* Error */ };
+template<> struct FloorLog2<1> { static const size_t value = 0; };
+
+/** Compute ceiling(log2(i)). */
+template<size_t I>
+struct CeilingLog2
+{
+    static const size_t value = FloorLog2<2 * I - 1>::value;
+};
+
+/** Round up to the nearest power of 2. */
+template<size_t I>
+struct RoundUpPow2
+{
+    static const size_t value = size_t(1) << CeilingLog2<I>::value;
+};
+template<>
+struct RoundUpPow2<0>
+{
+    static const size_t value = 1;
+};
+
+/** Compute the number of bits in the given unsigned type. */
+template<typename T>
+struct BitSize
+{
+    static const size_t value = sizeof(T) * CHAR_BIT;
+};
+
+/**
+ * Produce an N-bit mask, where N <= BitSize<size_t>::value.  Handle the
+ * language-undefined edge case when N = BitSize<size_t>::value.
+ */
+template<size_t N>
+struct NBitMask
+{
+    // Assert the precondition.  On success this evaluates to 0.  Otherwise it
+    // triggers divide-by-zero at compile time: a guaranteed compile error in
+    // C++11, and usually one in C++98.  Add this value to |value| to assure
+    // its computation.
+    static const size_t checkPrecondition = 0 / size_t(N < BitSize<size_t>::value);
+    static const size_t value = (size_t(1) << N) - 1 + checkPrecondition;
+};
+template<>
+struct NBitMask<BitSize<size_t>::value>
+{
+    static const size_t value = size_t(-1);
+};
+
+/**
+ * For the unsigned integral type size_t, compute a mask M for N such that
+ * for all X, !(X & M) implies X * N will not overflow (w.r.t size_t)
+ */
+template<size_t N>
+struct MulOverflowMask
+{
+    static const size_t value =
+      ~NBitMask<BitSize<size_t>::value - CeilingLog2<N>::value>::value;
+};
+template<> struct MulOverflowMask<0> { /* Error */ };
+template<> struct MulOverflowMask<1> { static const size_t value = 0; };
+
+} // namespace tl
+
+} // namespace mozilla
+
+#endif  /* mozilla_TemplateLib_h */
--- a/mfbt/exported_headers.mk
+++ b/mfbt/exported_headers.mk
@@ -40,15 +40,16 @@ EXPORTS_mozilla += \
   Range.h \
   RangedPtr.h \
   ReentrancyGuard.h \
   RefPtr.h \
   Scoped.h \
   SHA1.h \
   SplayTree.h \
   StandardInteger.h \
+  TemplateLib.h \
   ThreadLocal.h \
   TypedEnum.h \
   Types.h \
   TypeTraits.h \
   Util.h \
   WeakPtr.h \
   $(NULL)