Backed out changesets 6ee4b6cc240c, a818fd0874fe, and 70803a5f4683 (bug 1033442) for multiple crashtest oranges.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 08 Aug 2014 21:54:58 -0400
changeset 198731 93add398e8df0633e04d6caab18b06da925261c5
parent 198730 c13576bead5d94208be7d728d64b5c4e0aa4e76b
child 198732 bc1388026f8a7237df824b65da26a47f8dc62fca
push id8127
push userryanvm@gmail.com
push dateSat, 09 Aug 2014 15:26:38 +0000
treeherderfx-team@ad8cb646fad6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1033442
milestone34.0a1
backs out6ee4b6cc240cc14f833171077cd2f041665c40af
a818fd0874fef18782457445e7a1a1356a116952
70803a5f468399d53409b9c3e1df441ed02d1282
Backed out changesets 6ee4b6cc240c, a818fd0874fe, and 70803a5f4683 (bug 1033442) for multiple crashtest oranges.
js/public/HashTable.h
js/public/Utility.h
js/src/ds/LifoAlloc.h
js/src/gc/ForkJoinNursery.cpp
js/src/gc/ForkJoinNursery.h
js/src/jit/IonAllocPolicy.h
js/src/jit/MIR.cpp
js/src/jit/MIR.h
js/src/jit/RematerializedFrame.cpp
js/src/jsalloc.h
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.h
js/src/jsinfer.cpp
js/src/jsiter.cpp
js/src/jsscript.cpp
js/src/shell/js.cpp
js/src/vm/ArrayBufferObject.cpp
js/src/vm/MallocProvider.h
js/src/vm/Runtime.h
js/src/vm/Shape.cpp
js/src/vm/Shape.h
js/src/vm/StringBuffer.cpp
js/src/vm/StringBuffer.h
js/xpconnect/src/XPCLocale.cpp
layout/style/nsNthIndexCache.h
memory/replace/dmd/DMD.cpp
mfbt/AllocPolicy.h
mfbt/Vector.h
--- a/js/public/HashTable.h
+++ b/js/public/HashTable.h
@@ -1062,17 +1062,17 @@ class HashTable : private AllocPolicy
     }
 
     static Entry *createTable(AllocPolicy &alloc, uint32_t capacity)
     {
         static_assert(sFreeKey == 0,
                       "newly-calloc'd tables have to be considered empty");
         static_assert(sMaxCapacity <= SIZE_MAX / sizeof(Entry),
                       "would overflow allocating max number of entries");
-        return alloc.template pod_calloc<Entry>(capacity);
+        return static_cast<Entry*>(alloc.calloc_(capacity * sizeof(Entry)));
     }
 
     static void destroyTable(AllocPolicy &alloc, Entry *oldTable, uint32_t capacity)
     {
         for (Entry *e = oldTable, *end = e + capacity; e < end; ++e)
             e->destroyIfLive();
         alloc.free_(oldTable);
     }
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -558,26 +558,16 @@ template <class T>
 static MOZ_ALWAYS_INLINE T *
 js_pod_calloc(size_t numElems)
 {
     if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
         return nullptr;
     return (T *)js_calloc(numElems * sizeof(T));
 }
 
-template <class T>
-static MOZ_ALWAYS_INLINE T *
-js_pod_realloc(T *prior, size_t oldSize, size_t newSize)
-{
-    MOZ_ASSERT(!(oldSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value));
-    if (newSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
-        return nullptr;
-    return (T *)js_realloc(prior, newSize * sizeof(T));
-}
-
 namespace js {
 
 template<typename T>
 struct ScopedFreePtrTraits
 {
     typedef T* type;
     static T* empty() { return nullptr; }
     static void release(T* ptr) { js_free(ptr); }
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -514,34 +514,28 @@ class LifoAllocPolicy
 
   public:
     MOZ_IMPLICIT LifoAllocPolicy(LifoAlloc &alloc)
       : alloc_(alloc)
     {}
     void *malloc_(size_t bytes) {
         return fb == Fallible ? alloc_.alloc(bytes) : alloc_.allocInfallible(bytes);
     }
-    template <typename T>
-    T *pod_calloc(size_t numElems) {
-        if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
-            return nullptr;
-        T *p = (T *)malloc_(numElems * sizeof(T));
+    void *calloc_(size_t bytes) {
+        void *p = malloc_(bytes);
         if (fb == Fallible && !p)
             return nullptr;
-        memset(p, 0, numElems * sizeof(T));
+        memset(p, 0, bytes);
         return p;
     }
-    template <typename T>
-    T *pod_realloc(T *p, size_t oldSize, size_t newSize) {
-        if (newSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
-            return nullptr;
-        T *n = (T *)malloc_(newSize * sizeof(T));
+    void *realloc_(void *p, size_t oldBytes, size_t bytes) {
+        void *n = malloc_(bytes);
         if (fb == Fallible && !n)
             return nullptr;
-        memcpy(n, p, Min(oldSize * sizeof(T), newSize * sizeof(T)));
+        memcpy(n, p, Min(oldBytes, bytes));
         return n;
     }
     void free_(void *p) {
     }
     void reportAllocOverflow() const {
     }
 };
 
--- a/js/src/gc/ForkJoinNursery.cpp
+++ b/js/src/gc/ForkJoinNursery.cpp
@@ -580,33 +580,35 @@ ForkJoinNursery::allocateSlots(JSObject 
 
 HeapSlot *
 ForkJoinNursery::reallocateSlots(JSObject *obj, HeapSlot *oldSlots,
                                  uint32_t oldCount, uint32_t newCount)
 {
     if (newCount & mozilla::tl::MulOverflowMask<sizeof(HeapSlot)>::value)
         return nullptr;
 
+    size_t oldSize = oldCount * sizeof(HeapSlot);
+    size_t newSize = newCount * sizeof(HeapSlot);
+
     if (!isInsideNewspace(obj)) {
         JS_ASSERT_IF(oldSlots, !isInsideNewspace(oldSlots));
-        return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
+        return static_cast<HeapSlot *>(cx_->realloc_(oldSlots, oldSize, newSize));
     }
 
     if (!isInsideNewspace(oldSlots))
-        return reallocateHugeSlots(obj, oldSlots, oldCount, newCount);
+        return reallocateHugeSlots(oldSlots, oldSize, newSize);
 
     // No-op if we're shrinking, we can't make use of the freed portion.
     if (newCount < oldCount)
         return oldSlots;
 
     HeapSlot *newSlots = allocateSlots(obj, newCount);
     if (!newSlots)
         return nullptr;
 
-    size_t oldSize = oldCount * sizeof(HeapSlot);
     js_memcpy(newSlots, oldSlots, oldSize);
     return newSlots;
 }
 
 ObjectElements *
 ForkJoinNursery::allocateElements(JSObject *obj, uint32_t nelems)
 {
     JS_ASSERT(nelems >= ObjectElements::VALUES_PER_HEADER);
@@ -643,20 +645,19 @@ ForkJoinNursery::allocateHugeSlots(size_
         return slots;
 
     // If this put fails, we will only leak the slots.
     (void)hugeSlots[hugeSlotsNew].put(slots);
     return slots;
 }
 
 HeapSlot *
-ForkJoinNursery::reallocateHugeSlots(JSObject *obj, HeapSlot *oldSlots,
-                                     uint32_t oldCount, uint32_t newCount)
+ForkJoinNursery::reallocateHugeSlots(HeapSlot *oldSlots, uint32_t oldSize, uint32_t newSize)
 {
-    HeapSlot *newSlots = obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
+    HeapSlot *newSlots = static_cast<HeapSlot *>(cx_->realloc_(oldSlots, oldSize, newSize));
     if (!newSlots)
         return newSlots;
 
     if (oldSlots != newSlots) {
         hugeSlots[hugeSlotsNew].remove(oldSlots);
         // If this put fails, we will only leak the slots.
         (void)hugeSlots[hugeSlotsNew].put(newSlots);
     }
--- a/js/src/gc/ForkJoinNursery.h
+++ b/js/src/gc/ForkJoinNursery.h
@@ -205,18 +205,17 @@ class ForkJoinNursery
     void *allocate(size_t size);
 
     // Allocate an external slot array and register it with this nursery.
     HeapSlot *allocateHugeSlots(size_t nslots);
 
     // Reallocate an external slot array, unregister the old array and
     // register the new array.  If the allocation fails then leave
     // everything unchanged.
-    HeapSlot *reallocateHugeSlots(JSObject *obj, HeapSlot *oldSlots,
-                                  uint32_t oldCount, uint32_t newCount);
+    HeapSlot *reallocateHugeSlots(HeapSlot *oldSlots, uint32_t oldSize, uint32_t newSize);
 
     // Walk the list of registered slot arrays and free them all.
     void sweepHugeSlots();
 
     // Set the position/end pointers to correspond to the numbered
     // chunk.  Returns false if the chunk could not be allocated, either
     // because we're OOM or because the nursery capacity is exhausted.
     bool setCurrentChunk(int index);
--- a/js/src/jit/IonAllocPolicy.h
+++ b/js/src/jit/IonAllocPolicy.h
@@ -98,34 +98,27 @@ class IonAllocPolicy
 
   public:
     MOZ_IMPLICIT IonAllocPolicy(TempAllocator &alloc)
       : alloc_(alloc)
     {}
     void *malloc_(size_t bytes) {
         return alloc_.allocate(bytes);
     }
-    template <typename T>
-    T *pod_calloc(size_t numElems) {
-        if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
-            return nullptr;
-        T *p = (T *)alloc_.allocate(numElems * sizeof(T));
+    void *calloc_(size_t bytes) {
+        void *p = alloc_.allocate(bytes);
         if (p)
-            memset(p, 0, numElems * sizeof(T));
+            memset(p, 0, bytes);
         return p;
     }
-    template <typename T>
-    T *pod_realloc(T *p, size_t oldSize, size_t newSize) {
-        MOZ_ASSERT(!(oldSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value));
-        if (newSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
-            return nullptr;
-        T *n = (T *)malloc_(newSize * sizeof(T));
+    void *realloc_(void *p, size_t oldBytes, size_t bytes) {
+        void *n = malloc_(bytes);
         if (!n)
             return n;
-        memcpy(n, p, Min(oldSize * sizeof(T), newSize * sizeof(T)));
+        memcpy(n, p, Min(oldBytes, bytes));
         return n;
     }
     void free_(void *p) {
     }
     void reportAllocOverflow() const {
     }
 };
 
@@ -134,16 +127,29 @@ class IonAllocPolicy
 class OldIonAllocPolicy
 {
   public:
     OldIonAllocPolicy()
     {}
     void *malloc_(size_t bytes) {
         return GetIonContext()->temp->allocate(bytes);
     }
+    void *calloc_(size_t bytes) {
+        void *p = GetIonContext()->temp->allocate(bytes);
+        if (p)
+            memset(p, 0, bytes);
+        return p;
+    }
+    void *realloc_(void *p, size_t oldBytes, size_t bytes) {
+        void *n = malloc_(bytes);
+        if (!n)
+            return n;
+        memcpy(n, p, Min(oldBytes, bytes));
+        return n;
+    }
     void free_(void *p) {
     }
     void reportAllocOverflow() const {
     }
 };
 
 class AutoIonContextAlloc
 {
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -1049,17 +1049,17 @@ MPhi::congruentTo(const MDefinition *ins
     return congruentIfOperandsEqual(ins);
 }
 
 bool
 MPhi::reserveLength(size_t length)
 {
     // Initializes a new MPhi to have an Operand vector of at least the given
     // capacity. This permits use of addInput() instead of addInputSlow(), the
-    // latter of which may call realloc().
+    // latter of which may call realloc_().
     JS_ASSERT(numOperands() == 0);
 #if DEBUG
     capacity_ = length;
 #endif
     return inputs_.reserve(length);
 }
 
 static inline types::TemporaryTypeSet *
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -5245,17 +5245,17 @@ class MPhi MOZ_FINAL : public MDefinitio
 
     // Initializes the operands vector to the given capacity,
     // permitting use of addInput() instead of addInputSlow().
     bool reserveLength(size_t length);
 
     // Use only if capacity has been reserved by reserveLength
     void addInput(MDefinition *ins);
 
-    // Appends a new input to the input vector. May call realloc().
+    // Appends a new input to the input vector. May call realloc_().
     // Prefer reserveLength() and addInput() instead, where possible.
     bool addInputSlow(MDefinition *ins, bool *ptypeChange = nullptr);
 
     MDefinition *foldsTo(TempAllocator &alloc);
 
     bool congruentTo(const MDefinition *ins) const;
 
     bool isIterator() const {
--- a/js/src/jit/RematerializedFrame.cpp
+++ b/js/src/jit/RematerializedFrame.cpp
@@ -47,17 +47,17 @@ RematerializedFrame::RematerializedFrame
 RematerializedFrame::New(ThreadSafeContext *cx, uint8_t *top, InlineFrameIterator &iter)
 {
     unsigned numFormals = iter.isFunctionFrame() ? iter.callee()->nargs() : 0;
     unsigned numActualArgs = Max(numFormals, iter.numActualArgs());
     size_t numBytes = sizeof(RematerializedFrame) +
         (numActualArgs + iter.script()->nfixed()) * sizeof(Value) -
         sizeof(Value); // 1 Value included in sizeof(RematerializedFrame)
 
-    void *buf = cx->pod_calloc<uint8_t>(numBytes);
+    void *buf = cx->calloc_(numBytes);
     if (!buf)
         return nullptr;
 
     return new (buf) RematerializedFrame(cx, top, numActualArgs, iter);
 }
 
 /* static */ bool
 RematerializedFrame::RematerializeInlineFrames(ThreadSafeContext *cx, uint8_t *top,
--- a/js/src/jsalloc.h
+++ b/js/src/jsalloc.h
@@ -21,20 +21,18 @@ namespace js {
 
 struct ContextFriendFields;
 
 /* Policy for using system memory functions and doing no error reporting. */
 class SystemAllocPolicy
 {
   public:
     void *malloc_(size_t bytes) { return js_malloc(bytes); }
-    template <typename T> T *pod_calloc(size_t numElems) { return js_pod_calloc<T>(numElems); }
-    template <typename T> T *pod_realloc(T *p, size_t oldSize, size_t newSize) {
-        return js_pod_realloc<T>(p, oldSize, newSize);
-    }
+    void *calloc_(size_t bytes) { return js_calloc(bytes); }
+    void *realloc_(void *p, size_t oldBytes, size_t bytes) { return js_realloc(p, bytes); }
     void free_(void *p) { js_free(p); }
     void reportAllocOverflow() const {}
 };
 
 /*
  * Allocation policy that calls the system memory functions and reports errors
  * to the context. Since the JSContext given on construction is stored for
  * the lifetime of the container, this policy may only be used for containers
@@ -59,29 +57,27 @@ class TempAllocPolicy
 
     void *malloc_(size_t bytes) {
         void *p = js_malloc(bytes);
         if (MOZ_UNLIKELY(!p))
             p = onOutOfMemory(nullptr, bytes);
         return p;
     }
 
-    template <typename T>
-    T *pod_calloc(size_t numElems) {
-        T *p = js_pod_calloc<T>(numElems);
+    void *calloc_(size_t bytes) {
+        void *p = js_calloc(bytes);
         if (MOZ_UNLIKELY(!p))
-            p = (T *)onOutOfMemory(reinterpret_cast<void *>(1), numElems * sizeof(T));
+            p = onOutOfMemory(nullptr, bytes);
         return p;
     }
 
-    template <typename T>
-    T *pod_realloc(T *prior, size_t oldSize, size_t newSize) {
-        T *p2 = js_pod_realloc<T>(prior, oldSize, newSize);
+    void *realloc_(void *p, size_t oldBytes, size_t bytes) {
+        void *p2 = js_realloc(p, bytes);
         if (MOZ_UNLIKELY(!p2))
-            p2 = (T *)onOutOfMemory(p2, newSize * sizeof(T));
+            p2 = onOutOfMemory(p2, bytes);
         return p2;
     }
 
     void free_(void *p) {
         js_free(p);
     }
 
     JS_FRIEND_API(void) reportAllocOverflow() const;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1434,22 +1434,21 @@ JS_PUBLIC_API(void *)
 JS_malloc(JSContext *cx, size_t nbytes)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
     return cx->malloc_(nbytes);
 }
 
 JS_PUBLIC_API(void *)
-JS_realloc(JSContext *cx, void *p, size_t oldBytes, size_t newBytes)
-{
-    AssertHeapIsIdle(cx);
-    CHECK_REQUEST(cx);
-    return static_cast<void *>(cx->zone()->pod_realloc<uint8_t>(static_cast<uint8_t *>(p), oldBytes,
-                                                                newBytes));
+JS_realloc(JSContext *cx, void *p, size_t nbytes)
+{
+    AssertHeapIsIdle(cx);
+    CHECK_REQUEST(cx);
+    return cx->realloc_(p, nbytes);
 }
 
 JS_PUBLIC_API(void)
 JS_free(JSContext *cx, void *p)
 {
     return js_free(p);
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1856,17 +1856,17 @@ typedef bool
  */
 extern JS_PUBLIC_API(void)
 JS_EnumerateDiagnosticMemoryRegions(JSEnumerateDiagnosticMemoryCallback callback);
 
 extern JS_PUBLIC_API(void *)
 JS_malloc(JSContext *cx, size_t nbytes);
 
 extern JS_PUBLIC_API(void *)
-JS_realloc(JSContext *cx, void *p, size_t oldBytes, size_t newBytes);
+JS_realloc(JSContext *cx, void *p, size_t nbytes);
 
 /*
  * A wrapper for js_free(p) that may delay js_free(p) invocation as a
  * performance optimization.
  * cx may be nullptr.
  */
 extern JS_PUBLIC_API(void)
 JS_free(JSContext *cx, void *p);
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -977,16 +977,18 @@ class AutoAssertNoException
 class ContextAllocPolicy
 {
     ThreadSafeContext *const cx_;
 
   public:
     MOZ_IMPLICIT ContextAllocPolicy(ThreadSafeContext *cx) : cx_(cx) {}
     ThreadSafeContext *context() const { return cx_; }
     void *malloc_(size_t bytes) { return cx_->malloc_(bytes); }
+    void *calloc_(size_t bytes) { return cx_->calloc_(bytes); }
+    void *realloc_(void *p, size_t oldBytes, size_t bytes) { return cx_->realloc_(p, oldBytes, bytes); }
     void free_(void *p) { js_free(p); }
     void reportAllocOverflow() const { js_ReportAllocationOverflow(cx_); }
 };
 
 /* Exposed intrinsics so that Ion may inline them. */
 bool intrinsic_ToObject(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_IsObject(JSContext *cx, unsigned argc, Value *vp);
 bool intrinsic_ToInteger(JSContext *cx, unsigned argc, Value *vp);
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -3438,17 +3438,17 @@ CheckNewScriptProperties(JSContext *cx, 
         !type->addDefiniteProperties(cx, baseobj) ||
         !initializerList.append(done))
     {
         return;
     }
 
     size_t numBytes = sizeof(TypeNewScript)
                     + (initializerList.length() * sizeof(TypeNewScript::Initializer));
-    TypeNewScript *newScript = (TypeNewScript *) type->zone()->pod_calloc<uint8_t>(numBytes);
+    TypeNewScript *newScript = (TypeNewScript *) cx->calloc_(numBytes);
     if (!newScript)
         return;
 
     new (newScript) TypeNewScript();
 
     type->setAddendum(newScript);
 
     newScript->fun = fun;
@@ -3601,17 +3601,17 @@ JSScript::makeTypes(JSContext *cx)
 {
     JS_ASSERT(!types);
 
     AutoEnterAnalysis enter(cx);
 
     unsigned count = TypeScript::NumTypeSets(this);
 
     TypeScript *typeScript = (TypeScript *)
-        zone()->pod_calloc<uint8_t>(TypeScript::SizeIncludingTypeArray(count));
+        cx->calloc_(TypeScript::SizeIncludingTypeArray(count));
     if (!typeScript)
         return false;
 
     types = typeScript;
 
 #ifdef DEBUG
     StackTypeSet *typeArray = typeScript->typeArray();
     for (unsigned i = 0; i < nTypeSets(); i++) {
--- a/js/src/jsiter.cpp
+++ b/js/src/jsiter.cpp
@@ -1779,17 +1779,17 @@ js_NewGenerator(JSContext *cx, const Int
                    (-1 + /* one Value included in JSGenerator */
                     vplen +
                     VALUES_PER_STACK_FRAME +
                     stackfp->script()->nslots()) * sizeof(HeapValue);
 
     JS_ASSERT(nbytes % sizeof(Value) == 0);
     JS_STATIC_ASSERT(sizeof(InterpreterFrame) % sizeof(HeapValue) == 0);
 
-    JSGenerator *gen = (JSGenerator *) obj->zone()->pod_calloc<uint8_t>(nbytes);
+    JSGenerator *gen = (JSGenerator *) cx->calloc_(nbytes);
     if (!gen)
         return nullptr;
 
     /* Cut up floatingStack space. */
     HeapValue *genvp = gen->stackSnapshot;
     SetValueRangeToUndefined((Value *)genvp, vplen);
 
     InterpreterFrame *genfp = reinterpret_cast<InterpreterFrame *>(genvp + vplen);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -1133,34 +1133,34 @@ JSScript::initScriptCounts(JSContext *cx
 {
     JS_ASSERT(!hasScriptCounts());
 
     size_t n = 0;
 
     for (jsbytecode *pc = code(); pc < codeEnd(); pc += GetBytecodeLength(pc))
         n += PCCounts::numCounts(JSOp(*pc));
 
-    size_t nbytes = (length() * sizeof(PCCounts)) + (n * sizeof(double));
-    uint8_t *base = zone()->pod_calloc<uint8_t>(nbytes);
+    size_t bytes = (length() * sizeof(PCCounts)) + (n * sizeof(double));
+    char *base = (char *) cx->calloc_(bytes);
     if (!base)
         return false;
 
     /* Create compartment's scriptCountsMap if necessary. */
     ScriptCountsMap *map = compartment()->scriptCountsMap;
     if (!map) {
         map = cx->new_<ScriptCountsMap>();
         if (!map || !map->init()) {
             js_free(base);
             js_delete(map);
             return false;
         }
         compartment()->scriptCountsMap = map;
     }
 
-    uint8_t *cursor = base;
+    char *cursor = base;
 
     ScriptCounts scriptCounts;
     scriptCounts.pcCountsVector = (PCCounts *) cursor;
     cursor += length() * sizeof(PCCounts);
 
     for (jsbytecode *pc = code(); pc < codeEnd(); pc += GetBytecodeLength(pc)) {
         JS_ASSERT(uintptr_t(cursor) % sizeof(double) == 0);
         scriptCounts.pcCountsVector[pcToOffset(pc)].counts = (double *) cursor;
@@ -1172,17 +1172,17 @@ JSScript::initScriptCounts(JSContext *cx
     }
 
     if (!map->putNew(this, scriptCounts)) {
         js_free(base);
         return false;
     }
     hasScriptCounts_ = true; // safe to set this;  we can't fail after this point
 
-    JS_ASSERT(size_t(cursor - base) == nbytes);
+    JS_ASSERT(size_t(cursor - base) == bytes);
 
     /* Enable interrupts in any interpreter frames running on this script. */
     for (ActivationIterator iter(cx->runtime()); !iter.done(); ++iter) {
         if (iter->isInterpreter())
             iter->asInterpreter()->enableInterruptsIfRunning(this);
     }
 
     return true;
@@ -2353,38 +2353,41 @@ JSScript::Create(ExclusiveContext *cx, H
     script->setSourceObject(sourceObject);
     script->sourceStart_ = bufStart;
     script->sourceEnd_ = bufEnd;
 
     return script;
 }
 
 static inline uint8_t *
-AllocScriptData(JS::Zone *zone, size_t size)
+AllocScriptData(ExclusiveContext *cx, size_t size)
 {
-    if (!size)
-        return nullptr;
-
-    uint8_t *data = zone->pod_calloc<uint8_t>(JS_ROUNDUP(size, sizeof(Value)));
+    uint8_t *data = static_cast<uint8_t *>(cx->calloc_(JS_ROUNDUP(size, sizeof(Value))));
     if (!data)
         return nullptr;
-    JS_ASSERT(size_t(data) % sizeof(Value) == 0);
+
+    // All script data is optional, so size might be 0. In that case, we don't care about alignment.
+    JS_ASSERT(size == 0 || size_t(data) % sizeof(Value) == 0);
     return data;
 }
 
 /* static */ bool
 JSScript::partiallyInit(ExclusiveContext *cx, HandleScript script, uint32_t nconsts,
                         uint32_t nobjects, uint32_t nregexps, uint32_t ntrynotes,
                         uint32_t nblockscopes, uint32_t nTypeSets)
 {
     size_t size = ScriptDataSize(script->bindings.count(), nconsts, nobjects, nregexps, ntrynotes,
                                  nblockscopes);
-    script->data = AllocScriptData(script->zone(), size);
-    if (size && !script->data)
-        return false;
+    if (size > 0) {
+        script->data = AllocScriptData(cx, size);
+        if (!script->data)
+            return false;
+    } else {
+        script->data = nullptr;
+    }
     script->dataSize_ = size;
 
     JS_ASSERT(nTypeSets <= UINT16_MAX);
     script->nTypeSets_ = uint16_t(nTypeSets);
 
     uint8_t *cursor = script->data;
     if (nconsts != 0) {
         script->setHasArray(CONSTS);
@@ -2882,18 +2885,18 @@ js::CloneScript(JSContext *cx, HandleObj
     uint32_t nobjects  = src->hasObjects()  ? src->objects()->length  : 0;
     uint32_t nregexps  = src->hasRegexps()  ? src->regexps()->length  : 0;
     uint32_t ntrynotes = src->hasTrynotes() ? src->trynotes()->length : 0;
     uint32_t nblockscopes = src->hasBlockScopes() ? src->blockScopes()->length : 0;
 
     /* Script data */
 
     size_t size = src->dataSize();
-    uint8_t *data = AllocScriptData(cx->zone(), size);
-    if (size && !data)
+    uint8_t *data = AllocScriptData(cx, size);
+    if (!data)
         return nullptr;
 
     /* Bindings */
 
     Rooted<Bindings> bindings(cx);
     InternalHandle<Bindings*> bindingsHandle =
         InternalHandle<Bindings*>::fromMarkedLocation(bindings.address());
     if (!Bindings::clone(cx, bindingsHandle, data, src))
@@ -3144,17 +3147,17 @@ JSScript::destroyDebugScript(FreeOp *fop
 
 bool
 JSScript::ensureHasDebugScript(JSContext *cx)
 {
     if (hasDebugScript_)
         return true;
 
     size_t nbytes = offsetof(DebugScript, breakpoints) + length() * sizeof(BreakpointSite*);
-    DebugScript *debug = (DebugScript *) zone()->pod_calloc<uint8_t>(nbytes);
+    DebugScript *debug = (DebugScript *) cx->calloc_(nbytes);
     if (!debug)
         return false;
 
     /* Create compartment's debugScriptMap if necessary. */
     DebugScriptMap *map = compartment()->debugScriptMap;
     if (!map) {
         map = cx->new_<DebugScriptMap>();
         if (!map || !map->init()) {
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -494,17 +494,17 @@ ReadEvalPrintLoop(JSContext *cx, Handle<
     do {
         /*
          * Accumulate lines until we get a 'compilable unit' - one that either
          * generates an error (before running out of source) or that compiles
          * cleanly.  This should be whenever we get a complete statement that
          * coincides with the end of a line.
          */
         int startline = lineno;
-        typedef Vector<char, 32> CharBuffer;
+        typedef Vector<char, 32, ContextAllocPolicy> CharBuffer;
         CharBuffer buffer(cx);
         do {
             ScheduleWatchdog(cx->runtime(), -1);
             gServiceInterrupt = false;
             errno = 0;
 
             char *line = GetLine(in, startline == lineno ? "js> " : "");
             if (!line) {
@@ -1502,17 +1502,17 @@ ReadLine(JSContext *cx, unsigned argc, j
         } else if (buflength < bufsize - 1) {
             break;
         }
 
         /* Else, grow our buffer for another pass. */
         char *tmp;
         bufsize *= 2;
         if (bufsize > buflength) {
-            tmp = static_cast<char *>(JS_realloc(cx, buf, bufsize / 2, bufsize));
+            tmp = (char *) JS_realloc(cx, buf, bufsize);
         } else {
             JS_ReportOutOfMemory(cx);
             tmp = nullptr;
         }
 
         if (!tmp) {
             JS_free(cx, buf);
             return false;
@@ -1524,17 +1524,17 @@ ReadLine(JSContext *cx, unsigned argc, j
     /* Treat the empty string specially. */
     if (buflength == 0) {
         args.rval().set(feof(from) ? NullValue() : JS_GetEmptyStringValue(cx));
         JS_free(cx, buf);
         return true;
     }
 
     /* Shrink the buffer to the real size. */
-    char *tmp = static_cast<char *>(JS_realloc(cx, buf, bufsize, buflength));
+    char *tmp = static_cast<char*>(JS_realloc(cx, buf, buflength));
     if (!tmp) {
         JS_free(cx, buf);
         return false;
     }
 
     buf = tmp;
 
     /*
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -270,32 +270,27 @@ ArrayBufferObject::class_constructor(JSC
  * Note that some callers are allowed to pass in a nullptr cx, so we allocate
  * with the cx if available and fall back to the runtime.  If oldptr is given,
  * it's expected to be a previously-allocated contents pointer that we then
  * realloc.
  */
 static void *
 AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void *oldptr = nullptr, size_t oldnbytes = 0)
 {
-    uint8_t *p;
+    void *p;
 
     // if oldptr is given, then we need to do a realloc
     if (oldptr) {
-        uint8_t *prior = static_cast<uint8_t *>(oldptr);
-        p = maybecx
-            ? maybecx->runtime()->pod_reallocCanGC<uint8_t>(prior, oldnbytes, nbytes)
-            : js_pod_realloc<uint8_t>(prior, oldnbytes, nbytes);
+        p = maybecx ? maybecx->runtime()->reallocCanGC(oldptr, nbytes) : js_realloc(oldptr, nbytes);
 
         // if we grew the array, we need to set the new bytes to 0
         if (p && nbytes > oldnbytes)
-            memset(p + oldnbytes, 0, nbytes - oldnbytes);
+            memset(reinterpret_cast<uint8_t *>(p) + oldnbytes, 0, nbytes - oldnbytes);
     } else {
-        p = maybecx
-            ? maybecx->runtime()->pod_callocCanGC<uint8_t>(nbytes)
-            : js_pod_calloc<uint8_t>(nbytes);
+        p = maybecx ? maybecx->runtime()->callocCanGC(nbytes) : js_calloc(nbytes);
     }
 
     if (!p && maybecx)
         js_ReportOutOfMemory(maybecx);
 
     return p;
 }
 
--- a/js/src/vm/MallocProvider.h
+++ b/js/src/vm/MallocProvider.h
@@ -18,20 +18,16 @@
  *     These allocators are for system memory whose lifetime is not associated
  *     with a GC thing. See js/src/jsalloc.h.
  *
  *       - SystemAllocPolicy: No extra functionality over bare allocators.
  *
  *       - TempAllocPolicy: Adds automatic error reporting to the provided
  *         Context when allocations fail.
  *
- *       - ContextAllocPolicy: forwards to the JSContext MallocProvider.
- *
- *       - RuntimeAllocPolicy: forwards to the JSRuntime MallocProvider.
- *
  *   - MallocProvider. A mixin base class that handles automatically updating
  *     the GC's state in response to allocations that are tied to a GC lifetime
  *     or are for a particular GC purpose. These allocators must only be used
  *     for memory that will be freed when a GC thing is swept.
  *
  *       - gc::Zone:  Automatically triggers zone GC.
  *       - JSRuntime: Automatically triggers full GC.
  *       - ThreadsafeContext > ExclusiveContext > JSContext:
@@ -54,31 +50,55 @@ struct MallocProvider
 {
     void *malloc_(size_t bytes) {
         Client *client = static_cast<Client *>(this);
         client->updateMallocCounter(bytes);
         void *p = js_malloc(bytes);
         return MOZ_LIKELY(!!p) ? p : client->onOutOfMemory(nullptr, bytes);
     }
 
+    void *calloc_(size_t bytes) {
+        Client *client = static_cast<Client *>(this);
+        client->updateMallocCounter(bytes);
+        void *p = js_calloc(bytes);
+        return MOZ_LIKELY(!!p) ? p : client->onOutOfMemory(reinterpret_cast<void *>(1), bytes);
+    }
+
+    void *realloc_(void *p, size_t oldBytes, size_t newBytes) {
+        Client *client = static_cast<Client *>(this);
+        /*
+         * For compatibility we do not account for realloc that decreases
+         * previously allocated memory.
+         */
+        if (newBytes > oldBytes)
+            client->updateMallocCounter(newBytes - oldBytes);
+        void *p2 = js_realloc(p, newBytes);
+        return MOZ_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, newBytes);
+    }
+
+    void *realloc_(void *p, size_t bytes) {
+        Client *client = static_cast<Client *>(this);
+        /*
+         * For compatibility we do not account for realloc that increases
+         * previously allocated memory.
+         */
+        if (!p)
+            client->updateMallocCounter(bytes);
+        void *p2 = js_realloc(p, bytes);
+        return MOZ_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, bytes);
+    }
+
     template <class T>
     T *pod_malloc() {
         return (T *)malloc_(sizeof(T));
     }
 
     template <class T>
     T *pod_calloc() {
-        Client *client = static_cast<Client *>(this);
-        client->updateMallocCounter(sizeof(T));
-        T *p = js_pod_calloc<T>();
-        if (MOZ_UNLIKELY(!p)) {
-            client->onOutOfMemory(reinterpret_cast<void *>(1), sizeof(T));
-            return nullptr;
-        }
-        return p;
+        return (T *)calloc_(sizeof(T));
     }
 
     template <class T>
     T *pod_malloc(size_t numElems) {
         if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
             Client *client = static_cast<Client *>(this);
             client->reportAllocationOverflow();
             return nullptr;
@@ -89,56 +109,39 @@ struct MallocProvider
     template <class T>
     mozilla::UniquePtr<T[], JS::FreePolicy>
     make_pod_array(size_t numElems) {
         return mozilla::UniquePtr<T[], JS::FreePolicy>(pod_malloc<T>(numElems));
     }
 
     template <class T>
     T *
-    pod_calloc(size_t numElems) {
+    pod_calloc(size_t numElems, JSCompartment *comp = nullptr, JSContext *cx = nullptr) {
         if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
             Client *client = static_cast<Client *>(this);
             client->reportAllocationOverflow();
             return nullptr;
         }
-        Client *client = static_cast<Client *>(this);
-        client->updateMallocCounter(numElems * sizeof(T));
-        T *p = js_pod_calloc<T>(numElems);
-        if (MOZ_UNLIKELY(!p)) {
-            client->onOutOfMemory(reinterpret_cast<void *>(1), sizeof(T));
-            return nullptr;
-        }
-        return p;
+        return (T *)calloc_(numElems * sizeof(T));
     }
 
     template <class T>
     mozilla::UniquePtr<T[], JS::FreePolicy>
-    make_zeroed_pod_array(size_t numElems) {
-        return mozilla::UniquePtr<T[], JS::FreePolicy>(pod_calloc<T>(numElems));
+    make_zeroed_pod_array(size_t numElems,
+                          JSCompartment *comp = nullptr,
+                          JSContext *cx = nullptr)
+    {
+        return mozilla::UniquePtr<T[], JS::FreePolicy>(pod_calloc<T>(numElems, comp, cx));
     }
 
     template <class T>
     T *pod_realloc(T *prior, size_t oldSize, size_t newSize) {
-        Client *client = static_cast<Client *>(this);
-        T *p = js_pod_realloc(prior, oldSize, newSize);
-        if (MOZ_LIKELY(p)) {
-            // For compatibility we do not account for realloc that decreases
-            // previously allocated memory.
-            if (newSize > oldSize)
-                client->updateMallocCounter((newSize - oldSize) * sizeof(T));
-            return p;
-        }
-        if (newSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
-            client->reportAllocationOverflow();
-            return nullptr;
-        }
-        client->onOutOfMemory(prior, newSize * sizeof(T));
-        return nullptr;
+        return (T *)realloc_(prior, oldSize * sizeof(T), newSize * sizeof(T));
     }
 
+
     JS_DECLARE_NEW_METHODS(new_, malloc_, MOZ_ALWAYS_INLINE)
     JS_DECLARE_MAKE_METHODS(make_unique, new_, MOZ_ALWAYS_INLINE)
 };
 
 } /* namespace js */
 
 #endif /* vm_MallocProvider_h */
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -1366,38 +1366,28 @@ struct JSRuntime : public JS::shadow::Ru
 
     /*
      * These variations of malloc/calloc/realloc will call the
      * large-allocation-failure callback on OOM and retry the allocation.
      */
 
     static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
 
-    template <typename T>
-    T *pod_callocCanGC(size_t numElems) {
-        T *p = pod_calloc<T>(numElems);
+    void *callocCanGC(size_t bytes) {
+        void *p = calloc_(bytes);
         if (MOZ_LIKELY(!!p))
             return p;
-        if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
-            reportAllocationOverflow();
-            return nullptr;
-        }
-        return (T *)onOutOfMemoryCanGC(reinterpret_cast<void *>(1), numElems * sizeof(T));
+        return onOutOfMemoryCanGC(reinterpret_cast<void *>(1), bytes);
     }
 
-    template <typename T>
-    T *pod_reallocCanGC(T *p, size_t oldSize, size_t newSize) {
-        T *p2 = pod_realloc<T>(p, oldSize, newSize);
+    void *reallocCanGC(void *p, size_t bytes) {
+        void *p2 = realloc_(p, bytes);
         if (MOZ_LIKELY(!!p2))
             return p2;
-        if (newSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
-            reportAllocationOverflow();
-            return nullptr;
-        }
-        return (T *)onOutOfMemoryCanGC(p, newSize * sizeof(T));
+        return onOutOfMemoryCanGC(p, bytes);
     }
 };
 
 namespace js {
 
 // When entering JIT code, the calling JSContext* is stored into the thread's
 // PerThreadData. This function retrieves the JSContext with the pre-condition
 // that the caller is JIT code or C++ called directly from JIT code. This
@@ -1657,27 +1647,18 @@ SetValueRangeToNull(Value *vec, size_t l
  */
 class RuntimeAllocPolicy
 {
     JSRuntime *const runtime;
 
   public:
     MOZ_IMPLICIT RuntimeAllocPolicy(JSRuntime *rt) : runtime(rt) {}
     void *malloc_(size_t bytes) { return runtime->malloc_(bytes); }
-
-    template <typename T>
-    T *pod_calloc(size_t numElems) {
-        return runtime->pod_calloc<T>(numElems);
-    }
-
-    template <typename T>
-    T *pod_realloc(T *p, size_t oldSize, size_t newSize) {
-        return runtime->pod_realloc<T>(p, oldSize, newSize);
-    }
-
+    void *calloc_(size_t bytes) { return runtime->calloc_(bytes); }
+    void *realloc_(void *p, size_t bytes) { return runtime->realloc_(p, bytes); }
     void free_(void *p) { js_free(p); }
     void reportAllocOverflow() const {}
 };
 
 extern const JSSecurityCallbacks NullSecurityCallbacks;
 
 // Debugging RAII class which marks the current thread as performing an Ion
 // compilation, for use by CurrentThreadCan{Read,Write}CompilationData
--- a/js/src/vm/Shape.cpp
+++ b/js/src/vm/Shape.cpp
@@ -40,20 +40,20 @@ ShapeTable::init(ThreadSafeContext *cx, 
     uint32_t sizeLog2 = CeilingLog2Size(entryCount);
     uint32_t size = JS_BIT(sizeLog2);
     if (entryCount >= size - (size >> 2))
         sizeLog2++;
     if (sizeLog2 < MIN_SIZE_LOG2)
         sizeLog2 = MIN_SIZE_LOG2;
 
     /*
-     * Use rt->calloc for memory accounting and overpressure handling
+     * Use rt->calloc_ for memory accounting and overpressure handling
      * without OOM reporting. See ShapeTable::change.
      */
-    entries = cx->pod_calloc<Shape *>(JS_BIT(sizeLog2));
+    entries = (Shape **) cx->calloc_(sizeOfEntries(JS_BIT(sizeLog2)));
     if (!entries)
         return false;
 
     hashShift = HASH_BITS - sizeLog2;
     for (Shape::Range<NoGC> r(lastProp); !r.empty(); r.popFront()) {
         Shape &shape = r.front();
         JS_ASSERT(cx->isThreadLocal(&shape));
         Shape **spp = search(shape.propid(), true);
@@ -255,17 +255,17 @@ ShapeTable::change(int log2Delta, Thread
 
     /*
      * Grow, shrink, or compress by changing this->entries.
      */
     int oldlog2 = HASH_BITS - hashShift;
     int newlog2 = oldlog2 + log2Delta;
     uint32_t oldsize = JS_BIT(oldlog2);
     uint32_t newsize = JS_BIT(newlog2);
-    Shape **newTable = cx->pod_calloc<Shape *>(newsize);
+    Shape **newTable = (Shape **) cx->calloc_(sizeOfEntries(newsize));
     if (!newTable)
         return false;
 
     /* Now that we have newTable allocated, update members. */
     hashShift = HASH_BITS - newlog2;
     removedCount = 0;
     Shape **oldTable = entries;
     entries = newTable;
--- a/js/src/vm/Shape.h
+++ b/js/src/vm/Shape.h
@@ -156,16 +156,19 @@ struct ShapeTable {
 
     ~ShapeTable() {
         js_free(entries);
     }
 
     /* By definition, hashShift = HASH_BITS - log2(capacity). */
     uint32_t capacity() const { return JS_BIT(HASH_BITS - hashShift); }
 
+    /* Computes the size of the entries array for a given capacity. */
+    static size_t sizeOfEntries(size_t cap) { return cap * sizeof(Shape *); }
+
     /*
      * This counts the ShapeTable object itself (which must be
      * heap-allocated) and its |entries| array.
      */
     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
         return mallocSizeOf(this) + mallocSizeOf(entries);
     }
 
@@ -179,17 +182,17 @@ struct ShapeTable {
      * Try to grow the table.  On failure, reports out of memory on cx
      * and returns false.  This will make any extant pointers into the
      * table invalid.  Don't call this unless needsToGrow() is true.
      */
     bool grow(ThreadSafeContext *cx);
 
     /*
      * NB: init and change are fallible but do not report OOM, so callers can
-     * cope or ignore. They do however use the context's calloc method in
+     * cope or ignore. They do however use the context's calloc_ method in
      * order to update the malloc counter on success.
      */
     bool            init(ThreadSafeContext *cx, Shape *lastProp);
     bool            change(int log2Delta, ThreadSafeContext *cx);
     Shape           **search(jsid id, bool adding);
 };
 
 /*
--- a/js/src/vm/StringBuffer.cpp
+++ b/js/src/vm/StringBuffer.cpp
@@ -23,17 +23,18 @@ ExtractWellSized(ExclusiveContext *cx, B
 
     CharT *buf = cb.extractRawBuffer();
     if (!buf)
         return nullptr;
 
     /* For medium/big buffers, avoid wasting more than 1/4 of the memory. */
     JS_ASSERT(capacity >= length);
     if (length > Buffer::sMaxInlineStorage && capacity - length > length / 4) {
-        CharT *tmp = cx->zone()->pod_realloc<CharT>(buf, capacity, length + 1);
+        size_t bytes = sizeof(CharT) * (length + 1);
+        CharT *tmp = (CharT *)cx->realloc_(buf, bytes);
         if (!tmp) {
             js_free(buf);
             return nullptr;
         }
         buf = tmp;
     }
 
     return buf;
--- a/js/src/vm/StringBuffer.h
+++ b/js/src/vm/StringBuffer.h
@@ -28,18 +28,18 @@ namespace js {
  * See |extractWellSized|.
  */
 class StringBuffer
 {
     /*
      * The Vector's buffer is taken by the new string so use
      * ContextAllocPolicy.
      */
-    typedef Vector<Latin1Char, 64> Latin1CharBuffer;
-    typedef Vector<jschar, 32> TwoByteCharBuffer;
+    typedef Vector<Latin1Char, 64, ContextAllocPolicy> Latin1CharBuffer;
+    typedef Vector<jschar, 32, ContextAllocPolicy> TwoByteCharBuffer;
 
     ExclusiveContext *cx;
 
     /*
      * If Latin1 strings are enabled, cb starts out as a Latin1CharBuffer. When
      * a TwoByte char is appended, inflateChars() constructs a TwoByteCharBuffer
      * and copies the Latin1 chars.
      */
--- a/js/xpconnect/src/XPCLocale.cpp
+++ b/js/xpconnect/src/XPCLocale.cpp
@@ -208,18 +208,18 @@ private:
         rv = mDecoder->Convert(src, &srcLength, unichars, &unicharLength);
         if (NS_SUCCEEDED(rv)) {
           // terminate the returned string
           unichars[unicharLength] = 0;
 
           // nsIUnicodeDecoder::Convert may use fewer than srcLength PRUnichars
           if (unicharLength + 1 < srcLength + 1) {
             char16_t *shrunkUnichars =
-              static_cast<char16_t *>(JS_realloc(cx, unichars, srcLength + 1,
-                                                 unicharLength + 1));
+              (char16_t *)JS_realloc(cx, unichars,
+                                      (unicharLength + 1) * sizeof(char16_t));
             if (shrunkUnichars)
               unichars = shrunkUnichars;
           }
           JSString *str = JS_NewUCString(cx, reinterpret_cast<jschar*>(unichars), unicharLength);
           if (str) {
             rval.setString(str);
             return true;
           }
--- a/layout/style/nsNthIndexCache.h
+++ b/layout/style/nsNthIndexCache.h
@@ -56,22 +56,17 @@ private:
   // If -2, needs to be computed.
   // If -1, needs to be computed but known not to be 1.
   // If 0, the node is not at any index in its parent.
   typedef int32_t CacheEntry;
 
   class SystemAllocPolicy {
   public:
     void *malloc_(size_t bytes) { return ::malloc(bytes); }
-
-    template <typename T>
-    T *pod_calloc(size_t numElems) {
-      return static_cast<T *>(::calloc(numElems, sizeof(T)));
-    }
-
+    void *calloc_(size_t bytes) { return ::calloc(bytes, 1); }
     void *realloc_(void *p, size_t bytes) { return ::realloc(p, bytes); }
     void free_(void *p) { ::free(p); }
     void reportAllocOverflow() const {}
   };
 
   typedef js::HashMap<nsIContent*, CacheEntry, js::DefaultHasher<nsIContent*>,
                       SystemAllocPolicy> Cache;
 
--- a/memory/replace/dmd/DMD.cpp
+++ b/memory/replace/dmd/DMD.cpp
@@ -104,39 +104,28 @@ public:
 
   static void* calloc_(size_t aSize)
   {
     void* p = gMallocTable->calloc(1, aSize);
     ExitOnFailure(p);
     return p;
   }
 
-  template <typename T>
-  static T* pod_calloc(size_t aNumElems)
-  {
-    void* p = gMallocTable->calloc(aNumElems, sizeof(T));
-    ExitOnFailure(p);
-    return (T*)p;
-  }
-
   // This realloc_ is the one we use for direct reallocs within DMD.
   static void* realloc_(void* aPtr, size_t aNewSize)
   {
     void* p = gMallocTable->realloc(aPtr, aNewSize);
     ExitOnFailure(p);
     return p;
   }
 
   // This realloc_ is required for this to be a JS container AllocPolicy.
-  template <typename T>
-  static T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
+  static void* realloc_(void* aPtr, size_t aOldSize, size_t aNewSize)
   {
-    if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
-      return nullptr;
-    return (T*)InfallibleAllocPolicy::realloc_((void *)aPtr, aNewSize * sizeof(T));
+    return InfallibleAllocPolicy::realloc_(aPtr, aNewSize);
   }
 
   static void* memalign_(size_t aAlignment, size_t aSize)
   {
     void* p = gMallocTable->memalign(aAlignment, aSize);
     ExitOnFailure(p);
     return p;
   }
--- a/mfbt/AllocPolicy.h
+++ b/mfbt/AllocPolicy.h
@@ -7,38 +7,36 @@
 /*
  * An allocation policy concept, usable for structures and algorithms to
  * control how memory is allocated and how failures are handled.
  */
 
 #ifndef mozilla_AllocPolicy_h
 #define mozilla_AllocPolicy_h
 
-#include "mozilla/NullPtr.h"
-#include "mozilla/TemplateLib.h"
-
 #include <stddef.h>
 #include <stdlib.h>
 
 namespace mozilla {
 
 /*
  * Allocation policies are used to implement the standard allocation behaviors
  * in a customizable way.  Additionally, custom behaviors may be added to these
  * behaviors, such as additionally reporting an error through an out-of-band
  * mechanism when OOM occurs.  The concept modeled here is as follows:
  *
  *  - public copy constructor, assignment, destructor
  *  - void* malloc_(size_t)
  *      Responsible for OOM reporting when null is returned.
- *  - template <typename T> T* pod_calloc(size_t)
+ *  - void* calloc_(size_t)
  *      Responsible for OOM reporting when null is returned.
- *  - template <typename T> T* pod_realloc(T*, size_t, size_t)
- *      Responsible for OOM reporting when null is returned.  The old allocation
- *      size is passed in, in addition to the new allocation size requested.
+ *  - void* realloc_(void*, size_t, size_t)
+ *      Responsible for OOM reporting when null is returned.  The *used* bytes
+ *      of the previous buffer is passed in (rather than the old allocation
+ *      size), in addition to the *new* allocation size requested.
  *  - void free_(void*)
  *  - void reportAllocOverflow() const
  *      Called on allocation overflow (that is, an allocation implicitly tried
  *      to allocate more than the available memory space -- think allocating an
  *      array of large-size objects, where N * size overflows) before null is
  *      returned.
  *
  * mfbt provides (and typically uses by default) only MallocAllocPolicy, which
@@ -52,28 +50,24 @@ namespace mozilla {
 class MallocAllocPolicy
 {
 public:
   void* malloc_(size_t aBytes)
   {
     return malloc(aBytes);
   }
 
-  template <typename T>
-  T* pod_calloc(size_t aNumElems)
+  void* calloc_(size_t aBytes)
   {
-    return static_cast<T*>(calloc(aNumElems, sizeof(T)));
+    return calloc(aBytes, 1);
   }
 
-  template <typename T>
-  T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
+  void* realloc_(void* aPtr, size_t aOldBytes, size_t aBytes)
   {
-    if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
-        return nullptr;
-    return static_cast<T*>(realloc(aPtr, aNewSize * sizeof(T)));
+    return realloc(aPtr, aBytes);
   }
 
   void free_(void* aPtr)
   {
     free(aPtr);
   }
 
   void reportAllocOverflow() const
--- a/mfbt/Vector.h
+++ b/mfbt/Vector.h
@@ -199,17 +199,19 @@ struct VectorImpl<T, N, AP, ThisVector, 
     }
   }
 
   static inline bool
   growTo(VectorBase<T, N, AP, ThisVector>& aV, size_t aNewCap)
   {
     MOZ_ASSERT(!aV.usingInlineStorage());
     MOZ_ASSERT(!CapacityHasExcessSpace<T>(aNewCap));
-    T* newbuf = aV.template pod_realloc<T>(aV.mBegin, aV.mCapacity, aNewCap);
+    size_t oldSize = sizeof(T) * aV.mCapacity;
+    size_t newSize = sizeof(T) * aNewCap;
+    T* newbuf = reinterpret_cast<T*>(aV.realloc_(aV.mBegin, oldSize, newSize));
     if (!newbuf) {
       return false;
     }
     aV.mBegin = newbuf;
     /* aV.mLength is unchanged. */
     aV.mCapacity = aNewCap;
     return true;
   }