зеркало из https://github.com/mozilla/pjs.git
Empty shapes attached to type objects must have the same class as the prototype, bug 698150.
This commit is contained in:
Родитель
e53b529a86
Коммит
d82299608e
|
@ -814,10 +814,10 @@ struct TypeObject : gc::Cell
|
|||
/*
|
||||
* Return an immutable, shareable, empty shape for objects with this type
|
||||
* and the specified class, and finalize kind (fixed slot count). Objects
|
||||
* created with this shape have the same parent as the type's prototype.
|
||||
* created with this shape have the same class and parent as the type's
|
||||
* prototype.
|
||||
*/
|
||||
inline bool canProvideEmptyShape(js::Class *clasp);
|
||||
inline js::EmptyShape *getEmptyShape(JSContext *cx, js::Class *aclasp, gc::AllocKind kind);
|
||||
inline js::EmptyShape *getEmptyShape(JSContext *cx, gc::AllocKind kind);
|
||||
|
||||
/*
|
||||
* Get or create a property of this object. Only call this for properties which
|
||||
|
|
|
@ -4419,10 +4419,6 @@ DefineConstructorAndPrototype(JSContext *cx, JSObject *obj, JSProtoKey key, JSAt
|
|||
if (clasp == &ArrayClass && !proto->makeDenseArraySlow(cx))
|
||||
return NULL;
|
||||
|
||||
TypeObject *type = proto->getNewType(cx);
|
||||
if (!type || !type->getEmptyShape(cx, proto->getClass(), FINALIZE_OBJECT0))
|
||||
return NULL;
|
||||
|
||||
/* After this point, control must exit via label bad or out. */
|
||||
JSObject *ctor;
|
||||
bool named = false;
|
||||
|
|
|
@ -1585,8 +1585,11 @@ GetInitialShapeForObject(JSContext* cx, Class *clasp, JSObject *parent,
|
|||
{
|
||||
if (clasp->isNative()) {
|
||||
/* Share empty shapes on the type only if the object is similar to the proto. */
|
||||
if (type->canProvideEmptyShape(clasp) && parent == type->proto->getParent())
|
||||
return type->getEmptyShape(cx, clasp, kind);
|
||||
if (type->proto &&
|
||||
clasp == type->proto->getClass() &&
|
||||
parent == type->proto->getParent()) {
|
||||
return type->getEmptyShape(cx, kind);
|
||||
}
|
||||
|
||||
return EmptyShape::create(cx, clasp, parent, gc::GetGCKindSlots(kind, clasp));
|
||||
}
|
||||
|
|
|
@ -58,14 +58,14 @@
|
|||
#include "jsobjinlines.h"
|
||||
|
||||
inline js::EmptyShape *
|
||||
js::types::TypeObject::getEmptyShape(JSContext *cx, js::Class *aclasp, gc::AllocKind kind)
|
||||
js::types::TypeObject::getEmptyShape(JSContext *cx, gc::AllocKind kind)
|
||||
{
|
||||
JS_ASSERT(!singleton);
|
||||
|
||||
/*
|
||||
* Empty shapes can only be on the default 'new' type for a prototype.
|
||||
* Objects with a common prototype use the same shape lineage, even if
|
||||
* their prototypes differ.
|
||||
* their types differ.
|
||||
*/
|
||||
JS_ASSERT(proto->hasNewType(this));
|
||||
|
||||
|
@ -73,38 +73,17 @@ js::types::TypeObject::getEmptyShape(JSContext *cx, js::Class *aclasp, gc::Alloc
|
|||
emptyShapes = cx->new_<ShapeKindArray>();
|
||||
if (!emptyShapes)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Always fill in the first empty shape, so canProvideEmptyShape works.
|
||||
* Other empty shapes are filled in lazily.
|
||||
*/
|
||||
Shape *first = EmptyShape::create(cx, aclasp, proto->getParent(), 0);
|
||||
if (!first) {
|
||||
cx->delete_(emptyShapes);
|
||||
emptyShapes = NULL;
|
||||
return NULL;
|
||||
}
|
||||
emptyShapes->get(gc::FINALIZE_OBJECT0) = first;
|
||||
}
|
||||
|
||||
JS_ASSERT(aclasp == emptyShapes->get(gc::FINALIZE_OBJECT0)->getObjectClass());
|
||||
|
||||
Shape *&empty = emptyShapes->get(kind);
|
||||
if (!empty) {
|
||||
empty = EmptyShape::create(cx, aclasp, proto->getParent(),
|
||||
gc::GetGCKindSlots(kind, aclasp));
|
||||
empty = EmptyShape::create(cx, proto->getClass(), proto->getParent(),
|
||||
gc::GetGCKindSlots(kind, proto->getClass()));
|
||||
}
|
||||
|
||||
return static_cast<EmptyShape *>(empty);
|
||||
}
|
||||
|
||||
inline bool
|
||||
js::types::TypeObject::canProvideEmptyShape(js::Class *aclasp)
|
||||
{
|
||||
return proto && !singleton &&
|
||||
(!emptyShapes || emptyShapes->get(gc::FINALIZE_OBJECT0)->getObjectClass() == aclasp);
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSObject::updateFlags(JSContext *cx, jsid id, bool isDefinitelyAtom)
|
||||
{
|
||||
|
|
|
@ -107,10 +107,6 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
|
|||
if (!objectProto->setNewTypeUnknown(cx))
|
||||
return NULL;
|
||||
|
||||
types::TypeObject *objectType = objectProto->getNewType(cx);
|
||||
if (!objectType || !objectType->getEmptyShape(cx, &ObjectClass, gc::FINALIZE_OBJECT0))
|
||||
return NULL;
|
||||
|
||||
/* Create |Function.prototype| next so we can create other functions. */
|
||||
JSFunction *functionProto;
|
||||
{
|
||||
|
@ -144,10 +140,6 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
|
|||
|
||||
if (!proto->setNewTypeUnknown(cx))
|
||||
return NULL;
|
||||
|
||||
types::TypeObject *functionType = proto->getNewType(cx);
|
||||
if (!functionType || !functionType->getEmptyShape(cx, &FunctionClass, gc::FINALIZE_OBJECT0))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Create the Object function now that we have a [[Prototype]] for it. */
|
||||
|
@ -382,14 +374,6 @@ CreateBlankProto(JSContext *cx, Class *clasp, JSObject &proto, GlobalObject &glo
|
|||
if (!blankProto || !blankProto->setSingletonType(cx))
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Supply the created prototype object with an empty shape for the benefit
|
||||
* of callers of JSObject::initSharingEmptyShape.
|
||||
*/
|
||||
types::TypeObject *type = blankProto->getNewType(cx);
|
||||
if (!type || !type->getEmptyShape(cx, clasp, gc::FINALIZE_OBJECT0))
|
||||
return NULL;
|
||||
|
||||
return blankProto;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче