Bug 1134425 - Part 2: templatize the GC's allocation routines; r=jonco

--HG--
extra : rebase_source : 2b57ac72b48a44199375471b0047e4c40d7fb46d
This commit is contained in:
Terrence Cole 2015-03-04 11:30:24 -08:00
Родитель 5729940b3c
Коммит c11c675dc7
13 изменённых файлов: 71 добавлений и 169 удалений

Просмотреть файл

@ -149,11 +149,13 @@ CheckIncrementalZoneState(ExclusiveContext *cx, T *t)
* in the partially initialized thing.
*/
template <AllowGC allowGC>
inline JSObject *
AllocateObject(ExclusiveContext *cx, AllocKind kind, size_t nDynamicSlots, InitialHeap heap,
const Class *clasp)
template <typename T, AllowGC allowGC /* = CanGC */>
JSObject *
js::Allocate(ExclusiveContext *cx, AllocKind kind, size_t nDynamicSlots, InitialHeap heap,
const Class *clasp)
{
static_assert(mozilla::IsConvertible<T *, JSObject *>::value, "must be JSObject derived");
MOZ_ASSERT(kind >= FINALIZE_OBJECT0 && kind <= FINALIZE_OBJECT_LAST);
size_t thingSize = Arena::thingSize(kind);
MOZ_ASSERT(thingSize == Arena::thingSize(kind));
@ -194,11 +196,18 @@ AllocateObject(ExclusiveContext *cx, AllocKind kind, size_t nDynamicSlots, Initi
TraceTenuredAlloc(obj, kind);
return obj;
}
template JSObject *js::Allocate<JSObject, NoGC>(ExclusiveContext *cx, gc::AllocKind kind,
size_t nDynamicSlots, gc::InitialHeap heap,
const Class *clasp);
template JSObject *js::Allocate<JSObject, CanGC>(ExclusiveContext *cx, gc::AllocKind kind,
size_t nDynamicSlots, gc::InitialHeap heap,
const Class *clasp);
template <typename T, AllowGC allowGC>
inline T *
AllocateNonObject(ExclusiveContext *cx)
template <typename T, AllowGC allowGC /* = CanGC */>
T *
js::Allocate(ExclusiveContext *cx)
{
static_assert(!mozilla::IsConvertible<T*, JSObject*>::value, "must not be JSObject derived");
static_assert(sizeof(T) >= CellSize,
"All allocations must be at least the allocator-imposed minimum size.");
@ -214,10 +223,29 @@ AllocateNonObject(ExclusiveContext *cx)
t = static_cast<T *>(GCRuntime::refillFreeListFromAnyThread<allowGC>(cx, kind));
CheckIncrementalZoneState(cx, t);
TraceTenuredAlloc(t, kind);
gc::TraceTenuredAlloc(t, kind);
return t;
}
#define FOR_ALL_NON_OBJECT_GC_LAYOUTS(macro) \
macro(JS::Symbol) \
macro(JSExternalString) \
macro(JSFatInlineString) \
macro(JSScript) \
macro(JSString) \
macro(js::AccessorShape) \
macro(js::BaseShape) \
macro(js::LazyScript) \
macro(js::ObjectGroup) \
macro(js::Shape) \
macro(js::jit::JitCode)
#define DECL_ALLOCATOR_INSTANCES(type) \
template type *js::Allocate<type, NoGC>(ExclusiveContext *cx);\
template type *js::Allocate<type, CanGC>(ExclusiveContext *cx);
FOR_ALL_NON_OBJECT_GC_LAYOUTS(DECL_ALLOCATOR_INSTANCES)
#undef DECL_ALLOCATOR_INSTANCES
/*
* When allocating for initialization from a cached object copy, we will
* potentially destroy the cache entry we want to copy if we allow GC. On the
@ -247,7 +275,7 @@ js::gc::AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap hea
return reinterpret_cast<NativeObject *>(obj);
}
JSObject *obj = AllocateObject<NoGC>(cx, kind, 0, heap, clasp);
JSObject *obj = Allocate<JSObject, NoGC>(cx, kind, 0, heap, clasp);
if (!obj && allowGC) {
cx->runtime()->gc.maybeGC(cx->zone());
return nullptr;
@ -259,97 +287,3 @@ template NativeObject *js::gc::AllocateObjectForCacheHit<CanGC>(JSContext *, All
const Class *);
template NativeObject *js::gc::AllocateObjectForCacheHit<NoGC>(JSContext *, AllocKind, InitialHeap,
const Class *);
template <AllowGC allowGC>
JSObject *
js::NewGCObject(ExclusiveContext *cx, AllocKind kind, size_t nDynamicSlots,
InitialHeap heap, const Class *clasp)
{
MOZ_ASSERT(kind >= FINALIZE_OBJECT0 && kind <= FINALIZE_OBJECT_LAST);
return AllocateObject<allowGC>(cx, kind, nDynamicSlots, heap, clasp);
}
template JSObject *js::NewGCObject<CanGC>(ExclusiveContext *, AllocKind, size_t, InitialHeap,
const Class *);
template JSObject *js::NewGCObject<NoGC>(ExclusiveContext *, AllocKind, size_t, InitialHeap,
const Class *);
template <AllowGC allowGC>
jit::JitCode *
js::NewJitCode(ExclusiveContext *cx)
{
return AllocateNonObject<jit::JitCode, allowGC>(cx);
}
template jit::JitCode *js::NewJitCode<CanGC>(ExclusiveContext *cx);
template jit::JitCode *js::NewJitCode<NoGC>(ExclusiveContext *cx);
ObjectGroup *
js::NewObjectGroup(ExclusiveContext *cx)
{
return AllocateNonObject<ObjectGroup, CanGC>(cx);
}
template <AllowGC allowGC>
JSString *
js::NewGCString(ExclusiveContext *cx)
{
return AllocateNonObject<JSString, allowGC>(cx);
}
template JSString *js::NewGCString<CanGC>(ExclusiveContext *cx);
template JSString *js::NewGCString<NoGC>(ExclusiveContext *cx);
template <AllowGC allowGC>
JSFatInlineString *
js::NewGCFatInlineString(ExclusiveContext *cx)
{
return AllocateNonObject<JSFatInlineString, allowGC>(cx);
}
template JSFatInlineString *js::NewGCFatInlineString<CanGC>(ExclusiveContext *cx);
template JSFatInlineString *js::NewGCFatInlineString<NoGC>(ExclusiveContext *cx);
JSExternalString *
js::NewGCExternalString(ExclusiveContext *cx)
{
return AllocateNonObject<JSExternalString, CanGC>(cx);
}
Shape *
js::NewGCShape(ExclusiveContext *cx)
{
return AllocateNonObject<Shape, CanGC>(cx);
}
Shape *
js::NewGCAccessorShape(ExclusiveContext *cx)
{
return AllocateNonObject<AccessorShape, CanGC>(cx);
}
JSScript *
js::NewGCScript(ExclusiveContext *cx)
{
return AllocateNonObject<JSScript, CanGC>(cx);
}
LazyScript *
js::NewGCLazyScript(ExclusiveContext *cx)
{
return AllocateNonObject<LazyScript, CanGC>(cx);
}
template <AllowGC allowGC>
BaseShape *
js::NewGCBaseShape(ExclusiveContext *cx)
{
return AllocateNonObject<BaseShape, allowGC>(cx);
}
template BaseShape *js::NewGCBaseShape<CanGC>(ExclusiveContext *cx);
template BaseShape *js::NewGCBaseShape<NoGC>(ExclusiveContext *cx);
template <AllowGC allowGC>
JS::Symbol *
js::NewGCSymbol(ExclusiveContext *cx)
{
return AllocateNonObject<JS::Symbol, allowGC>(cx);
}
template JS::Symbol *js::NewGCSymbol<CanGC>(ExclusiveContext *cx);
template JS::Symbol *js::NewGCSymbol<NoGC>(ExclusiveContext *cx);

Просмотреть файл

@ -29,48 +29,14 @@ namespace jit {
class JitCode;
} // namespace jit
template <AllowGC allowGC>
template <typename, AllowGC allowGC = CanGC>
JSObject *
NewGCObject(ExclusiveContext *cx, gc::AllocKind kind, size_t nDynamicSlots,
gc::InitialHeap heap, const Class *clasp);
Allocate(ExclusiveContext *cx, gc::AllocKind kind, size_t nDynamicSlots, gc::InitialHeap heap,
const Class *clasp);
template <AllowGC allowGC>
jit::JitCode *
NewJitCode(ExclusiveContext *cx);
ObjectGroup *
NewObjectGroup(ExclusiveContext *cx);
template <AllowGC allowGC>
JSString *
NewGCString(ExclusiveContext *cx);
template <AllowGC allowGC>
JSFatInlineString *
NewGCFatInlineString(ExclusiveContext *cx);
JSExternalString *
NewGCExternalString(ExclusiveContext *cx);
Shape *
NewGCShape(ExclusiveContext *cx);
Shape *
NewGCAccessorShape(ExclusiveContext *cx);
JSScript *
NewGCScript(ExclusiveContext *cx);
LazyScript *
NewGCLazyScript(ExclusiveContext *cx);
template <AllowGC allowGC>
BaseShape *
NewGCBaseShape(ExclusiveContext *cx);
template <AllowGC allowGC>
JS::Symbol *
NewGCSymbol(ExclusiveContext *cx);
template <typename T, AllowGC allowGC = CanGC>
T *
Allocate(ExclusiveContext *cx);
namespace gc {

Просмотреть файл

@ -600,7 +600,7 @@ JitCode *
JitCode::New(JSContext *cx, uint8_t *code, uint32_t bufferSize, uint32_t headerSize,
ExecutablePool *pool, CodeKind kind)
{
JitCode *codeObj = js::NewJitCode<allowGC>(cx);
JitCode *codeObj = Allocate<JitCode, allowGC>(cx);
if (!codeObj) {
pool->release(headerSize + bufferSize, kind);
return nullptr;

Просмотреть файл

@ -90,7 +90,7 @@ JSObject *
NewGCObject(JSContext *cx, gc::AllocKind allocKind, gc::InitialHeap initialHeap,
const js::Class *clasp)
{
return js::NewGCObject<CanGC>(cx, allocKind, 0, initialHeap, clasp);
return js::Allocate<JSObject>(cx, allocKind, 0, initialHeap, clasp);
}
bool

Просмотреть файл

@ -262,7 +262,7 @@ JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::Initi
size_t nDynamicSlots =
js::NativeObject::dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan(), clasp);
JSObject *obj = js::NewGCObject<js::CanGC>(cx, kind, nDynamicSlots, heap, clasp);
JSObject *obj = js::Allocate<JSObject>(cx, kind, nDynamicSlots, heap, clasp);
if (!obj)
return nullptr;
@ -270,7 +270,7 @@ JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::Initi
obj->setInitialShapeMaybeNonNative(shape);
// Note: slots are created and assigned internally by NewGCObject.
// Note: slots are created and assigned internally by Allocate<JSObject>.
obj->setInitialElementsMaybeNonNative(js::emptyObjectElements);
if (clasp->hasPrivate())

Просмотреть файл

@ -2380,7 +2380,7 @@ JSScript::Create(ExclusiveContext *cx, HandleObject enclosingScope, bool savedCa
{
MOZ_ASSERT(bufStart <= bufEnd);
RootedScript script(cx, NewGCScript(cx));
RootedScript script(cx, Allocate<JSScript>(cx));
if (!script)
return nullptr;
@ -3758,7 +3758,7 @@ LazyScript::CreateRaw(ExclusiveContext *cx, HandleFunction fun,
if (bytes && !table)
return nullptr;
LazyScript *res = NewGCLazyScript(cx);
LazyScript *res = Allocate<LazyScript>(cx);
if (!res)
return nullptr;

Просмотреть файл

@ -3066,7 +3066,7 @@ static inline JSFatInlineString *
FlattenSubstrings(JSContext *cx, HandleLinearString str, const StringRange *ranges,
size_t rangesLen, size_t outputLen)
{
JSFatInlineString *result = NewGCFatInlineString<CanGC>(cx);
JSFatInlineString *result = Allocate<JSFatInlineString>(cx);
if (!result)
return nullptr;

Просмотреть файл

@ -44,7 +44,7 @@ ArrayObject::createArrayInternal(ExclusiveContext *cx, gc::AllocKind kind, gc::I
MOZ_ASSERT(shape->numFixedSlots() == 0);
size_t nDynamicSlots = dynamicSlotsCount(0, shape->slotSpan(), group->clasp());
JSObject *obj = NewGCObject<CanGC>(cx, kind, nDynamicSlots, heap, group->clasp());
JSObject *obj = Allocate<JSObject>(cx, kind, nDynamicSlots, heap, group->clasp());
if (!obj)
return nullptr;

Просмотреть файл

@ -1322,7 +1322,7 @@ ObjectGroupCompartment::makeGroup(ExclusiveContext *cx, const Class *clasp,
{
MOZ_ASSERT_IF(proto.isObject(), cx->isInsideCurrentCompartment(proto.toObject()));
ObjectGroup *group = NewObjectGroup(cx);
ObjectGroup *group = Allocate<ObjectGroup>(cx);
if (!group)
return nullptr;
new(group) ObjectGroup(clasp, proto, cx->compartment(), initialFlags);

Просмотреть файл

@ -107,7 +107,9 @@ inline Shape *
Shape::new_(ExclusiveContext *cx, StackShape &unrootedOther, uint32_t nfixed)
{
RootedGeneric<StackShape*> other(cx, &unrootedOther);
Shape *shape = other->isAccessorShape() ? NewGCAccessorShape(cx) : NewGCShape(cx);
Shape *shape = other->isAccessorShape()
? js::Allocate<AccessorShape>(cx)
: js::Allocate<Shape>(cx);
if (!shape) {
ReportOutOfMemory(cx);
return nullptr;

Просмотреть файл

@ -116,7 +116,7 @@ Shape::makeOwnBaseShape(ExclusiveContext *cx)
MOZ_ASSERT(!base()->isOwned());
assertSameCompartmentDebugOnly(cx, compartment());
BaseShape *nbase = NewGCBaseShape<NoGC>(cx);
BaseShape *nbase = Allocate<BaseShape, NoGC>(cx);
if (!nbase)
return false;
@ -383,7 +383,7 @@ NativeObject::getChildPropertyOnDictionary(ExclusiveContext *cx, HandleNativeObj
if (obj->inDictionaryMode()) {
MOZ_ASSERT(parent == obj->lastProperty());
RootedGeneric<StackShape*> childRoot(cx, &child);
shape = childRoot->isAccessorShape() ? NewGCAccessorShape(cx) : NewGCShape(cx);
shape = childRoot->isAccessorShape() ? Allocate<AccessorShape>(cx) : Allocate<Shape>(cx);
if (!shape)
return nullptr;
if (childRoot->hasSlot() && childRoot->slot() >= obj->lastProperty()->base()->slotSpan()) {
@ -438,7 +438,7 @@ js::NativeObject::toDictionaryMode(ExclusiveContext *cx)
while (shape) {
MOZ_ASSERT(!shape->inDictionary());
Shape *dprop = shape->isAccessorShape() ? NewGCAccessorShape(cx) : NewGCShape(cx);
Shape *dprop = shape->isAccessorShape() ? Allocate<AccessorShape>(cx) : Allocate<Shape>(cx);
if (!dprop) {
ReportOutOfMemory(cx);
return false;
@ -937,7 +937,7 @@ NativeObject::removeProperty(ExclusiveContext *cx, jsid id_)
RootedShape spare(cx);
if (self->inDictionaryMode()) {
/* For simplicity, always allocate an accessor shape for now. */
spare = NewGCAccessorShape(cx);
spare = Allocate<AccessorShape>(cx);
if (!spare)
return false;
new (spare) Shape(shape->base()->unowned(), 0);
@ -1093,8 +1093,8 @@ NativeObject::replaceWithNewEquivalentShape(ExclusiveContext *cx, Shape *oldShap
RootedNativeObject selfRoot(cx, self);
RootedShape oldRoot(cx, oldShape);
newShape = (oldShape->isAccessorShape() || accessorShape)
? NewGCAccessorShape(cx)
: NewGCShape(cx);
? Allocate<AccessorShape>(cx)
: Allocate<Shape>(cx);
if (!newShape)
return nullptr;
new (newShape) Shape(oldRoot->base()->unowned(), 0);
@ -1374,7 +1374,7 @@ BaseShape::getUnowned(ExclusiveContext *cx, StackBaseShape &base)
RootedGeneric<StackBaseShape*> root(cx, &base);
BaseShape *nbase_ = NewGCBaseShape<CanGC>(cx);
BaseShape *nbase_ = Allocate<BaseShape>(cx);
if (!nbase_)
return nullptr;
@ -1631,7 +1631,7 @@ JSCompartment::checkInitialShapesTableAfterMovingGC()
Shape *
EmptyShape::new_(ExclusiveContext *cx, Handle<UnownedBaseShape *> base, uint32_t nfixed)
{
Shape *shape = NewGCShape(cx);
Shape *shape = Allocate<Shape>(cx);
if (!shape) {
ReportOutOfMemory(cx);
return nullptr;

Просмотреть файл

@ -125,7 +125,7 @@ JSRope::new_(js::ExclusiveContext *cx,
{
if (!validateLength(cx, length))
return nullptr;
JSRope *str = (JSRope *)js::NewGCString<allowGC>(cx);
JSRope *str = static_cast<JSRope *>(js::Allocate<JSString, allowGC>(cx));
if (!str)
return nullptr;
str->init(cx, left, right, length);
@ -181,7 +181,7 @@ JSDependentString::new_(js::ExclusiveContext *cx, JSLinearString *baseArg, size_
: js::NewInlineString<char16_t>(cx, base, start, length);
}
JSDependentString *str = (JSDependentString *)js::NewGCString<js::NoGC>(cx);
JSDependentString *str = static_cast<JSDependentString *>(js::Allocate<JSString, js::NoGC>(cx));
if (str) {
str->init(cx, baseArg, start, length);
return str;
@ -189,7 +189,7 @@ JSDependentString::new_(js::ExclusiveContext *cx, JSLinearString *baseArg, size_
js::RootedLinearString base(cx, baseArg);
str = (JSDependentString *)js::NewGCString<js::CanGC>(cx);
str = static_cast<JSDependentString *>(js::Allocate<JSString>(cx));
if (!str)
return nullptr;
str->init(cx, base, start, length);
@ -221,7 +221,7 @@ JSFlatString::new_(js::ExclusiveContext *cx, const CharT *chars, size_t length)
if (!validateLength(cx, length))
return nullptr;
JSFlatString *str = (JSFlatString *)js::NewGCString<allowGC>(cx);
JSFlatString *str = static_cast<JSFlatString *>(js::Allocate<JSString, allowGC>(cx));
if (!str)
return nullptr;
@ -248,14 +248,14 @@ template <js::AllowGC allowGC>
MOZ_ALWAYS_INLINE JSThinInlineString *
JSThinInlineString::new_(js::ExclusiveContext *cx)
{
return (JSThinInlineString *)js::NewGCString<allowGC>(cx);
return static_cast<JSThinInlineString *>(js::Allocate<JSString, allowGC>(cx));
}
template <js::AllowGC allowGC>
MOZ_ALWAYS_INLINE JSFatInlineString *
JSFatInlineString::new_(js::ExclusiveContext *cx)
{
return js::NewGCFatInlineString<allowGC>(cx);
return js::Allocate<JSFatInlineString, allowGC>(cx);
}
template<>
@ -317,7 +317,7 @@ JSExternalString::new_(JSContext *cx, const char16_t *chars, size_t length,
if (!validateLength(cx, length))
return nullptr;
JSExternalString *str = js::NewGCExternalString(cx);
JSExternalString *str = js::Allocate<JSExternalString>(cx);
if (!str)
return nullptr;
str->init(chars, length, fin);

Просмотреть файл

@ -26,7 +26,7 @@ Symbol::newInternal(ExclusiveContext *cx, JS::SymbolCode code, JSAtom *descripti
MOZ_ASSERT(cx->atomsCompartment()->runtimeFromAnyThread()->currentThreadHasExclusiveAccess());
// Following js::AtomizeString, we grudgingly forgo last-ditch GC here.
Symbol *p = NewGCSymbol<NoGC>(cx);
Symbol *p = Allocate<JS::Symbol, NoGC>(cx);
if (!p) {
ReportOutOfMemory(cx);
return nullptr;