Bug 1033442 - Add allocation functions to Cell to make it more obvious which allocator to use; r=jonco

This commit is contained in:
Terrence Cole 2014-08-08 17:00:46 -07:00
parent d5746df1f6
commit e4c65dd6d7
15 changed files with 109 additions and 65 deletions

View File

@ -304,6 +304,29 @@ class BarrieredCell : public gc::Cell
static void writeBarrierPost(T *thing, void *cellp) {}
static void writeBarrierPostRelocate(T *thing, void *cellp) {}
static void writeBarrierPostRemove(T *thing, void *cellp) {}
template <typename S>
S *pod_malloc(size_t numElems) {
return zone()->template pod_malloc<S>(numElems);
}
template <typename S>
S *pod_calloc(size_t numElems) {
return zone()->template pod_calloc<S>(numElems);
}
template <typename S>
S *pod_realloc(S *prior, size_t oldSize, size_t newSize) {
return zone()->template pod_realloc<S>(prior, oldSize, newSize);
}
template <typename S, typename U>
S *pod_malloc_with_extra(size_t numExtra) {
return zone()->template pod_malloc_with_extra<S, U>(numExtra);
}
template <typename S, typename U>
S *pod_calloc_with_extra(size_t numExtra) {
return zone()->template pod_calloc_with_extra<S, U>(numExtra);
}
};
} // namespace gc

View File

@ -554,7 +554,7 @@ ForkJoinNursery::allocateSlots(JSObject *obj, uint32_t nslots)
return nullptr;
if (!isInsideNewspace(obj))
return obj->zone()->pod_malloc<HeapSlot>(nslots);
return obj->pod_malloc<HeapSlot>(nslots);
if (nslots > MaxNurserySlots)
return allocateHugeSlots(obj, nslots);
@ -576,7 +576,7 @@ ForkJoinNursery::reallocateSlots(JSObject *obj, HeapSlot *oldSlots,
if (!isInsideNewspace(obj)) {
JS_ASSERT_IF(oldSlots, !isInsideNewspace(oldSlots));
return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
return obj->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
}
if (!isInsideNewspace(oldSlots))
@ -626,7 +626,7 @@ ForkJoinNursery::allocateHugeSlots(JSObject *obj, size_t nslots)
if (nslots & mozilla::tl::MulOverflowMask<sizeof(HeapSlot)>::value)
return nullptr;
HeapSlot *slots = obj->zone()->pod_malloc<HeapSlot>(nslots);
HeapSlot *slots = obj->pod_malloc<HeapSlot>(nslots);
if (!slots)
return slots;
@ -639,7 +639,7 @@ HeapSlot *
ForkJoinNursery::reallocateHugeSlots(JSObject *obj, HeapSlot *oldSlots,
uint32_t oldCount, uint32_t newCount)
{
HeapSlot *newSlots = obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
HeapSlot *newSlots = obj->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
if (!newSlots)
return newSlots;

View File

@ -223,7 +223,7 @@ js::Nursery::allocateSlots(JSObject *obj, uint32_t nslots)
JS_ASSERT(nslots > 0);
if (!IsInsideNursery(obj))
return obj->zone()->pod_malloc<HeapSlot>(nslots);
return obj->pod_malloc<HeapSlot>(nslots);
if (nslots > MaxNurserySlots)
return allocateHugeSlots(obj->zone(), nslots);
@ -248,10 +248,10 @@ js::Nursery::reallocateSlots(JSObject *obj, HeapSlot *oldSlots,
uint32_t oldCount, uint32_t newCount)
{
if (!IsInsideNursery(obj))
return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
return obj->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
if (!isInside(oldSlots)) {
HeapSlot *newSlots = obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
HeapSlot *newSlots = obj->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
if (newSlots && oldSlots != newSlots) {
hugeSlots.remove(oldSlots);
/* If this put fails, we will only leak the slots. */

View File

@ -178,7 +178,7 @@ BaselineCompiler::compile()
// Note: There is an extra entry in the bytecode type map for the search hint, see below.
size_t bytecodeTypeMapEntries = script->nTypeSets() + 1;
BaselineScript *baselineScript = BaselineScript::New(cx, prologueOffset_.offset(),
BaselineScript *baselineScript = BaselineScript::New(script, prologueOffset_.offset(),
epilogueOffset_.offset(),
spsPushToggleOffset_.offset(),
postDebugPrologueOffset_.offset(),

View File

@ -349,15 +349,13 @@ jit::CanEnterBaselineMethod(JSContext *cx, RunState &state)
};
BaselineScript *
BaselineScript::New(JSContext *cx, uint32_t prologueOffset, uint32_t epilogueOffset,
BaselineScript::New(JSScript *jsscript, uint32_t prologueOffset, uint32_t epilogueOffset,
uint32_t spsPushToggleOffset, uint32_t postDebugPrologueOffset,
size_t icEntries, size_t pcMappingIndexEntries, size_t pcMappingSize,
size_t bytecodeTypeMapEntries)
{
static const unsigned DataAlignment = sizeof(uintptr_t);
size_t paddedBaselineScriptSize = AlignBytes(sizeof(BaselineScript), DataAlignment);
size_t icEntriesSize = icEntries * sizeof(ICEntry);
size_t pcMappingIndexEntriesSize = pcMappingIndexEntries * sizeof(PCMappingIndexEntry);
size_t bytecodeTypeMapSize = bytecodeTypeMapEntries * sizeof(uint32_t);
@ -367,21 +365,19 @@ BaselineScript::New(JSContext *cx, uint32_t prologueOffset, uint32_t epilogueOff
size_t paddedPCMappingSize = AlignBytes(pcMappingSize, DataAlignment);
size_t paddedBytecodeTypesMapSize = AlignBytes(bytecodeTypeMapSize, DataAlignment);
size_t allocBytes = paddedBaselineScriptSize +
paddedICEntriesSize +
paddedPCMappingIndexEntriesSize +
paddedPCMappingSize +
paddedBytecodeTypesMapSize;
size_t allocBytes = paddedICEntriesSize +
paddedPCMappingIndexEntriesSize +
paddedPCMappingSize +
paddedBytecodeTypesMapSize;
uint8_t *buffer = cx->zone()->pod_malloc<uint8_t>(allocBytes);
if (!buffer)
BaselineScript *script = jsscript->pod_malloc_with_extra<BaselineScript, uint8_t>(allocBytes);
if (!script)
return nullptr;
BaselineScript *script = reinterpret_cast<BaselineScript *>(buffer);
new (script) BaselineScript(prologueOffset, epilogueOffset,
spsPushToggleOffset, postDebugPrologueOffset);
size_t offsetCursor = paddedBaselineScriptSize;
size_t offsetCursor = sizeof(BaselineScript);
MOZ_ASSERT(offsetCursor == AlignBytes(sizeof(BaselineScript), DataAlignment));
script->icEntriesOffset_ = offsetCursor;
script->icEntries_ = icEntries;

View File

@ -178,7 +178,7 @@ struct BaselineScript
BaselineScript(uint32_t prologueOffset, uint32_t epilogueOffset,
uint32_t spsPushToggleOffset, uint32_t postDebugPrologueOffset);
static BaselineScript *New(JSContext *cx, uint32_t prologueOffset,
static BaselineScript *New(JSScript *script, uint32_t prologueOffset,
uint32_t epilogueOffset, uint32_t postDebugPrologueOffset,
uint32_t spsPushToggleOffset, size_t icEntries,
size_t pcMappingIndexEntries, size_t pcMappingSize,
@ -347,6 +347,8 @@ struct BaselineScript
return reinterpret_cast<uint32_t *>(reinterpret_cast<uint8_t *>(this) + bytecodeTypeMapOffset_);
}
};
static_assert(sizeof(BaselineScript) % sizeof(uintptr_t) == 0,
"The data attached to the script must be aligned for fast JIT access.");
inline bool
IsBaselineEnabled(JSContext *cx)

View File

@ -901,11 +901,9 @@ IonScript::New(JSContext *cx, types::RecompileInfo recompileInfo,
paddedSafepointSize +
paddedCallTargetSize +
paddedBackedgeSize;
uint8_t *buffer = cx->zone()->pod_malloc<uint8_t>(sizeof(IonScript) + bytes);
if (!buffer)
IonScript *script = cx->zone()->pod_malloc_with_extra<IonScript, uint8_t>(bytes);
if (!script)
return nullptr;
IonScript *script = reinterpret_cast<IonScript *>(buffer);
new (script) IonScript();
uint32_t offsetCursor = sizeof(IonScript);

View File

@ -2644,11 +2644,11 @@ TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj)
if (obj->isIndexed())
objType->setFlags(cx, OBJECT_FLAG_SPARSE_INDEXES);
ScopedJSFreePtr<jsid> ids(cx->pod_calloc<jsid>(properties.length()));
ScopedJSFreePtr<jsid> ids(objType->pod_calloc<jsid>(properties.length()));
if (!ids)
return;
ScopedJSFreePtr<Type> types(cx->pod_calloc<Type>(properties.length()));
ScopedJSFreePtr<Type> types(objType->pod_calloc<Type>(properties.length()));
if (!types)
return;
@ -3389,9 +3389,8 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
return;
}
size_t numBytes = sizeof(TypeNewScript)
+ (initializerList.length() * sizeof(TypeNewScript::Initializer));
TypeNewScript *newScript = (TypeNewScript *) type->zone()->pod_calloc<uint8_t>(numBytes);
TypeNewScript *newScript = type->pod_calloc_with_extra<TypeNewScript, TypeNewScript::Initializer>(
initializerList.length());
if (!newScript)
return;
@ -3402,8 +3401,7 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
newScript->fun = fun;
newScript->templateObject = baseobj;
newScript->initializerList = (TypeNewScript::Initializer *)
((char *) newScript + sizeof(TypeNewScript));
newScript->initializerList = reinterpret_cast<TypeNewScript::Initializer *>(newScript + 1);
PodCopy(newScript->initializerList,
initializerList.begin(),
initializerList.length());
@ -3599,7 +3597,7 @@ JSScript::makeTypes(JSContext *cx)
unsigned count = TypeScript::NumTypeSets(this);
TypeScript *typeScript = (TypeScript *)
zone()->pod_calloc<uint8_t>(TypeScript::SizeIncludingTypeArray(count));
pod_calloc<uint8_t>(TypeScript::SizeIncludingTypeArray(count));
if (!typeScript)
return false;

View File

@ -499,16 +499,12 @@ NativeIterator *
NativeIterator::allocateIterator(JSContext *cx, uint32_t slength, const AutoIdVector &props)
{
size_t plength = props.length();
size_t nbytes = sizeof(NativeIterator) +
plength * sizeof(JSString *) +
slength * sizeof(Shape *);
uint8_t *bytes = cx->zone()->pod_malloc<uint8_t>(nbytes);
if (!bytes)
NativeIterator *ni = cx->zone()->pod_malloc_with_extra<NativeIterator, void *>(plength + slength);
if (!ni)
return nullptr;
NativeIterator *ni = (NativeIterator *)bytes;
AutoValueVector strings(cx);
ni->props_array = ni->props_cursor = (HeapPtrFlatString *) (ni + 1);
ni->props_array = ni->props_cursor = reinterpret_cast<HeapPtrFlatString *>(ni + 1);
ni->props_end = ni->props_array + plength;
if (plength) {
for (size_t i = 0; i < plength; i++) {
@ -526,7 +522,7 @@ NativeIterator::allocateIterator(JSContext *cx, uint32_t slength, const AutoIdVe
NativeIterator *
NativeIterator::allocateSentinel(JSContext *cx)
{
NativeIterator *ni = (NativeIterator *)js_malloc(sizeof(NativeIterator));
NativeIterator *ni = js_pod_malloc<NativeIterator>();
if (!ni)
return nullptr;
@ -1778,22 +1774,15 @@ js_NewGenerator(JSContext *cx, const InterpreterRegs &stackRegs)
Value *stackvp = stackfp->generatorArgsSnapshotBegin();
unsigned vplen = stackfp->generatorArgsSnapshotEnd() - stackvp;
/* Compute JSGenerator size. */
unsigned nbytes = sizeof(JSGenerator) +
(-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);
static_assert(sizeof(InterpreterFrame) % sizeof(HeapValue) == 0,
"The Values stored after InterpreterFrame must be aligned.");
unsigned nvals = vplen + VALUES_PER_STACK_FRAME + stackfp->script()->nslots();
JSGenerator *gen = obj->pod_calloc_with_extra<JSGenerator, HeapValue>(nvals);
if (!gen)
return nullptr;
/* Cut up floatingStack space. */
HeapValue *genvp = gen->stackSnapshot;
HeapValue *genvp = gen->stackSnapshot();
SetValueRangeToUndefined((Value *)genvp, vplen);
InterpreterFrame *genfp = reinterpret_cast<InterpreterFrame *>(genvp + vplen);

View File

@ -246,7 +246,15 @@ struct JSGenerator
js::InterpreterRegs regs;
JSGenerator *prevGenerator;
js::InterpreterFrame *fp;
js::HeapValue stackSnapshot[1];
#if JS_BITS_PER_WORD == 32
uint32_t padding;
#endif
js::HeapValue *stackSnapshot() {
static_assert(sizeof(JSGenerator) % sizeof(js::HeapValue) == 0,
"The generator must have Value alignment for JIT access.");
return reinterpret_cast<js::HeapValue *>(this + 1);
}
};
extern JSObject *

View File

@ -2487,13 +2487,13 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *aArg, JSObject *bArg,
unsigned bdynamic = dynamicSlotsCount(reserved.newbfixed, a->slotSpan(), a->getClass());
if (adynamic) {
reserved.newaslots = a->zone()->pod_malloc<HeapSlot>(adynamic);
reserved.newaslots = a->pod_malloc<HeapSlot>(adynamic);
if (!reserved.newaslots)
return false;
Debug_SetSlotRangeToCrashOnTouch(reserved.newaslots, adynamic);
}
if (bdynamic) {
reserved.newbslots = b->zone()->pod_malloc<HeapSlot>(bdynamic);
reserved.newbslots = b->pod_malloc<HeapSlot>(bdynamic);
if (!reserved.newbslots)
return false;
Debug_SetSlotRangeToCrashOnTouch(reserved.newbslots, bdynamic);
@ -2972,7 +2972,7 @@ AllocateSlots(ThreadSafeContext *cx, JSObject *obj, uint32_t nslots)
if (cx->isForkJoinContext())
return cx->asForkJoinContext()->nursery().allocateSlots(obj, nslots);
#endif
return obj->zone()->pod_malloc<HeapSlot>(nslots);
return obj->pod_malloc<HeapSlot>(nslots);
}
// This will not run the garbage collector. If a nursery cannot accomodate the slot array
@ -2995,7 +2995,7 @@ ReallocateSlots(ThreadSafeContext *cx, JSObject *obj, HeapSlot *oldSlots,
oldCount, newCount);
}
#endif
return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
return obj->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
}
/* static */ bool
@ -3310,7 +3310,7 @@ AllocateElements(ThreadSafeContext *cx, JSObject *obj, uint32_t nelems)
return cx->asForkJoinContext()->nursery().allocateElements(obj, nelems);
#endif
return reinterpret_cast<js::ObjectElements *>(obj->zone()->pod_malloc<HeapSlot>(nelems));
return reinterpret_cast<js::ObjectElements *>(obj->pod_malloc<HeapSlot>(nelems));
}
// This will not run the garbage collector. If a nursery cannot accomodate the element array
@ -3333,8 +3333,8 @@ ReallocateElements(ThreadSafeContext *cx, JSObject *obj, ObjectElements *oldHead
#endif
return reinterpret_cast<js::ObjectElements *>(
obj->zone()->pod_realloc<HeapSlot>(reinterpret_cast<HeapSlot *>(oldHeader),
oldCount, newCount));
obj->pod_realloc<HeapSlot>(reinterpret_cast<HeapSlot *>(oldHeader),
oldCount, newCount));
}
// Round up |reqAllocated| to a good size. Up to 1 Mebi (i.e. 1,048,576) the

View File

@ -3655,7 +3655,7 @@ LazyScript::CreateRaw(ExclusiveContext *cx, HandleFunction fun,
size_t bytes = (p.numFreeVariables * sizeof(HeapPtrAtom))
+ (p.numInnerFunctions * sizeof(HeapPtrFunction));
ScopedJSFreePtr<uint8_t> table(bytes ? fun->zone()->pod_malloc<uint8_t>(bytes) : nullptr);
ScopedJSFreePtr<uint8_t> table(bytes ? fun->pod_malloc<uint8_t>(bytes) : nullptr);
if (bytes && !table)
return nullptr;

View File

@ -78,6 +78,26 @@ struct MallocProvider
return nullptr;
}
template <class T, class U>
T *pod_malloc_with_extra(size_t numExtra) {
if (numExtra & mozilla::tl::MulOverflowMask<sizeof(U)>::value) {
client()->reportAllocationOverflow();
return nullptr;
}
size_t bytes = sizeof(T) + numExtra * sizeof(U);
if (bytes < sizeof(T)) {
client()->reportAllocationOverflow();
return nullptr;
}
T *p = (T *)js_pod_malloc<uint8_t>(bytes);
if (MOZ_LIKELY(p)) {
client()->updateMallocCounter(bytes);
return p;
}
client()->onOutOfMemory(nullptr, bytes);
return nullptr;
}
template <class T>
mozilla::UniquePtr<T[], JS::FreePolicy>
make_pod_array(size_t numElems) {
@ -111,6 +131,16 @@ struct MallocProvider
return nullptr;
}
template <class T, class U>
T *
pod_calloc_with_extra(size_t numExtra) {
T *p = pod_malloc_with_extra<T, U>(numExtra);
if (MOZ_UNLIKELY(!p))
return nullptr;
memset(p, 0, sizeof(T) + numExtra * sizeof(U));
return p;
}
template <class T>
mozilla::UniquePtr<T[], JS::FreePolicy>
make_zeroed_pod_array(size_t numElems)

View File

@ -1037,7 +1037,7 @@ JSRuntime::initSelfHosting(JSContext *cx)
const unsigned char *compressed = compressedSources;
uint32_t compressedLen = GetCompressedSize();
ScopedJSFreePtr<char> src(selfHostingGlobal_->zone()->pod_malloc<char>(srcLen));
ScopedJSFreePtr<char> src(selfHostingGlobal_->pod_malloc<char>(srcLen));
if (!src || !DecompressString(compressed, compressedLen,
reinterpret_cast<unsigned char *>(src.get()), srcLen))
{

View File

@ -173,7 +173,7 @@ AllocChars(JSString *str, size_t length, CharT **chars, size_t *capacity)
*capacity = numChars - 1;
JS_STATIC_ASSERT(JSString::MAX_LENGTH * sizeof(CharT) < UINT32_MAX);
*chars = str->zone()->pod_malloc<CharT>(numChars);
*chars = str->pod_malloc<CharT>(numChars);
return *chars != nullptr;
}