mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Empty shapes attached to type objects must have the same class as the prototype, bug 698150.
This commit is contained in:
parent
da034e0aac
commit
2c2283ba38
@ -814,10 +814,10 @@ struct TypeObject : gc::Cell
|
|||||||
/*
|
/*
|
||||||
* Return an immutable, shareable, empty shape for objects with this type
|
* Return an immutable, shareable, empty shape for objects with this type
|
||||||
* and the specified class, and finalize kind (fixed slot count). Objects
|
* 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, gc::AllocKind kind);
|
||||||
inline js::EmptyShape *getEmptyShape(JSContext *cx, js::Class *aclasp, gc::AllocKind kind);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get or create a property of this object. Only call this for properties which
|
* 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))
|
if (clasp == &ArrayClass && !proto->makeDenseArraySlow(cx))
|
||||||
return NULL;
|
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. */
|
/* After this point, control must exit via label bad or out. */
|
||||||
JSObject *ctor;
|
JSObject *ctor;
|
||||||
bool named = false;
|
bool named = false;
|
||||||
|
@ -1585,8 +1585,11 @@ GetInitialShapeForObject(JSContext* cx, Class *clasp, JSObject *parent,
|
|||||||
{
|
{
|
||||||
if (clasp->isNative()) {
|
if (clasp->isNative()) {
|
||||||
/* Share empty shapes on the type only if the object is similar to the proto. */
|
/* Share empty shapes on the type only if the object is similar to the proto. */
|
||||||
if (type->canProvideEmptyShape(clasp) && parent == type->proto->getParent())
|
if (type->proto &&
|
||||||
return type->getEmptyShape(cx, clasp, kind);
|
clasp == type->proto->getClass() &&
|
||||||
|
parent == type->proto->getParent()) {
|
||||||
|
return type->getEmptyShape(cx, kind);
|
||||||
|
}
|
||||||
|
|
||||||
return EmptyShape::create(cx, clasp, parent, gc::GetGCKindSlots(kind, clasp));
|
return EmptyShape::create(cx, clasp, parent, gc::GetGCKindSlots(kind, clasp));
|
||||||
}
|
}
|
||||||
|
@ -58,14 +58,14 @@
|
|||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
inline js::EmptyShape *
|
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);
|
JS_ASSERT(!singleton);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Empty shapes can only be on the default 'new' type for a prototype.
|
* 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
|
* Objects with a common prototype use the same shape lineage, even if
|
||||||
* their prototypes differ.
|
* their types differ.
|
||||||
*/
|
*/
|
||||||
JS_ASSERT(proto->hasNewType(this));
|
JS_ASSERT(proto->hasNewType(this));
|
||||||
|
|
||||||
@ -73,38 +73,17 @@ js::types::TypeObject::getEmptyShape(JSContext *cx, js::Class *aclasp, gc::Alloc
|
|||||||
emptyShapes = cx->new_<ShapeKindArray>();
|
emptyShapes = cx->new_<ShapeKindArray>();
|
||||||
if (!emptyShapes)
|
if (!emptyShapes)
|
||||||
return NULL;
|
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);
|
Shape *&empty = emptyShapes->get(kind);
|
||||||
if (!empty) {
|
if (!empty) {
|
||||||
empty = EmptyShape::create(cx, aclasp, proto->getParent(),
|
empty = EmptyShape::create(cx, proto->getClass(), proto->getParent(),
|
||||||
gc::GetGCKindSlots(kind, aclasp));
|
gc::GetGCKindSlots(kind, proto->getClass()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<EmptyShape *>(empty);
|
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
|
inline bool
|
||||||
JSObject::updateFlags(JSContext *cx, jsid id, bool isDefinitelyAtom)
|
JSObject::updateFlags(JSContext *cx, jsid id, bool isDefinitelyAtom)
|
||||||
{
|
{
|
||||||
|
@ -107,10 +107,6 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
|
|||||||
if (!objectProto->setNewTypeUnknown(cx))
|
if (!objectProto->setNewTypeUnknown(cx))
|
||||||
return NULL;
|
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. */
|
/* Create |Function.prototype| next so we can create other functions. */
|
||||||
JSFunction *functionProto;
|
JSFunction *functionProto;
|
||||||
{
|
{
|
||||||
@ -144,10 +140,6 @@ GlobalObject::initFunctionAndObjectClasses(JSContext *cx)
|
|||||||
|
|
||||||
if (!proto->setNewTypeUnknown(cx))
|
if (!proto->setNewTypeUnknown(cx))
|
||||||
return NULL;
|
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. */
|
/* 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))
|
if (!blankProto || !blankProto->setSingletonType(cx))
|
||||||
return NULL;
|
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;
|
return blankProto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user