Backed out changesets 6ee4b6cc240c, a818fd0874fe, and 70803a5f4683 (bug 1033442) for multiple crashtest oranges.

This commit is contained in:
Ryan VanderMeulen 2014-08-08 21:54:58 -04:00
parent 3027419040
commit 7d00738b7a
29 changed files with 156 additions and 203 deletions

View File

@ -1067,7 +1067,7 @@ class HashTable : private AllocPolicy
"newly-calloc'd tables have to be considered empty"); "newly-calloc'd tables have to be considered empty");
static_assert(sMaxCapacity <= SIZE_MAX / sizeof(Entry), static_assert(sMaxCapacity <= SIZE_MAX / sizeof(Entry),
"would overflow allocating max number of entries"); "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) static void destroyTable(AllocPolicy &alloc, Entry *oldTable, uint32_t capacity)

View File

@ -563,16 +563,6 @@ js_pod_calloc(size_t numElems)
return (T *)js_calloc(numElems * sizeof(T)); 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 { namespace js {
template<typename T> template<typename T>

View File

@ -519,24 +519,18 @@ class LifoAllocPolicy
void *malloc_(size_t bytes) { void *malloc_(size_t bytes) {
return fb == Fallible ? alloc_.alloc(bytes) : alloc_.allocInfallible(bytes); return fb == Fallible ? alloc_.alloc(bytes) : alloc_.allocInfallible(bytes);
} }
template <typename T> void *calloc_(size_t bytes) {
T *pod_calloc(size_t numElems) { void *p = malloc_(bytes);
if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
return nullptr;
T *p = (T *)malloc_(numElems * sizeof(T));
if (fb == Fallible && !p) if (fb == Fallible && !p)
return nullptr; return nullptr;
memset(p, 0, numElems * sizeof(T)); memset(p, 0, bytes);
return p; return p;
} }
template <typename T> void *realloc_(void *p, size_t oldBytes, size_t bytes) {
T *pod_realloc(T *p, size_t oldSize, size_t newSize) { void *n = malloc_(bytes);
if (newSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
return nullptr;
T *n = (T *)malloc_(newSize * sizeof(T));
if (fb == Fallible && !n) if (fb == Fallible && !n)
return nullptr; return nullptr;
memcpy(n, p, Min(oldSize * sizeof(T), newSize * sizeof(T))); memcpy(n, p, Min(oldBytes, bytes));
return n; return n;
} }
void free_(void *p) { void free_(void *p) {

View File

@ -585,13 +585,16 @@ ForkJoinNursery::reallocateSlots(JSObject *obj, HeapSlot *oldSlots,
if (newCount & mozilla::tl::MulOverflowMask<sizeof(HeapSlot)>::value) if (newCount & mozilla::tl::MulOverflowMask<sizeof(HeapSlot)>::value)
return nullptr; return nullptr;
size_t oldSize = oldCount * sizeof(HeapSlot);
size_t newSize = newCount * sizeof(HeapSlot);
if (!isInsideNewspace(obj)) { if (!isInsideNewspace(obj)) {
JS_ASSERT_IF(oldSlots, !isInsideNewspace(oldSlots)); 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)) 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. // No-op if we're shrinking, we can't make use of the freed portion.
if (newCount < oldCount) if (newCount < oldCount)
@ -601,7 +604,6 @@ ForkJoinNursery::reallocateSlots(JSObject *obj, HeapSlot *oldSlots,
if (!newSlots) if (!newSlots)
return nullptr; return nullptr;
size_t oldSize = oldCount * sizeof(HeapSlot);
js_memcpy(newSlots, oldSlots, oldSize); js_memcpy(newSlots, oldSlots, oldSize);
return newSlots; return newSlots;
} }
@ -648,10 +650,9 @@ ForkJoinNursery::allocateHugeSlots(size_t nslots)
} }
HeapSlot * HeapSlot *
ForkJoinNursery::reallocateHugeSlots(JSObject *obj, HeapSlot *oldSlots, ForkJoinNursery::reallocateHugeSlots(HeapSlot *oldSlots, uint32_t oldSize, uint32_t newSize)
uint32_t oldCount, uint32_t newCount)
{ {
HeapSlot *newSlots = obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount); HeapSlot *newSlots = static_cast<HeapSlot *>(cx_->realloc_(oldSlots, oldSize, newSize));
if (!newSlots) if (!newSlots)
return newSlots; return newSlots;

View File

@ -210,8 +210,7 @@ class ForkJoinNursery
// Reallocate an external slot array, unregister the old array and // Reallocate an external slot array, unregister the old array and
// register the new array. If the allocation fails then leave // register the new array. If the allocation fails then leave
// everything unchanged. // everything unchanged.
HeapSlot *reallocateHugeSlots(JSObject *obj, HeapSlot *oldSlots, HeapSlot *reallocateHugeSlots(HeapSlot *oldSlots, uint32_t oldSize, uint32_t newSize);
uint32_t oldCount, uint32_t newCount);
// Walk the list of registered slot arrays and free them all. // Walk the list of registered slot arrays and free them all.
void sweepHugeSlots(); void sweepHugeSlots();

View File

@ -103,24 +103,17 @@ class IonAllocPolicy
void *malloc_(size_t bytes) { void *malloc_(size_t bytes) {
return alloc_.allocate(bytes); return alloc_.allocate(bytes);
} }
template <typename T> void *calloc_(size_t bytes) {
T *pod_calloc(size_t numElems) { void *p = alloc_.allocate(bytes);
if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value)
return nullptr;
T *p = (T *)alloc_.allocate(numElems * sizeof(T));
if (p) if (p)
memset(p, 0, numElems * sizeof(T)); memset(p, 0, bytes);
return p; return p;
} }
template <typename T> void *realloc_(void *p, size_t oldBytes, size_t bytes) {
T *pod_realloc(T *p, size_t oldSize, size_t newSize) { void *n = malloc_(bytes);
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));
if (!n) if (!n)
return n; return n;
memcpy(n, p, Min(oldSize * sizeof(T), newSize * sizeof(T))); memcpy(n, p, Min(oldBytes, bytes));
return n; return n;
} }
void free_(void *p) { void free_(void *p) {
@ -139,6 +132,19 @@ class OldIonAllocPolicy
void *malloc_(size_t bytes) { void *malloc_(size_t bytes) {
return GetIonContext()->temp->allocate(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 free_(void *p) {
} }
void reportAllocOverflow() const { void reportAllocOverflow() const {

View File

@ -1054,7 +1054,7 @@ MPhi::reserveLength(size_t length)
{ {
// Initializes a new MPhi to have an Operand vector of at least the given // Initializes a new MPhi to have an Operand vector of at least the given
// capacity. This permits use of addInput() instead of addInputSlow(), the // 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); JS_ASSERT(numOperands() == 0);
#if DEBUG #if DEBUG
capacity_ = length; capacity_ = length;

View File

@ -5250,7 +5250,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineListNode<MPhi>
// Use only if capacity has been reserved by reserveLength // Use only if capacity has been reserved by reserveLength
void addInput(MDefinition *ins); 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. // Prefer reserveLength() and addInput() instead, where possible.
bool addInputSlow(MDefinition *ins, bool *ptypeChange = nullptr); bool addInputSlow(MDefinition *ins, bool *ptypeChange = nullptr);

View File

@ -52,7 +52,7 @@ RematerializedFrame::New(ThreadSafeContext *cx, uint8_t *top, InlineFrameIterato
(numActualArgs + iter.script()->nfixed()) * sizeof(Value) - (numActualArgs + iter.script()->nfixed()) * sizeof(Value) -
sizeof(Value); // 1 Value included in sizeof(RematerializedFrame) sizeof(Value); // 1 Value included in sizeof(RematerializedFrame)
void *buf = cx->pod_calloc<uint8_t>(numBytes); void *buf = cx->calloc_(numBytes);
if (!buf) if (!buf)
return nullptr; return nullptr;

View File

@ -26,10 +26,8 @@ class SystemAllocPolicy
{ {
public: public:
void *malloc_(size_t bytes) { return js_malloc(bytes); } void *malloc_(size_t bytes) { return js_malloc(bytes); }
template <typename T> T *pod_calloc(size_t numElems) { return js_pod_calloc<T>(numElems); } void *calloc_(size_t bytes) { return js_calloc(bytes); }
template <typename T> T *pod_realloc(T *p, size_t oldSize, size_t newSize) { void *realloc_(void *p, size_t oldBytes, size_t bytes) { return js_realloc(p, bytes); }
return js_pod_realloc<T>(p, oldSize, newSize);
}
void free_(void *p) { js_free(p); } void free_(void *p) { js_free(p); }
void reportAllocOverflow() const {} void reportAllocOverflow() const {}
}; };
@ -64,19 +62,17 @@ class TempAllocPolicy
return p; return p;
} }
template <typename T> void *calloc_(size_t bytes) {
T *pod_calloc(size_t numElems) { void *p = js_calloc(bytes);
T *p = js_pod_calloc<T>(numElems);
if (MOZ_UNLIKELY(!p)) if (MOZ_UNLIKELY(!p))
p = (T *)onOutOfMemory(reinterpret_cast<void *>(1), numElems * sizeof(T)); p = onOutOfMemory(nullptr, bytes);
return p; return p;
} }
template <typename T> void *realloc_(void *p, size_t oldBytes, size_t bytes) {
T *pod_realloc(T *prior, size_t oldSize, size_t newSize) { void *p2 = js_realloc(p, bytes);
T *p2 = js_pod_realloc<T>(prior, oldSize, newSize);
if (MOZ_UNLIKELY(!p2)) if (MOZ_UNLIKELY(!p2))
p2 = (T *)onOutOfMemory(p2, newSize * sizeof(T)); p2 = onOutOfMemory(p2, bytes);
return p2; return p2;
} }

View File

@ -1439,12 +1439,11 @@ JS_malloc(JSContext *cx, size_t nbytes)
} }
JS_PUBLIC_API(void *) 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)
{ {
AssertHeapIsIdle(cx); AssertHeapIsIdle(cx);
CHECK_REQUEST(cx); CHECK_REQUEST(cx);
return static_cast<void *>(cx->zone()->pod_realloc<uint8_t>(static_cast<uint8_t *>(p), oldBytes, return cx->realloc_(p, nbytes);
newBytes));
} }
JS_PUBLIC_API(void) JS_PUBLIC_API(void)

View File

@ -1861,7 +1861,7 @@ extern JS_PUBLIC_API(void *)
JS_malloc(JSContext *cx, size_t nbytes); JS_malloc(JSContext *cx, size_t nbytes);
extern JS_PUBLIC_API(void *) 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 * A wrapper for js_free(p) that may delay js_free(p) invocation as a

View File

@ -982,6 +982,8 @@ class ContextAllocPolicy
MOZ_IMPLICIT ContextAllocPolicy(ThreadSafeContext *cx) : cx_(cx) {} MOZ_IMPLICIT ContextAllocPolicy(ThreadSafeContext *cx) : cx_(cx) {}
ThreadSafeContext *context() const { return cx_; } ThreadSafeContext *context() const { return cx_; }
void *malloc_(size_t bytes) { return cx_->malloc_(bytes); } 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 free_(void *p) { js_free(p); }
void reportAllocOverflow() const { js_ReportAllocationOverflow(cx_); } void reportAllocOverflow() const { js_ReportAllocationOverflow(cx_); }
}; };

View File

@ -3443,7 +3443,7 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
size_t numBytes = sizeof(TypeNewScript) size_t numBytes = sizeof(TypeNewScript)
+ (initializerList.length() * sizeof(TypeNewScript::Initializer)); + (initializerList.length() * sizeof(TypeNewScript::Initializer));
TypeNewScript *newScript = (TypeNewScript *) type->zone()->pod_calloc<uint8_t>(numBytes); TypeNewScript *newScript = (TypeNewScript *) cx->calloc_(numBytes);
if (!newScript) if (!newScript)
return; return;
@ -3606,7 +3606,7 @@ JSScript::makeTypes(JSContext *cx)
unsigned count = TypeScript::NumTypeSets(this); unsigned count = TypeScript::NumTypeSets(this);
TypeScript *typeScript = (TypeScript *) TypeScript *typeScript = (TypeScript *)
zone()->pod_calloc<uint8_t>(TypeScript::SizeIncludingTypeArray(count)); cx->calloc_(TypeScript::SizeIncludingTypeArray(count));
if (!typeScript) if (!typeScript)
return false; return false;

View File

@ -1784,7 +1784,7 @@ js_NewGenerator(JSContext *cx, const InterpreterRegs &stackRegs)
JS_ASSERT(nbytes % sizeof(Value) == 0); JS_ASSERT(nbytes % sizeof(Value) == 0);
JS_STATIC_ASSERT(sizeof(InterpreterFrame) % sizeof(HeapValue) == 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) if (!gen)
return nullptr; return nullptr;

View File

@ -1138,8 +1138,8 @@ JSScript::initScriptCounts(JSContext *cx)
for (jsbytecode *pc = code(); pc < codeEnd(); pc += GetBytecodeLength(pc)) for (jsbytecode *pc = code(); pc < codeEnd(); pc += GetBytecodeLength(pc))
n += PCCounts::numCounts(JSOp(*pc)); n += PCCounts::numCounts(JSOp(*pc));
size_t nbytes = (length() * sizeof(PCCounts)) + (n * sizeof(double)); size_t bytes = (length() * sizeof(PCCounts)) + (n * sizeof(double));
uint8_t *base = zone()->pod_calloc<uint8_t>(nbytes); char *base = (char *) cx->calloc_(bytes);
if (!base) if (!base)
return false; return false;
@ -1155,7 +1155,7 @@ JSScript::initScriptCounts(JSContext *cx)
compartment()->scriptCountsMap = map; compartment()->scriptCountsMap = map;
} }
uint8_t *cursor = base; char *cursor = base;
ScriptCounts scriptCounts; ScriptCounts scriptCounts;
scriptCounts.pcCountsVector = (PCCounts *) cursor; scriptCounts.pcCountsVector = (PCCounts *) cursor;
@ -1177,7 +1177,7 @@ JSScript::initScriptCounts(JSContext *cx)
} }
hasScriptCounts_ = true; // safe to set this; we can't fail after this point 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. */ /* Enable interrupts in any interpreter frames running on this script. */
for (ActivationIterator iter(cx->runtime()); !iter.done(); ++iter) { for (ActivationIterator iter(cx->runtime()); !iter.done(); ++iter) {
@ -2358,15 +2358,14 @@ JSScript::Create(ExclusiveContext *cx, HandleObject enclosingScope, bool savedCa
} }
static inline uint8_t * static inline uint8_t *
AllocScriptData(JS::Zone *zone, size_t size) AllocScriptData(ExclusiveContext *cx, size_t size)
{ {
if (!size) uint8_t *data = static_cast<uint8_t *>(cx->calloc_(JS_ROUNDUP(size, sizeof(Value))));
return nullptr;
uint8_t *data = zone->pod_calloc<uint8_t>(JS_ROUNDUP(size, sizeof(Value)));
if (!data) if (!data)
return nullptr; 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; return data;
} }
@ -2377,9 +2376,13 @@ JSScript::partiallyInit(ExclusiveContext *cx, HandleScript script, uint32_t ncon
{ {
size_t size = ScriptDataSize(script->bindings.count(), nconsts, nobjects, nregexps, ntrynotes, size_t size = ScriptDataSize(script->bindings.count(), nconsts, nobjects, nregexps, ntrynotes,
nblockscopes); nblockscopes);
script->data = AllocScriptData(script->zone(), size); if (size > 0) {
if (size && !script->data) script->data = AllocScriptData(cx, size);
if (!script->data)
return false; return false;
} else {
script->data = nullptr;
}
script->dataSize_ = size; script->dataSize_ = size;
JS_ASSERT(nTypeSets <= UINT16_MAX); JS_ASSERT(nTypeSets <= UINT16_MAX);
@ -2887,8 +2890,8 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
/* Script data */ /* Script data */
size_t size = src->dataSize(); size_t size = src->dataSize();
uint8_t *data = AllocScriptData(cx->zone(), size); uint8_t *data = AllocScriptData(cx, size);
if (size && !data) if (!data)
return nullptr; return nullptr;
/* Bindings */ /* Bindings */
@ -3149,7 +3152,7 @@ JSScript::ensureHasDebugScript(JSContext *cx)
return true; return true;
size_t nbytes = offsetof(DebugScript, breakpoints) + length() * sizeof(BreakpointSite*); 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) if (!debug)
return false; return false;

View File

@ -499,7 +499,7 @@ ReadEvalPrintLoop(JSContext *cx, Handle<JSObject*> global, FILE *in, FILE *out,
* coincides with the end of a line. * coincides with the end of a line.
*/ */
int startline = lineno; int startline = lineno;
typedef Vector<char, 32> CharBuffer; typedef Vector<char, 32, ContextAllocPolicy> CharBuffer;
CharBuffer buffer(cx); CharBuffer buffer(cx);
do { do {
ScheduleWatchdog(cx->runtime(), -1); ScheduleWatchdog(cx->runtime(), -1);
@ -1507,7 +1507,7 @@ ReadLine(JSContext *cx, unsigned argc, jsval *vp)
char *tmp; char *tmp;
bufsize *= 2; bufsize *= 2;
if (bufsize > buflength) { if (bufsize > buflength) {
tmp = static_cast<char *>(JS_realloc(cx, buf, bufsize / 2, bufsize)); tmp = (char *) JS_realloc(cx, buf, bufsize);
} else { } else {
JS_ReportOutOfMemory(cx); JS_ReportOutOfMemory(cx);
tmp = nullptr; tmp = nullptr;
@ -1529,7 +1529,7 @@ ReadLine(JSContext *cx, unsigned argc, jsval *vp)
} }
/* Shrink the buffer to the real size. */ /* 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) { if (!tmp) {
JS_free(cx, buf); JS_free(cx, buf);
return false; return false;

View File

@ -275,22 +275,17 @@ ArrayBufferObject::class_constructor(JSContext *cx, unsigned argc, Value *vp)
static void * static void *
AllocateArrayBufferContents(JSContext *maybecx, uint32_t nbytes, void *oldptr = nullptr, size_t oldnbytes = 0) 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 is given, then we need to do a realloc
if (oldptr) { if (oldptr) {
uint8_t *prior = static_cast<uint8_t *>(oldptr); p = maybecx ? maybecx->runtime()->reallocCanGC(oldptr, nbytes) : js_realloc(oldptr, nbytes);
p = maybecx
? maybecx->runtime()->pod_reallocCanGC<uint8_t>(prior, oldnbytes, nbytes)
: js_pod_realloc<uint8_t>(prior, oldnbytes, nbytes);
// if we grew the array, we need to set the new bytes to 0 // if we grew the array, we need to set the new bytes to 0
if (p && nbytes > oldnbytes) if (p && nbytes > oldnbytes)
memset(p + oldnbytes, 0, nbytes - oldnbytes); memset(reinterpret_cast<uint8_t *>(p) + oldnbytes, 0, nbytes - oldnbytes);
} else { } else {
p = maybecx p = maybecx ? maybecx->runtime()->callocCanGC(nbytes) : js_calloc(nbytes);
? maybecx->runtime()->pod_callocCanGC<uint8_t>(nbytes)
: js_pod_calloc<uint8_t>(nbytes);
} }
if (!p && maybecx) if (!p && maybecx)

View File

@ -23,10 +23,6 @@
* - TempAllocPolicy: Adds automatic error reporting to the provided * - TempAllocPolicy: Adds automatic error reporting to the provided
* Context when allocations fail. * 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 * - MallocProvider. A mixin base class that handles automatically updating
* the GC's state in response to allocations that are tied to a GC lifetime * 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 * or are for a particular GC purpose. These allocators must only be used
@ -59,6 +55,37 @@ struct MallocProvider
return MOZ_LIKELY(!!p) ? p : client->onOutOfMemory(nullptr, 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> template <class T>
T *pod_malloc() { T *pod_malloc() {
return (T *)malloc_(sizeof(T)); return (T *)malloc_(sizeof(T));
@ -66,14 +93,7 @@ struct MallocProvider
template <class T> template <class T>
T *pod_calloc() { T *pod_calloc() {
Client *client = static_cast<Client *>(this); return (T *)calloc_(sizeof(T));
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;
} }
template <class T> template <class T>
@ -94,47 +114,30 @@ struct MallocProvider
template <class T> template <class T>
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) { if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
Client *client = static_cast<Client *>(this); Client *client = static_cast<Client *>(this);
client->reportAllocationOverflow(); client->reportAllocationOverflow();
return nullptr; return nullptr;
} }
Client *client = static_cast<Client *>(this); return (T *)calloc_(numElems * sizeof(T));
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;
} }
template <class T> template <class T>
mozilla::UniquePtr<T[], JS::FreePolicy> mozilla::UniquePtr<T[], JS::FreePolicy>
make_zeroed_pod_array(size_t numElems) { make_zeroed_pod_array(size_t numElems,
return mozilla::UniquePtr<T[], JS::FreePolicy>(pod_calloc<T>(numElems)); JSCompartment *comp = nullptr,
JSContext *cx = nullptr)
{
return mozilla::UniquePtr<T[], JS::FreePolicy>(pod_calloc<T>(numElems, comp, cx));
} }
template <class T> template <class T>
T *pod_realloc(T *prior, size_t oldSize, size_t newSize) { T *pod_realloc(T *prior, size_t oldSize, size_t newSize) {
Client *client = static_cast<Client *>(this); 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_, malloc_, MOZ_ALWAYS_INLINE) JS_DECLARE_NEW_METHODS(new_, malloc_, MOZ_ALWAYS_INLINE)
JS_DECLARE_MAKE_METHODS(make_unique, new_, MOZ_ALWAYS_INLINE) JS_DECLARE_MAKE_METHODS(make_unique, new_, MOZ_ALWAYS_INLINE)
}; };

View File

@ -1371,28 +1371,18 @@ struct JSRuntime : public JS::shadow::Runtime,
static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024; static const unsigned LARGE_ALLOCATION = 25 * 1024 * 1024;
template <typename T> void *callocCanGC(size_t bytes) {
T *pod_callocCanGC(size_t numElems) { void *p = calloc_(bytes);
T *p = pod_calloc<T>(numElems);
if (MOZ_LIKELY(!!p)) if (MOZ_LIKELY(!!p))
return p; return p;
if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) { return onOutOfMemoryCanGC(reinterpret_cast<void *>(1), bytes);
reportAllocationOverflow();
return nullptr;
}
return (T *)onOutOfMemoryCanGC(reinterpret_cast<void *>(1), numElems * sizeof(T));
} }
template <typename T> void *reallocCanGC(void *p, size_t bytes) {
T *pod_reallocCanGC(T *p, size_t oldSize, size_t newSize) { void *p2 = realloc_(p, bytes);
T *p2 = pod_realloc<T>(p, oldSize, newSize);
if (MOZ_LIKELY(!!p2)) if (MOZ_LIKELY(!!p2))
return p2; return p2;
if (newSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) { return onOutOfMemoryCanGC(p, bytes);
reportAllocationOverflow();
return nullptr;
}
return (T *)onOutOfMemoryCanGC(p, newSize * sizeof(T));
} }
}; };
@ -1662,17 +1652,8 @@ class RuntimeAllocPolicy
public: public:
MOZ_IMPLICIT RuntimeAllocPolicy(JSRuntime *rt) : runtime(rt) {} MOZ_IMPLICIT RuntimeAllocPolicy(JSRuntime *rt) : runtime(rt) {}
void *malloc_(size_t bytes) { return runtime->malloc_(bytes); } void *malloc_(size_t bytes) { return runtime->malloc_(bytes); }
void *calloc_(size_t bytes) { return runtime->calloc_(bytes); }
template <typename T> void *realloc_(void *p, size_t bytes) { return runtime->realloc_(p, bytes); }
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 free_(void *p) { js_free(p); } void free_(void *p) { js_free(p); }
void reportAllocOverflow() const {} void reportAllocOverflow() const {}
}; };

View File

@ -45,10 +45,10 @@ ShapeTable::init(ThreadSafeContext *cx, Shape *lastProp)
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. * without OOM reporting. See ShapeTable::change.
*/ */
entries = cx->pod_calloc<Shape *>(JS_BIT(sizeLog2)); entries = (Shape **) cx->calloc_(sizeOfEntries(JS_BIT(sizeLog2)));
if (!entries) if (!entries)
return false; return false;
@ -260,7 +260,7 @@ ShapeTable::change(int log2Delta, ThreadSafeContext *cx)
int newlog2 = oldlog2 + log2Delta; int newlog2 = oldlog2 + log2Delta;
uint32_t oldsize = JS_BIT(oldlog2); uint32_t oldsize = JS_BIT(oldlog2);
uint32_t newsize = JS_BIT(newlog2); uint32_t newsize = JS_BIT(newlog2);
Shape **newTable = cx->pod_calloc<Shape *>(newsize); Shape **newTable = (Shape **) cx->calloc_(sizeOfEntries(newsize));
if (!newTable) if (!newTable)
return false; return false;

View File

@ -161,6 +161,9 @@ struct ShapeTable {
/* By definition, hashShift = HASH_BITS - log2(capacity). */ /* By definition, hashShift = HASH_BITS - log2(capacity). */
uint32_t capacity() const { return JS_BIT(HASH_BITS - hashShift); } 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 * This counts the ShapeTable object itself (which must be
* heap-allocated) and its |entries| array. * heap-allocated) and its |entries| array.
@ -184,7 +187,7 @@ struct ShapeTable {
/* /*
* NB: init and change are fallible but do not report OOM, so callers can * 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. * order to update the malloc counter on success.
*/ */
bool init(ThreadSafeContext *cx, Shape *lastProp); bool init(ThreadSafeContext *cx, Shape *lastProp);

View File

@ -28,7 +28,8 @@ ExtractWellSized(ExclusiveContext *cx, Buffer &cb)
/* For medium/big buffers, avoid wasting more than 1/4 of the memory. */ /* For medium/big buffers, avoid wasting more than 1/4 of the memory. */
JS_ASSERT(capacity >= length); JS_ASSERT(capacity >= length);
if (length > Buffer::sMaxInlineStorage && capacity - length > length / 4) { 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) { if (!tmp) {
js_free(buf); js_free(buf);
return nullptr; return nullptr;

View File

@ -33,8 +33,8 @@ class StringBuffer
* The Vector's buffer is taken by the new string so use * The Vector's buffer is taken by the new string so use
* ContextAllocPolicy. * ContextAllocPolicy.
*/ */
typedef Vector<Latin1Char, 64> Latin1CharBuffer; typedef Vector<Latin1Char, 64, ContextAllocPolicy> Latin1CharBuffer;
typedef Vector<jschar, 32> TwoByteCharBuffer; typedef Vector<jschar, 32, ContextAllocPolicy> TwoByteCharBuffer;
ExclusiveContext *cx; ExclusiveContext *cx;

View File

@ -213,8 +213,8 @@ private:
// nsIUnicodeDecoder::Convert may use fewer than srcLength PRUnichars // nsIUnicodeDecoder::Convert may use fewer than srcLength PRUnichars
if (unicharLength + 1 < srcLength + 1) { if (unicharLength + 1 < srcLength + 1) {
char16_t *shrunkUnichars = char16_t *shrunkUnichars =
static_cast<char16_t *>(JS_realloc(cx, unichars, srcLength + 1, (char16_t *)JS_realloc(cx, unichars,
unicharLength + 1)); (unicharLength + 1) * sizeof(char16_t));
if (shrunkUnichars) if (shrunkUnichars)
unichars = shrunkUnichars; unichars = shrunkUnichars;
} }

View File

@ -61,12 +61,7 @@ private:
class SystemAllocPolicy { class SystemAllocPolicy {
public: public:
void *malloc_(size_t bytes) { return ::malloc(bytes); } void *malloc_(size_t bytes) { return ::malloc(bytes); }
void *calloc_(size_t bytes) { return ::calloc(bytes, 1); }
template <typename T>
T *pod_calloc(size_t numElems) {
return static_cast<T *>(::calloc(numElems, sizeof(T)));
}
void *realloc_(void *p, size_t bytes) { return ::realloc(p, bytes); } void *realloc_(void *p, size_t bytes) { return ::realloc(p, bytes); }
void free_(void *p) { ::free(p); } void free_(void *p) { ::free(p); }
void reportAllocOverflow() const {} void reportAllocOverflow() const {}

View File

@ -109,14 +109,6 @@ public:
return 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. // This realloc_ is the one we use for direct reallocs within DMD.
static void* realloc_(void* aPtr, size_t aNewSize) static void* realloc_(void* aPtr, size_t aNewSize)
{ {
@ -126,12 +118,9 @@ public:
} }
// This realloc_ is required for this to be a JS container AllocPolicy. // This realloc_ is required for this to be a JS container AllocPolicy.
template <typename T> static void* realloc_(void* aPtr, size_t aOldSize, size_t aNewSize)
static T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
{ {
if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) return InfallibleAllocPolicy::realloc_(aPtr, aNewSize);
return nullptr;
return (T*)InfallibleAllocPolicy::realloc_((void *)aPtr, aNewSize * sizeof(T));
} }
static void* memalign_(size_t aAlignment, size_t aSize) static void* memalign_(size_t aAlignment, size_t aSize)

View File

@ -12,9 +12,6 @@
#ifndef mozilla_AllocPolicy_h #ifndef mozilla_AllocPolicy_h
#define mozilla_AllocPolicy_h #define mozilla_AllocPolicy_h
#include "mozilla/NullPtr.h"
#include "mozilla/TemplateLib.h"
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
@ -29,11 +26,12 @@ namespace mozilla {
* - public copy constructor, assignment, destructor * - public copy constructor, assignment, destructor
* - void* malloc_(size_t) * - void* malloc_(size_t)
* Responsible for OOM reporting when null is returned. * 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. * Responsible for OOM reporting when null is returned.
* - template <typename T> T* pod_realloc(T*, size_t, size_t) * - void* realloc_(void*, size_t, size_t)
* Responsible for OOM reporting when null is returned. The old allocation * Responsible for OOM reporting when null is returned. The *used* bytes
* size is passed in, in addition to the new allocation size requested. * 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 free_(void*)
* - void reportAllocOverflow() const * - void reportAllocOverflow() const
* Called on allocation overflow (that is, an allocation implicitly tried * Called on allocation overflow (that is, an allocation implicitly tried
@ -57,18 +55,14 @@ public:
return malloc(aBytes); return malloc(aBytes);
} }
template <typename T> void* calloc_(size_t aBytes)
T* pod_calloc(size_t aNumElems)
{ {
return static_cast<T*>(calloc(aNumElems, sizeof(T))); return calloc(aBytes, 1);
} }
template <typename T> void* realloc_(void* aPtr, size_t aOldBytes, size_t aBytes)
T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
{ {
if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) return realloc(aPtr, aBytes);
return nullptr;
return static_cast<T*>(realloc(aPtr, aNewSize * sizeof(T)));
} }
void free_(void* aPtr) void free_(void* aPtr)

View File

@ -204,7 +204,9 @@ struct VectorImpl<T, N, AP, ThisVector, true>
{ {
MOZ_ASSERT(!aV.usingInlineStorage()); MOZ_ASSERT(!aV.usingInlineStorage());
MOZ_ASSERT(!CapacityHasExcessSpace<T>(aNewCap)); 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) { if (!newbuf) {
return false; return false;
} }