Bug 1127167 - Backout 825f6ee63f7f for causing massive regressions on a CLOSED TREE

This commit is contained in:
Brian Hackett 2015-02-11 17:47:13 -07:00
Родитель b3fc1b8237
Коммит f93fe5bf9e
8 изменённых файлов: 83 добавлений и 81 удалений

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

@ -9335,28 +9335,24 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
// as a constructor, for later use during Ion compilation.
RootedObject templateObject(cx);
if (constructing) {
JSObject *thisObject = CreateThisForFunction(cx, fun, MaybeSingletonObject);
if (!thisObject)
return false;
if (thisObject->is<PlainObject>() || thisObject->is<UnboxedPlainObject>()) {
templateObject = thisObject;
// If we are calling a constructor for which the new script
// properties analysis has not been performed yet, don't attach a
// stub. After the analysis is performed, CreateThisForFunction may
// start returning objects with a different type, and the Ion
// compiler will get confused.
// Only attach a stub if the function already has a prototype and
// we can look it up without causing side effects.
RootedValue protov(cx);
if (!GetPropertyPure(cx, fun, NameToId(cx->names().prototype), protov.address())) {
JitSpew(JitSpew_BaselineIC, " Can't purely lookup function prototype");
return true;
}
if (protov.isObject()) {
TaggedProto proto(&protov.toObject());
ObjectGroup *group = ObjectGroup::defaultNewGroup(cx, nullptr, proto, fun);
if (!group)
return false;
if (group->newScript() && !group->newScript()->analyzed()) {
JitSpew(JitSpew_BaselineIC, " Function newScript has not been analyzed");
// compiler might get confused.
TypeNewScript *newScript = templateObject->group()->newScript();
if (newScript && !newScript->analyzed()) {
// Clear the object just created from the preliminary objects
// on the TypeNewScript, as it will not be used or filled in by
// running code.
newScript->unregisterNewObject(&templateObject->as<PlainObject>());
return true;
}
}

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

@ -1305,13 +1305,13 @@ ClassProtoKeyOrAnonymousOrNull(const js::Class *clasp)
}
static inline bool
NativeGetPureInline(NativeObject *pobj, Shape *shape, Value *vp)
NativeGetPureInline(NativeObject *pobj, Shape *shape, MutableHandleValue vp)
{
if (shape->hasSlot()) {
*vp = pobj->getSlot(shape->slot());
MOZ_ASSERT(!vp->isMagic());
vp.set(pobj->getSlot(shape->slot()));
MOZ_ASSERT(!vp.isMagic());
} else {
vp->setUndefined();
vp.setUndefined();
}
/* Fail if we have a custom getter. */
@ -1350,7 +1350,7 @@ FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class
return false;
} else {
Shape *shape = nctor->lookup(cx, cx->names().prototype);
if (!shape || !NativeGetPureInline(nctor, shape, v.address()))
if (!shape || !NativeGetPureInline(nctor, shape, &v))
return false;
}
if (v.isObject())
@ -1487,7 +1487,6 @@ js::NewObjectWithGroupCommon(JSContext *cx, HandleObjectGroup group, JSObject *p
parent == group->proto().toObject()->getParent() &&
newKind == GenericObject &&
group->clasp()->isNative() &&
(!group->newScript() || group->newScript()->analyzed()) &&
!cx->compartment()->hasObjectMetadataCallback())
{
if (cache.lookupGroup(group, allocKind, &entry)) {
@ -2140,7 +2139,7 @@ js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
AllocKind kind = GetBackgroundAllocKind(GuessObjectGCKind(srcObj->as<PlainObject>().numFixedSlots()));
MOZ_ASSERT_IF(srcObj->isTenured(), kind == srcObj->asTenured().getAllocKind());
RootedObject proto(cx, cx->global()->getOrCreateObjectPrototype(cx));
JSObject *proto = cx->global()->getOrCreateObjectPrototype(cx);
if (!proto)
return nullptr;
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &PlainObject::class_,
@ -2148,17 +2147,8 @@ js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
if (!group)
return nullptr;
RootedPlainObject res(cx, NewObjectWithGroup<PlainObject>(cx, group, parent, kind,
MaybeSingletonObject));
if (!res)
return nullptr;
RootedShape newShape(cx, ReshapeForParentAndAllocKind(cx, srcObj->lastProperty(),
TaggedProto(proto), parent, kind));
if (!newShape || !NativeObject::setLastProperty(cx, res, newShape))
return nullptr;
return res;
RootedShape shape(cx, srcObj->lastProperty());
return NewReshapedObject(cx, group, parent, kind, shape);
}
RootedArrayObject srcArray(cx, &srcObj->as<ArrayObject>());
@ -3012,16 +3002,6 @@ js::LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, JSObject **
return true;
}
bool
js::GetPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, Value *vp)
{
JSObject *pobj;
Shape *shape;
if (!LookupPropertyPure(cx, obj, id, &pobj, &shape))
return false;
return pobj->isNative() && NativeGetPureInline(&pobj->as<NativeObject>(), shape, vp);
}
bool
JSObject::reportReadOnly(JSContext *cx, jsid id, unsigned report)
{

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

@ -1199,9 +1199,6 @@ bool
LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, JSObject **objp,
Shape **propp);
bool
GetPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, Value *vp);
bool
GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id,
MutableHandle<PropertyDescriptor> desc);

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

@ -648,6 +648,11 @@ NewObjectWithGroup(JSContext *cx, HandleObjectGroup group, JSObject *parent,
return NewObjectWithGroup<T>(cx, group, parent, allocKind, newKind);
}
JSObject *
NewReshapedObject(JSContext *cx, HandleObjectGroup group, JSObject *parent,
gc::AllocKind allocKind, HandleShape shape,
NewObjectKind newKind = GenericObject);
/*
* As for gc::GetGCObjectKind, where numSlots is a guess at the final size of
* the object, zero if the final size is unknown. This should only be used for

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

@ -601,17 +601,21 @@ NativeObject::addPropertyInternal(ExclusiveContext *cx,
return nullptr;
}
Shape *
js::ReshapeForParentAndAllocKind(JSContext *cx, Shape *shape, TaggedProto proto, JSObject *parent,
gc::AllocKind allocKind)
JSObject *
js::NewReshapedObject(JSContext *cx, HandleObjectGroup group, JSObject *parent,
gc::AllocKind allocKind, HandleShape shape, NewObjectKind newKind)
{
// Compute the number of fixed slots with the new allocation kind.
size_t nfixed = gc::GetGCKindSlots(allocKind, shape->getObjectClass());
RootedPlainObject res(cx, NewObjectWithGroup<PlainObject>(cx, group, parent, allocKind, newKind));
if (!res)
return nullptr;
// Get all the ids in the shape, in order.
if (shape->isEmptyShape())
return res;
/* Get all the ids in the object, in order. */
js::AutoIdVector ids(cx);
{
for (unsigned i = 0; i < shape->slotSpan(); i++) {
for (unsigned i = 0; i <= shape->slot(); i++) {
if (!ids.append(JSID_VOID))
return nullptr;
}
@ -622,13 +626,17 @@ js::ReshapeForParentAndAllocKind(JSContext *cx, Shape *shape, TaggedProto proto,
}
}
// Construct the new shape, without updating type information.
/* Construct the new shape, without updating type information. */
RootedId id(cx);
RootedShape newShape(cx, EmptyShape::getInitialShape(cx, shape->getObjectClass(),
proto, parent, shape->getObjectMetadata(),
nfixed, shape->getObjectFlags()));
RootedShape newShape(cx, EmptyShape::getInitialShape(cx, res->getClass(),
res->getTaggedProto(),
res->getParent(),
res->getMetadata(),
res->numFixedSlots(),
shape->getObjectFlags()));
for (unsigned i = 0; i < ids.length(); i++) {
id = ids[i];
MOZ_ASSERT(!res->contains(cx, id));
uint32_t index;
bool indexed = js_IdIsIndex(id, &index);
@ -646,9 +654,11 @@ js::ReshapeForParentAndAllocKind(JSContext *cx, Shape *shape, TaggedProto proto,
newShape = cx->compartment()->propertyTree.getChild(cx, newShape, child);
if (!newShape)
return nullptr;
if (!NativeObject::setLastProperty(cx, res, newShape))
return nullptr;
}
return newShape;
return res;
}
/*

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

@ -1553,10 +1553,6 @@ IsImplicitDenseOrTypedArrayElement(Shape *prop)
return prop == reinterpret_cast<Shape*>(1);
}
Shape *
ReshapeForParentAndAllocKind(JSContext *cx, Shape *shape, TaggedProto proto, JSObject *parent,
gc::AllocKind allocKind);
} // namespace js
#ifdef _MSC_VER

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

@ -3152,6 +3152,19 @@ PreliminaryObjectArray::registerNewObject(JSObject *res)
MOZ_CRASH("There should be room for registering the new object");
}
void
PreliminaryObjectArray::unregisterNewObject(JSObject *res)
{
for (size_t i = 0; i < COUNT; i++) {
if (objects[i] == res) {
objects[i] = nullptr;
return;
}
}
MOZ_CRASH("The object should be one of the preliminary objects");
}
bool
PreliminaryObjectArray::full() const
{
@ -3227,6 +3240,13 @@ TypeNewScript::registerNewObject(PlainObject *res)
preliminaryObjects->registerNewObject(res);
}
void
TypeNewScript::unregisterNewObject(PlainObject *res)
{
MOZ_ASSERT(!analyzed());
preliminaryObjects->unregisterNewObject(res);
}
// Return whether shape consists entirely of plain data properties.
static bool
OnlyHasDataProperties(Shape *shape)
@ -3274,13 +3294,14 @@ ChangeObjectFixedSlotCount(JSContext *cx, PlainObject *obj, gc::AllocKind allocK
{
MOZ_ASSERT(OnlyHasDataProperties(obj->lastProperty()));
Shape *newShape = ReshapeForParentAndAllocKind(cx, obj->lastProperty(),
obj->getTaggedProto(), obj->getParent(),
allocKind);
if (!newShape)
// Make a clone of the object, with the new allocation kind.
RootedShape oldShape(cx, obj->lastProperty());
RootedObjectGroup group(cx, obj->group());
JSObject *clone = NewReshapedObject(cx, group, obj->getParent(), allocKind, oldShape);
if (!clone)
return false;
obj->setLastPropertyShrinkFixedSlots(newShape);
obj->setLastPropertyShrinkFixedSlots(clone->lastProperty());
return true;
}
@ -3468,15 +3489,10 @@ TypeNewScript::maybeAnalyze(JSContext *cx, ObjectGroup *group, bool *regenerate,
MOZ_ASSERT(group->unboxedLayout().newScript() == this);
destroyNewScript.group = nullptr;
// Clear out the template object, which is not used for TypeNewScripts
// with an unboxed layout. Currently it is a mutant object with a
// non-native group and native shape, so make it safe for GC by changing
// its group to the default for its prototype.
ObjectGroup *plainGroup = ObjectGroup::defaultNewGroup(cx, &PlainObject::class_,
group->proto());
if (!plainGroup)
CrashAtUnhandlableOOM("TypeNewScript::maybeAnalyze");
templateObject_->setGroup(plainGroup);
// Clear out the template object. This is not used for TypeNewScripts
// with an unboxed layout, and additionally this template is now a
// mutant object with a non-native class and native shape, and must be
// collected by the next GC.
templateObject_ = nullptr;
return true;

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

@ -753,6 +753,7 @@ class PreliminaryObjectArray
}
void registerNewObject(JSObject *res);
void unregisterNewObject(JSObject *res);
JSObject *get(size_t i) const {
MOZ_ASSERT(i < COUNT);
@ -888,6 +889,7 @@ class TypeNewScript
void sweep();
void registerNewObject(PlainObject *res);
void unregisterNewObject(PlainObject *res);
bool maybeAnalyze(JSContext *cx, ObjectGroup *group, bool *regenerate, bool force = false);
bool rollbackPartiallyInitializedObjects(JSContext *cx, ObjectGroup *group);