Allow one prototype change before marking an object's prototype as uncacheable, bug 703047.

This commit is contained in:
Brian Hackett 2011-11-25 16:01:08 -05:00
Родитель 6c0fff0081
Коммит b044399808
5 изменённых файлов: 24 добавлений и 11 удалений

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

@ -4977,12 +4977,12 @@ SetProto(JSContext *cx, JSObject *obj, JSObject *proto, bool checkForCycles)
/*
* Regenerate shapes for all of the scopes along the old prototype chain,
* in case any entries were filled by looking up through obj. Stop when an
* object with an uncacheable prototype or a non-native object is found,
* prototype lookups will not be cached across these.
* object with a non-native object is found, prototype lookups will not be
* cached across these.
*/
JSObject *oldproto = obj;
while (oldproto && oldproto->isNative()) {
if (!oldproto->setUncacheableProto(cx))
if (!oldproto->protoShapeChange(cx))
return false;
oldproto = oldproto->getProto();
}

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

@ -597,7 +597,7 @@ struct JSObject : js::gc::Cell
* lookups on the object.
*/
inline bool hasUncacheableProto() const;
inline bool setUncacheableProto(JSContext *cx);
bool protoShapeChange(JSContext *cx);
bool generateOwnShape(JSContext *cx, js::Shape *newShape = NULL);

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

@ -916,11 +916,6 @@ inline bool JSObject::hasUncacheableProto() const
return lastProperty()->hasObjectFlag(js::BaseShape::UNCACHEABLE_PROTO);
}
inline bool JSObject::setUncacheableProto(JSContext *cx)
{
return setFlag(cx, js::BaseShape::UNCACHEABLE_PROTO);
}
inline bool JSObject::isExtensible() const
{
return !lastProperty()->hasObjectFlag(js::BaseShape::NOT_EXTENSIBLE);

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

@ -1198,6 +1198,23 @@ JSObject::preventExtensions(JSContext *cx, js::AutoIdVector *props)
return setFlag(cx, BaseShape::NOT_EXTENSIBLE, GENERATE_SHAPE);
}
bool
JSObject::protoShapeChange(JSContext *cx)
{
/*
* The CHANGED_PROTO flag is set on an object the first time its prototype
* dynamically changes. In such cases the object incurs a shape change,
* but its prototype can still be cached. The second type the prototype
* changes dynamically, the prototype becomes uncacheable. This is a hack
* for DOM behavior which resolves prototypes after creation in some cases.
* See ResolvePrototype in dom/base/nsDOMClassInfo.cpp.
*/
if (!lastProperty()->hasObjectFlag(BaseShape::CHANGED_PROTO))
return setFlag(cx, BaseShape::CHANGED_PROTO);
return setFlag(cx, js::BaseShape::UNCACHEABLE_PROTO);
}
bool
JSObject::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32 flag_, GenerateShape generateShape)
{

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

@ -371,9 +371,10 @@ class BaseShape : public js::gc::Cell
WATCHED = 0x400,
ITERATED_SINGLETON = 0x800,
NEW_TYPE_UNKNOWN = 0x1000,
UNCACHEABLE_PROTO = 0x2000,
CHANGED_PROTO = 0x2000,
UNCACHEABLE_PROTO = 0x4000,
OBJECT_FLAG_MASK = 0x3ff8
OBJECT_FLAG_MASK = 0x7ff8
};
private: