forked from mirrors/gecko-dev
Bug 1127167 - Backout 825f6ee63f7f for causing massive regressions on a CLOSED TREE
This commit is contained in:
parent
b3fc1b8237
commit
f93fe5bf9e
8 changed files with 83 additions and 81 deletions
|
|
@ -9335,28 +9335,24 @@ TryAttachCallStub(JSContext *cx, ICCall_Fallback *stub, HandleScript script, jsb
|
||||||
// as a constructor, for later use during Ion compilation.
|
// as a constructor, for later use during Ion compilation.
|
||||||
RootedObject templateObject(cx);
|
RootedObject templateObject(cx);
|
||||||
if (constructing) {
|
if (constructing) {
|
||||||
// If we are calling a constructor for which the new script
|
JSObject *thisObject = CreateThisForFunction(cx, fun, MaybeSingletonObject);
|
||||||
// properties analysis has not been performed yet, don't attach a
|
if (!thisObject)
|
||||||
// stub. After the analysis is performed, CreateThisForFunction may
|
return false;
|
||||||
// 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
|
if (thisObject->is<PlainObject>() || thisObject->is<UnboxedPlainObject>()) {
|
||||||
// we can look it up without causing side effects.
|
templateObject = thisObject;
|
||||||
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()) {
|
// If we are calling a constructor for which the new script
|
||||||
TaggedProto proto(&protov.toObject());
|
// properties analysis has not been performed yet, don't attach a
|
||||||
ObjectGroup *group = ObjectGroup::defaultNewGroup(cx, nullptr, proto, fun);
|
// stub. After the analysis is performed, CreateThisForFunction may
|
||||||
if (!group)
|
// start returning objects with a different type, and the Ion
|
||||||
return false;
|
// compiler might get confused.
|
||||||
|
TypeNewScript *newScript = templateObject->group()->newScript();
|
||||||
if (group->newScript() && !group->newScript()->analyzed()) {
|
if (newScript && !newScript->analyzed()) {
|
||||||
JitSpew(JitSpew_BaselineIC, " Function newScript has not been 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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1305,13 +1305,13 @@ ClassProtoKeyOrAnonymousOrNull(const js::Class *clasp)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
NativeGetPureInline(NativeObject *pobj, Shape *shape, Value *vp)
|
NativeGetPureInline(NativeObject *pobj, Shape *shape, MutableHandleValue vp)
|
||||||
{
|
{
|
||||||
if (shape->hasSlot()) {
|
if (shape->hasSlot()) {
|
||||||
*vp = pobj->getSlot(shape->slot());
|
vp.set(pobj->getSlot(shape->slot()));
|
||||||
MOZ_ASSERT(!vp->isMagic());
|
MOZ_ASSERT(!vp.isMagic());
|
||||||
} else {
|
} else {
|
||||||
vp->setUndefined();
|
vp.setUndefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fail if we have a custom getter. */
|
/* Fail if we have a custom getter. */
|
||||||
|
|
@ -1350,7 +1350,7 @@ FindClassPrototype(ExclusiveContext *cx, MutableHandleObject protop, const Class
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
Shape *shape = nctor->lookup(cx, cx->names().prototype);
|
Shape *shape = nctor->lookup(cx, cx->names().prototype);
|
||||||
if (!shape || !NativeGetPureInline(nctor, shape, v.address()))
|
if (!shape || !NativeGetPureInline(nctor, shape, &v))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (v.isObject())
|
if (v.isObject())
|
||||||
|
|
@ -1487,7 +1487,6 @@ js::NewObjectWithGroupCommon(JSContext *cx, HandleObjectGroup group, JSObject *p
|
||||||
parent == group->proto().toObject()->getParent() &&
|
parent == group->proto().toObject()->getParent() &&
|
||||||
newKind == GenericObject &&
|
newKind == GenericObject &&
|
||||||
group->clasp()->isNative() &&
|
group->clasp()->isNative() &&
|
||||||
(!group->newScript() || group->newScript()->analyzed()) &&
|
|
||||||
!cx->compartment()->hasObjectMetadataCallback())
|
!cx->compartment()->hasObjectMetadataCallback())
|
||||||
{
|
{
|
||||||
if (cache.lookupGroup(group, allocKind, &entry)) {
|
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()));
|
AllocKind kind = GetBackgroundAllocKind(GuessObjectGCKind(srcObj->as<PlainObject>().numFixedSlots()));
|
||||||
MOZ_ASSERT_IF(srcObj->isTenured(), kind == srcObj->asTenured().getAllocKind());
|
MOZ_ASSERT_IF(srcObj->isTenured(), kind == srcObj->asTenured().getAllocKind());
|
||||||
|
|
||||||
RootedObject proto(cx, cx->global()->getOrCreateObjectPrototype(cx));
|
JSObject *proto = cx->global()->getOrCreateObjectPrototype(cx);
|
||||||
if (!proto)
|
if (!proto)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &PlainObject::class_,
|
RootedObjectGroup group(cx, ObjectGroup::defaultNewGroup(cx, &PlainObject::class_,
|
||||||
|
|
@ -2148,17 +2147,8 @@ js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
|
||||||
if (!group)
|
if (!group)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
RootedPlainObject res(cx, NewObjectWithGroup<PlainObject>(cx, group, parent, kind,
|
RootedShape shape(cx, srcObj->lastProperty());
|
||||||
MaybeSingletonObject));
|
return NewReshapedObject(cx, group, parent, kind, shape);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedArrayObject srcArray(cx, &srcObj->as<ArrayObject>());
|
RootedArrayObject srcArray(cx, &srcObj->as<ArrayObject>());
|
||||||
|
|
@ -3012,16 +3002,6 @@ js::LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, JSObject **
|
||||||
return true;
|
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
|
bool
|
||||||
JSObject::reportReadOnly(JSContext *cx, jsid id, unsigned report)
|
JSObject::reportReadOnly(JSContext *cx, jsid id, unsigned report)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1199,9 +1199,6 @@ bool
|
||||||
LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
LookupPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, JSObject **objp,
|
||||||
Shape **propp);
|
Shape **propp);
|
||||||
|
|
||||||
bool
|
|
||||||
GetPropertyPure(ExclusiveContext *cx, JSObject *obj, jsid id, Value *vp);
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id,
|
GetOwnPropertyDescriptor(JSContext *cx, HandleObject obj, HandleId id,
|
||||||
MutableHandle<PropertyDescriptor> desc);
|
MutableHandle<PropertyDescriptor> desc);
|
||||||
|
|
|
||||||
|
|
@ -648,6 +648,11 @@ NewObjectWithGroup(JSContext *cx, HandleObjectGroup group, JSObject *parent,
|
||||||
return NewObjectWithGroup<T>(cx, group, parent, allocKind, newKind);
|
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
|
* 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
|
* 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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape *
|
JSObject *
|
||||||
js::ReshapeForParentAndAllocKind(JSContext *cx, Shape *shape, TaggedProto proto, JSObject *parent,
|
js::NewReshapedObject(JSContext *cx, HandleObjectGroup group, JSObject *parent,
|
||||||
gc::AllocKind allocKind)
|
gc::AllocKind allocKind, HandleShape shape, NewObjectKind newKind)
|
||||||
{
|
{
|
||||||
// Compute the number of fixed slots with the new allocation kind.
|
RootedPlainObject res(cx, NewObjectWithGroup<PlainObject>(cx, group, parent, allocKind, newKind));
|
||||||
size_t nfixed = gc::GetGCKindSlots(allocKind, shape->getObjectClass());
|
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);
|
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))
|
if (!ids.append(JSID_VOID))
|
||||||
return nullptr;
|
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);
|
RootedId id(cx);
|
||||||
RootedShape newShape(cx, EmptyShape::getInitialShape(cx, shape->getObjectClass(),
|
RootedShape newShape(cx, EmptyShape::getInitialShape(cx, res->getClass(),
|
||||||
proto, parent, shape->getObjectMetadata(),
|
res->getTaggedProto(),
|
||||||
nfixed, shape->getObjectFlags()));
|
res->getParent(),
|
||||||
|
res->getMetadata(),
|
||||||
|
res->numFixedSlots(),
|
||||||
|
shape->getObjectFlags()));
|
||||||
for (unsigned i = 0; i < ids.length(); i++) {
|
for (unsigned i = 0; i < ids.length(); i++) {
|
||||||
id = ids[i];
|
id = ids[i];
|
||||||
|
MOZ_ASSERT(!res->contains(cx, id));
|
||||||
|
|
||||||
uint32_t index;
|
uint32_t index;
|
||||||
bool indexed = js_IdIsIndex(id, &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);
|
newShape = cx->compartment()->propertyTree.getChild(cx, newShape, child);
|
||||||
if (!newShape)
|
if (!newShape)
|
||||||
return nullptr;
|
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);
|
return prop == reinterpret_cast<Shape*>(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape *
|
|
||||||
ReshapeForParentAndAllocKind(JSContext *cx, Shape *shape, TaggedProto proto, JSObject *parent,
|
|
||||||
gc::AllocKind allocKind);
|
|
||||||
|
|
||||||
} // namespace js
|
} // namespace js
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
|
||||||
|
|
@ -3152,6 +3152,19 @@ PreliminaryObjectArray::registerNewObject(JSObject *res)
|
||||||
MOZ_CRASH("There should be room for registering the new object");
|
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
|
bool
|
||||||
PreliminaryObjectArray::full() const
|
PreliminaryObjectArray::full() const
|
||||||
{
|
{
|
||||||
|
|
@ -3227,6 +3240,13 @@ TypeNewScript::registerNewObject(PlainObject *res)
|
||||||
preliminaryObjects->registerNewObject(res);
|
preliminaryObjects->registerNewObject(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TypeNewScript::unregisterNewObject(PlainObject *res)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!analyzed());
|
||||||
|
preliminaryObjects->unregisterNewObject(res);
|
||||||
|
}
|
||||||
|
|
||||||
// Return whether shape consists entirely of plain data properties.
|
// Return whether shape consists entirely of plain data properties.
|
||||||
static bool
|
static bool
|
||||||
OnlyHasDataProperties(Shape *shape)
|
OnlyHasDataProperties(Shape *shape)
|
||||||
|
|
@ -3274,13 +3294,14 @@ ChangeObjectFixedSlotCount(JSContext *cx, PlainObject *obj, gc::AllocKind allocK
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(OnlyHasDataProperties(obj->lastProperty()));
|
MOZ_ASSERT(OnlyHasDataProperties(obj->lastProperty()));
|
||||||
|
|
||||||
Shape *newShape = ReshapeForParentAndAllocKind(cx, obj->lastProperty(),
|
// Make a clone of the object, with the new allocation kind.
|
||||||
obj->getTaggedProto(), obj->getParent(),
|
RootedShape oldShape(cx, obj->lastProperty());
|
||||||
allocKind);
|
RootedObjectGroup group(cx, obj->group());
|
||||||
if (!newShape)
|
JSObject *clone = NewReshapedObject(cx, group, obj->getParent(), allocKind, oldShape);
|
||||||
|
if (!clone)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
obj->setLastPropertyShrinkFixedSlots(newShape);
|
obj->setLastPropertyShrinkFixedSlots(clone->lastProperty());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3468,15 +3489,10 @@ TypeNewScript::maybeAnalyze(JSContext *cx, ObjectGroup *group, bool *regenerate,
|
||||||
MOZ_ASSERT(group->unboxedLayout().newScript() == this);
|
MOZ_ASSERT(group->unboxedLayout().newScript() == this);
|
||||||
destroyNewScript.group = nullptr;
|
destroyNewScript.group = nullptr;
|
||||||
|
|
||||||
// Clear out the template object, which is not used for TypeNewScripts
|
// Clear out the template object. This is not used for TypeNewScripts
|
||||||
// with an unboxed layout. Currently it is a mutant object with a
|
// with an unboxed layout, and additionally this template is now a
|
||||||
// non-native group and native shape, so make it safe for GC by changing
|
// mutant object with a non-native class and native shape, and must be
|
||||||
// its group to the default for its prototype.
|
// collected by the next GC.
|
||||||
ObjectGroup *plainGroup = ObjectGroup::defaultNewGroup(cx, &PlainObject::class_,
|
|
||||||
group->proto());
|
|
||||||
if (!plainGroup)
|
|
||||||
CrashAtUnhandlableOOM("TypeNewScript::maybeAnalyze");
|
|
||||||
templateObject_->setGroup(plainGroup);
|
|
||||||
templateObject_ = nullptr;
|
templateObject_ = nullptr;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -753,6 +753,7 @@ class PreliminaryObjectArray
|
||||||
}
|
}
|
||||||
|
|
||||||
void registerNewObject(JSObject *res);
|
void registerNewObject(JSObject *res);
|
||||||
|
void unregisterNewObject(JSObject *res);
|
||||||
|
|
||||||
JSObject *get(size_t i) const {
|
JSObject *get(size_t i) const {
|
||||||
MOZ_ASSERT(i < COUNT);
|
MOZ_ASSERT(i < COUNT);
|
||||||
|
|
@ -888,6 +889,7 @@ class TypeNewScript
|
||||||
void sweep();
|
void sweep();
|
||||||
|
|
||||||
void registerNewObject(PlainObject *res);
|
void registerNewObject(PlainObject *res);
|
||||||
|
void unregisterNewObject(PlainObject *res);
|
||||||
bool maybeAnalyze(JSContext *cx, ObjectGroup *group, bool *regenerate, bool force = false);
|
bool maybeAnalyze(JSContext *cx, ObjectGroup *group, bool *regenerate, bool force = false);
|
||||||
|
|
||||||
bool rollbackPartiallyInitializedObjects(JSContext *cx, ObjectGroup *group);
|
bool rollbackPartiallyInitializedObjects(JSContext *cx, ObjectGroup *group);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue