Bug 1053999 - Investigation for JS_TransplantObject crash (r=bholley)

This commit is contained in:
Bill McCloskey 2014-09-18 08:56:56 -07:00
parent a0855f2419
commit 8869122ba4
3 changed files with 36 additions and 24 deletions

View File

@ -2451,11 +2451,10 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *aArg, JSObject *bArg,
const Class *bClass = b->getClass();
Rooted<TaggedProto> aProto(cx, a->getTaggedProto());
Rooted<TaggedProto> bProto(cx, b->getTaggedProto());
bool success;
if (!SetClassAndProto(cx, a, bClass, bProto, &success) || !success)
return false;
if (!SetClassAndProto(cx, b, aClass, aProto, &success) || !success)
return false;
if (!SetClassAndProto(cx, a, bClass, bProto, true))
MOZ_CRASH();
if (!SetClassAndProto(cx, b, aClass, aProto, true))
MOZ_CRASH();
if (a->tenuredSizeOfThis() == b->tenuredSizeOfThis())
return true;
@ -2468,29 +2467,29 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *aArg, JSObject *bArg,
*/
if (a->isNative()) {
if (!a->generateOwnShape(cx))
return false;
MOZ_CRASH();
} else {
reserved.newbshape = EmptyShape::getInitialShape(cx, aClass, aProto, a->getParent(), a->getMetadata(),
b->asTenured()->getAllocKind());
if (!reserved.newbshape)
return false;
MOZ_CRASH();
}
if (b->isNative()) {
if (!b->generateOwnShape(cx))
return false;
MOZ_CRASH();
} else {
reserved.newashape = EmptyShape::getInitialShape(cx, bClass, bProto, b->getParent(), b->getMetadata(),
a->asTenured()->getAllocKind());
if (!reserved.newashape)
return false;
MOZ_CRASH();
}
/* The avals/bvals vectors hold all original values from the objects. */
if (!reserved.avals.reserve(a->slotSpan()))
return false;
MOZ_CRASH();
if (!reserved.bvals.reserve(b->slotSpan()))
return false;
MOZ_CRASH();
/*
* The newafixed/newbfixed hold the number of fixed slots in the objects
@ -2525,13 +2524,13 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *aArg, JSObject *bArg,
if (adynamic) {
reserved.newaslots = a->zone()->pod_malloc<HeapSlot>(adynamic);
if (!reserved.newaslots)
return false;
MOZ_CRASH();
Debug_SetSlotRangeToCrashOnTouch(reserved.newaslots, adynamic);
}
if (bdynamic) {
reserved.newbslots = b->zone()->pod_malloc<HeapSlot>(bdynamic);
if (!reserved.newbslots)
return false;
MOZ_CRASH();
Debug_SetSlotRangeToCrashOnTouch(reserved.newbslots, bdynamic);
}
@ -3602,7 +3601,7 @@ JSObject::fixupAfterMovingGC()
bool
js::SetClassAndProto(JSContext *cx, HandleObject obj,
const Class *clasp, Handle<js::TaggedProto> proto,
bool *succeeded)
bool crashOnFailure)
{
/*
* Regenerate shapes for all of the scopes along the old prototype chain,
@ -3623,15 +3622,20 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj,
*
* :XXX: bug 707717 make this code less brittle.
*/
*succeeded = false;
RootedObject oldproto(cx, obj);
while (oldproto && oldproto->isNative()) {
if (oldproto->hasSingletonType()) {
if (!oldproto->generateOwnShape(cx))
if (!oldproto->generateOwnShape(cx)) {
if (crashOnFailure)
MOZ_CRASH();
return false;
}
} else {
if (!oldproto->setUncacheableProto(cx))
if (!oldproto->setUncacheableProto(cx)) {
if (crashOnFailure)
MOZ_CRASH();
return false;
}
}
oldproto = oldproto->getProto();
}
@ -3641,22 +3645,30 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj,
* Just splice the prototype, but mark the properties as unknown for
* consistent behavior.
*/
if (!obj->splicePrototype(cx, clasp, proto))
if (!obj->splicePrototype(cx, clasp, proto)) {
if (crashOnFailure)
MOZ_CRASH();
return false;
}
MarkTypeObjectUnknownProperties(cx, obj->type());
*succeeded = true;
return true;
}
if (proto.isObject()) {
RootedObject protoObj(cx, proto.toObject());
if (!JSObject::setNewTypeUnknown(cx, clasp, protoObj))
if (!JSObject::setNewTypeUnknown(cx, clasp, protoObj)) {
if (crashOnFailure)
MOZ_CRASH();
return false;
}
}
TypeObject *type = cx->getNewType(clasp, proto);
if (!type)
if (!type) {
if (crashOnFailure)
MOZ_CRASH();
return false;
}
/*
* Setting __proto__ on an object that has escaped and may be referenced by
@ -3671,7 +3683,6 @@ js::SetClassAndProto(JSContext *cx, HandleObject obj,
obj->setType(type);
*succeeded = true;
return true;
}

View File

@ -1311,7 +1311,7 @@ GetBuiltinPrototypePure(GlobalObject *global, JSProtoKey protoKey);
extern bool
SetClassAndProto(JSContext *cx, HandleObject obj,
const Class *clasp, Handle<TaggedProto> proto, bool *succeeded);
const Class *clasp, Handle<TaggedProto> proto, bool crashOnFailure);
/*
* Property-lookup-based access to interface and prototype objects for classes.

View File

@ -492,7 +492,8 @@ JSObject::setProto(JSContext *cx, JS::HandleObject obj, JS::HandleObject proto,
}
JS::Rooted<js::TaggedProto> taggedProto(cx, js::TaggedProto(proto));
return SetClassAndProto(cx, obj, obj->getClass(), taggedProto, succeeded);
*succeeded = SetClassAndProto(cx, obj, obj->getClass(), taggedProto, false);
return *succeeded;
}
inline bool