Skip to content

Commit

Permalink
Bug 1033442 - Remove non-pod realloc from MallocProvider and AllocPol…
Browse files Browse the repository at this point in the history
…icy; r=jonco

--HG--
extra : rebase_source : 507ab10313127ffcbf905c42438882aa9074c38a
  • Loading branch information
Terrence Cole committed Aug 5, 2014
1 parent a0cb1d7 commit 6606ad7
Show file tree
Hide file tree
Showing 19 changed files with 98 additions and 63 deletions.
10 changes: 10 additions & 0 deletions js/public/Utility.h
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,16 @@ js_pod_calloc(size_t numElems)
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>
Expand Down
10 changes: 6 additions & 4 deletions js/src/ds/LifoAlloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -532,12 +532,14 @@ class LifoAllocPolicy
memset(p, 0, numElems * sizeof(T));
return p;
}
void *realloc_(void *p, size_t oldBytes, size_t bytes) {
uint8_t *n = pod_malloc<uint8_t>(bytes);
template <typename T>
T *pod_realloc(T *p, size_t oldSize, size_t newSize) {
T *n = pod_malloc<T>(newSize);
if (fb == Fallible && !n)
return nullptr;
memcpy(n, p, Min(oldBytes, bytes));
return static_cast<void *>(n);
JS_ASSERT(!(oldSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value));
memcpy(n, p, Min(oldSize * sizeof(T), newSize * sizeof(T)));
return n;
}
void free_(void *p) {
}
Expand Down
13 changes: 6 additions & 7 deletions js/src/gc/ForkJoinNursery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,16 +574,13 @@ ForkJoinNursery::reallocateSlots(JSObject *obj, HeapSlot *oldSlots,
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 static_cast<HeapSlot *>(cx_->realloc_(oldSlots, oldSize, newSize));
return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
}

if (!isInsideNewspace(oldSlots))
return reallocateHugeSlots(oldSlots, oldSize, newSize);
return reallocateHugeSlots(obj, oldSlots, oldCount, newCount);

// No-op if we're shrinking, we can't make use of the freed portion.
if (newCount < oldCount)
Expand All @@ -593,6 +590,7 @@ ForkJoinNursery::reallocateSlots(JSObject *obj, HeapSlot *oldSlots,
if (!newSlots)
return nullptr;

size_t oldSize = oldCount * sizeof(HeapSlot);
js_memcpy(newSlots, oldSlots, oldSize);
return newSlots;
}
Expand Down Expand Up @@ -638,9 +636,10 @@ ForkJoinNursery::allocateHugeSlots(JSObject *obj, size_t nslots)
}

HeapSlot *
ForkJoinNursery::reallocateHugeSlots(HeapSlot *oldSlots, uint32_t oldSize, uint32_t newSize)
ForkJoinNursery::reallocateHugeSlots(JSObject *obj, HeapSlot *oldSlots,
uint32_t oldCount, uint32_t newCount)
{
HeapSlot *newSlots = static_cast<HeapSlot *>(cx_->realloc_(oldSlots, oldSize, newSize));
HeapSlot *newSlots = obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
if (!newSlots)
return newSlots;

Expand Down
3 changes: 2 additions & 1 deletion js/src/gc/ForkJoinNursery.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ class ForkJoinNursery
// Reallocate an external slot array, unregister the old array and
// register the new array. If the allocation fails then leave
// everything unchanged.
HeapSlot *reallocateHugeSlots(HeapSlot *oldSlots, uint32_t oldSize, uint32_t newSize);
HeapSlot *reallocateHugeSlots(JSObject *obj, HeapSlot *oldSlots,
uint32_t oldCount, uint32_t newCount);

// Walk the list of registered slot arrays and free them all.
void sweepHugeSlots();
Expand Down
8 changes: 5 additions & 3 deletions js/src/jit/IonAllocPolicy.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,13 @@ class IonAllocPolicy
memset(p, 0, numElems * sizeof(T));
return p;
}
void *realloc_(void *p, size_t oldBytes, size_t bytes) {
void *n = static_cast<void *>(pod_malloc<uint8_t>(bytes));
template <typename T>
T *pod_realloc(T *p, size_t oldSize, size_t newSize) {
T *n = pod_malloc<T>(newSize);
if (!n)
return n;
memcpy(n, p, Min(oldBytes, bytes));
MOZ_ASSERT(!(oldSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value));
memcpy(n, p, Min(oldSize * sizeof(T), newSize * sizeof(T)));
return n;
}
void free_(void *p) {
Expand Down
4 changes: 2 additions & 2 deletions js/src/jit/MIR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1088,7 +1088,7 @@ 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 pod_realloc().
JS_ASSERT(numOperands() == 0);
#if DEBUG
capacity_ = length;
Expand Down Expand Up @@ -1246,7 +1246,7 @@ MPhi::addInputSlow(MDefinition *ins, bool *ptypeChange)
uint32_t index = inputs_.length();
bool performingRealloc = !inputs_.canAppendWithoutRealloc(1);

// Remove all MUses from all use lists, in case realloc_() moves.
// Remove all MUses from all use lists, in case pod_realloc() moves.
if (performingRealloc) {
for (uint32_t i = 0; i < index; i++) {
MUse *use = &inputs_[i];
Expand Down
2 changes: 1 addition & 1 deletion js/src/jit/MIR.h
Original file line number Diff line number Diff line change
Expand Up @@ -5566,7 +5566,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineListNode<MPhi>
// 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 pod_realloc().
// Prefer reserveLength() and addInput() instead, where possible.
bool addInputSlow(MDefinition *ins, bool *ptypeChange = nullptr);

Expand Down
11 changes: 7 additions & 4 deletions js/src/jsalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ class SystemAllocPolicy
public:
template <typename T> T *pod_malloc(size_t numElems) { return js_pod_malloc<T>(numElems); }
template <typename T> T *pod_calloc(size_t numElems) { return js_pod_calloc<T>(numElems); }
void *realloc_(void *p, size_t oldBytes, size_t bytes) { return js_realloc(p, bytes); }
template <typename T> T *pod_realloc(T *p, size_t oldSize, size_t newSize) {
return js_pod_realloc<T>(p, oldSize, newSize);
}
void free_(void *p) { js_free(p); }
void reportAllocOverflow() const {}
};
Expand Down Expand Up @@ -71,10 +73,11 @@ class TempAllocPolicy
return p;
}

void *realloc_(void *p, size_t oldBytes, size_t bytes) {
void *p2 = js_realloc(p, bytes);
template <typename T>
T *pod_realloc(T *prior, size_t oldSize, size_t newSize) {
T *p2 = js_pod_realloc<T>(prior, oldSize, newSize);
if (MOZ_UNLIKELY(!p2))
p2 = onOutOfMemory(p2, bytes);
p2 = static_cast<T *>(onOutOfMemory(p2, newSize * sizeof(T)));
return p2;
}

Expand Down
5 changes: 3 additions & 2 deletions js/src/jsapi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1415,11 +1415,12 @@ JS_malloc(JSContext *cx, size_t nbytes)
}

JS_PUBLIC_API(void *)
JS_realloc(JSContext *cx, void *p, size_t nbytes)
JS_realloc(JSContext *cx, void *p, size_t oldBytes, size_t newBytes)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
return cx->realloc_(p, nbytes);
return static_cast<void *>(cx->zone()->pod_realloc<uint8_t>(static_cast<uint8_t *>(p), oldBytes,
newBytes));
}

JS_PUBLIC_API(void)
Expand Down
2 changes: 1 addition & 1 deletion js/src/jsapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1858,7 +1858,7 @@ 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 nbytes);
JS_realloc(JSContext *cx, void *p, size_t oldBytes, size_t newBytes);

/*
* A wrapper for js_free(p) that may delay js_free(p) invocation as a
Expand Down
4 changes: 2 additions & 2 deletions js/src/shell/js.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1509,7 +1509,7 @@ ReadLine(JSContext *cx, unsigned argc, jsval *vp)
char *tmp;
bufsize *= 2;
if (bufsize > buflength) {
tmp = (char *) JS_realloc(cx, buf, bufsize);
tmp = static_cast<char *>(JS_realloc(cx, buf, bufsize / 2, bufsize));
} else {
JS_ReportOutOfMemory(cx);
tmp = nullptr;
Expand All @@ -1531,7 +1531,7 @@ ReadLine(JSContext *cx, unsigned argc, jsval *vp)
}

/* Shrink the buffer to the real size. */
char *tmp = static_cast<char*>(JS_realloc(cx, buf, buflength));
char *tmp = static_cast<char *>(JS_realloc(cx, buf, bufsize, buflength));
if (!tmp) {
JS_free(cx, buf);
return false;
Expand Down
2 changes: 1 addition & 1 deletion js/src/vm/ArrayBufferObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ ArrayBufferObject::class_constructor(JSContext *cx, unsigned argc, Value *vp)
static ArrayBufferObject::BufferContents
AllocateArrayBufferContents(JSContext *cx, uint32_t nbytes)
{
void *p = cx->runtime()->callocCanGC(nbytes);
uint8_t *p = cx->runtime()->pod_callocCanGC<uint8_t>(nbytes);
if (!p)
js_ReportOutOfMemory(cx);

Expand Down
27 changes: 14 additions & 13 deletions js/src/vm/MallocProvider.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,21 +130,22 @@ struct MallocProvider
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_realloc(T *prior, size_t oldSize, size_t newSize) {
return (T *)realloc_(prior, oldSize * sizeof(T), newSize * sizeof(T));
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;
}

JS_DECLARE_NEW_METHODS(new_, pod_malloc<uint8_t>, MOZ_ALWAYS_INLINE)
Expand Down
28 changes: 21 additions & 7 deletions js/src/vm/Runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -1385,18 +1385,28 @@ struct JSRuntime : public JS::shadow::Runtime,

static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;

void *callocCanGC(size_t bytes) {
void *p = (void *)pod_calloc<uint8_t>(bytes);
template <typename T>
T *pod_callocCanGC(size_t numElems) {
T *p = pod_calloc<T>(numElems);
if (MOZ_LIKELY(!!p))
return p;
return onOutOfMemoryCanGC(reinterpret_cast<void *>(1), bytes);
if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
reportAllocationOverflow();
return nullptr;
}
return (T *)onOutOfMemoryCanGC(reinterpret_cast<void *>(1), numElems * sizeof(T));
}

void *reallocCanGC(void *p, size_t bytes) {
void *p2 = realloc_(p, bytes);
template <typename T>
T *pod_reallocCanGC(T *p, size_t oldSize, size_t newSize) {
T *p2 = pod_realloc<T>(p, oldSize, newSize);
if (MOZ_LIKELY(!!p2))
return p2;
return onOutOfMemoryCanGC(p, bytes);
if (newSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
reportAllocationOverflow();
return nullptr;
}
return (T *)onOutOfMemoryCanGC(p, newSize * sizeof(T));
}
};

Expand Down Expand Up @@ -1676,7 +1686,11 @@ class RuntimeAllocPolicy
return runtime->pod_calloc<T>(numElems);
}

void *realloc_(void *p, size_t bytes) { return runtime->realloc_(p, bytes); }
template <typename T>
T *pod_realloc(T *p, size_t oldSize, size_t newSize) {
return runtime->pod_realloc<T>(p, oldSize, newSize);
}

void free_(void *p) { js_free(p); }
void reportAllocOverflow() const {}
};
Expand Down
3 changes: 1 addition & 2 deletions js/src/vm/StringBuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ ExtractWellSized(ExclusiveContext *cx, Buffer &cb)
/* 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) {
size_t bytes = sizeof(CharT) * (length + 1);
CharT *tmp = (CharT *)cx->realloc_(buf, bytes);
CharT *tmp = cx->zone()->pod_realloc<CharT>(buf, capacity, length + 1);
if (!tmp) {
js_free(buf);
return nullptr;
Expand Down
4 changes: 2 additions & 2 deletions js/xpconnect/src/XPCLocale.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,8 @@ struct XPCLocaleCallbacks : public JSLocaleCallbacks
// nsIUnicodeDecoder::Convert may use fewer than srcLength PRUnichars
if (unicharLength + 1 < srcLength + 1) {
char16_t *shrunkUnichars =
(char16_t *)JS_realloc(cx, unichars,
(unicharLength + 1) * sizeof(char16_t));
static_cast<char16_t *>(JS_realloc(cx, unichars, srcLength + 1,
unicharLength + 1));
if (shrunkUnichars)
unichars = shrunkUnichars;
}
Expand Down
7 changes: 5 additions & 2 deletions memory/replace/dmd/DMD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,12 @@ class InfallibleAllocPolicy
}

// This realloc_ is required for this to be a JS container AllocPolicy.
static void* realloc_(void* aPtr, size_t aOldSize, size_t aNewSize)
template <typename T>
static T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
{
return InfallibleAllocPolicy::realloc_(aPtr, aNewSize);
if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
return nullptr;
return (T*)InfallibleAllocPolicy::realloc_((void *)aPtr, aNewSize * sizeof(T));
}

static void* memalign_(size_t aAlignment, size_t aSize)
Expand Down
14 changes: 8 additions & 6 deletions mfbt/AllocPolicy.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@ namespace mozilla {
* Responsible for OOM reporting when null is returned.
* - template <typename T> T* pod_calloc(size_t)
* Responsible for OOM reporting when null is returned.
* - 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.
* - 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 free_(void*)
* - void reportAllocOverflow() const
* Called on allocation overflow (that is, an allocation implicitly tried
Expand Down Expand Up @@ -67,9 +66,12 @@ class MallocAllocPolicy
return static_cast<T*>(calloc(aNumElems, sizeof(T)));
}

void* realloc_(void* aPtr, size_t aOldBytes, size_t aBytes)
template <typename T>
T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
{
return realloc(aPtr, aBytes);
if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
return nullptr;
return static_cast<T*>(realloc(aPtr, aNewSize * sizeof(T)));
}

void free_(void* aPtr)
Expand Down
4 changes: 1 addition & 3 deletions mfbt/Vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,7 @@ struct VectorImpl<T, N, AP, ThisVector, true>
{
MOZ_ASSERT(!aV.usingInlineStorage());
MOZ_ASSERT(!CapacityHasExcessSpace<T>(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));
T* newbuf = aV.template pod_realloc<T>(aV.mBegin, aV.mCapacity, aNewCap);
if (!newbuf) {
return false;
}
Expand Down

0 comments on commit 6606ad7

Please sign in to comment.