Bug 935324 - Clean up adding of type properties to objects, r=jandem.

This commit is contained in:
Brian Hackett 2013-11-07 11:12:15 -08:00
parent 8ce5c1241b
commit 2140481adb
12 changed files with 157 additions and 150 deletions

View File

@ -1976,7 +1976,7 @@ AnalyzePoppedThis(JSContext *cx, types::TypeObject *type,
RootedId id(cx, NameToId(setprop->name()));
RootedValue value(cx, UndefinedValue());
if (!DefineNativeProperty(cx, baseobj, id, value, nullptr, nullptr,
JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE))
JSPROP_ENUMERATE, 0, 0))
{
return false;
}

View File

@ -6310,14 +6310,9 @@ IonBuilder::setStaticName(JSObject *staticObject, PropertyName *name)
// If the property has a known type, we may be able to optimize typed stores by not
// storing the type tag.
MIRType slotType = MIRType_None;
{
Shape *shape = staticObject->nativeLookup(cx, id);
if (!shape || !shape->hasSlot() || !staticObject->getSlot(shape->slot()).isUndefined()) {
JSValueType knownType = property.knownTypeTag(constraints());
if (knownType != JSVAL_TYPE_UNKNOWN)
slotType = MIRTypeFromValueType(knownType);
}
}
JSValueType knownType = property.knownTypeTag(constraints());
if (knownType != JSVAL_TYPE_UNKNOWN)
slotType = MIRTypeFromValueType(knownType);
bool needsBarrier = property.needsBarrier(constraints());
return storeSlot(obj, property.maybeTypes()->definiteSlot(), NumFixedSlots(staticObject),

View File

@ -462,7 +462,7 @@ SetProperty(JSContext *cx, HandleObject obj, HandlePropertyName name, HandleValu
// required for initializing 'const' closure variables.
Shape *shape = obj->nativeLookup(cx, name);
JS_ASSERT(shape && shape->hasSlot());
JSObject::nativeSetSlotWithType(cx, obj, shape, value);
obj->nativeSetSlotWithType(cx, shape, value);
return true;
}

View File

@ -286,7 +286,7 @@ SetArrayElement(JSContext *cx, HandleObject obj, double index, HandleValue v)
break;
if (idx >= arr->length())
arr->setLengthInt32(idx + 1);
JSObject::setDenseElementWithType(cx, arr, idx, v);
arr->setDenseElementWithType(cx, idx, v);
return true;
} while (false);
@ -677,14 +677,12 @@ js::ArraySetLength(typename ExecutionModeTraits<mode>::ContextType cxArg,
RootedValue v(cxArg, NumberValue(newLen));
if (mode == ParallelExecution) {
// Adding the property type or overflowing int32 requires changing TI
// state.
if (!HasTypePropertyId(arr, id, v) || newLen > INT32_MAX)
// Overflowing int32 requires changing TI state.
if (newLen > INT32_MAX)
return false;
arr->setLengthInt32(newLen);
} else {
JSContext *cx = cxArg->asJSContext();
AddTypePropertyId(cx, arr, id, v);
ArrayObject::setLength(cx, arr, newLen);
}
@ -2022,7 +2020,7 @@ NewbornArrayPushImpl(JSContext *cx, HandleObject obj, const Value &v)
arr->setDenseInitializedLength(length + 1);
arr->setLengthInt32(length + 1);
JSObject::initDenseElementWithType(cx, arr, length, v);
arr->initDenseElementWithType(cx, length, v);
return true;
}
@ -2066,7 +2064,7 @@ js::array_push(JSContext *cx, unsigned argc, Value *vp)
if (result == JSObject::ED_OK) {
for (uint32_t i = 0, index = length; i < argCount; index++, i++)
JSObject::setDenseElementWithType(cx, obj, index, args[i]);
obj->setDenseElementWithType(cx, index, args[i]);
uint32_t newlength = length + argCount;
args.rval().setNumber(newlength);
if (obj->is<ArrayObject>()) {

View File

@ -1000,7 +1000,7 @@ class ConstraintDataFreeze
const char *kind() { return "freeze"; }
bool invalidateOnNewType(Type type) { return true; }
bool invalidateOnNewPropertyState(TypeSet *property) { return false; }
bool invalidateOnNewPropertyState(TypeSet *property) { return true; }
bool invalidateOnNewObjectState(TypeObject *object) { return false; }
bool constraintHolds(JSContext *cx,
@ -1103,7 +1103,7 @@ HeapTypeSetKey::knownTypeTag(CompilerConstraintList *constraints)
bool
HeapTypeSetKey::isOwnProperty(CompilerConstraintList *constraints)
{
if (maybeTypes() && !maybeTypes()->empty())
if (maybeTypes() && (!maybeTypes()->empty() || maybeTypes()->configuredProperty()))
return true;
if (JSObject *obj = object()->singleton()) {
if (CanHaveEmptyPropertyTypesForOwnProperty(obj))
@ -1138,9 +1138,9 @@ TemporaryTypeSet::getSingleton()
JSObject *
HeapTypeSetKey::singleton(CompilerConstraintList *constraints)
{
TypeSet *types = maybeTypes();
HeapTypeSet *types = maybeTypes();
if (!types || types->baseFlags() != 0 || types->getObjectCount() != 1)
if (!types || types->configuredProperty() || types->baseFlags() != 0 || types->getObjectCount() != 1)
return nullptr;
JSObject *obj = types->getSingleObject(0);

View File

@ -536,7 +536,7 @@ MarkTypeObjectUnknownProperties(JSContext *cx, TypeObject *obj,
* have a getter/setter.
*/
inline void
MarkTypePropertyConfigured(ExclusiveContext *cx, HandleObject obj, jsid id)
MarkTypePropertyConfigured(ExclusiveContext *cx, JSObject *obj, jsid id)
{
if (cx->typeInferenceEnabled()) {
id = IdToTypeId(id);

View File

@ -1444,9 +1444,9 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg,
* Create a plain object with the specified type. This bypasses getNewType to
* avoid losing creation site information for objects made by scripted 'new'.
*/
static JSObject *
NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
NewObjectKind newKind = GenericObject)
JSObject *
js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
NewObjectKind newKind)
{
JS_ASSERT(type->proto->hasNewType(&JSObject::class_, type));
JS_ASSERT(parent);
@ -1502,46 +1502,6 @@ js::NewObjectScriptedCall(JSContext *cx, MutableHandleObject pobj)
return true;
}
JSObject *
js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
gc::AllocKind allocKind, HandleShape shape, NewObjectKind newKind)
{
RootedObject res(cx, NewObjectWithType(cx, type, parent, allocKind, newKind));
if (!res)
return nullptr;
if (shape->isEmptyShape())
return res;
/* Get all the ids in the object, in order. */
js::AutoIdVector ids(cx);
{
for (unsigned i = 0; i <= shape->slot(); i++) {
if (!ids.append(JSID_VOID))
return nullptr;
}
Shape *nshape = shape;
while (!nshape->isEmptyShape()) {
ids[nshape->slot()] = nshape->propid();
nshape = nshape->previous();
}
}
/* Construct the new shape. */
RootedId id(cx);
RootedValue undefinedValue(cx, UndefinedValue());
for (unsigned i = 0; i < ids.length(); i++) {
id = ids[i];
if (!DefineNativeProperty(cx, res, id, undefinedValue, nullptr, nullptr,
JSPROP_ENUMERATE, 0, 0, DNP_SKIP_TYPE)) {
return nullptr;
}
}
JS_ASSERT(!res->inDictionaryMode());
return res;
}
JSObject*
js::CreateThis(JSContext *cx, const Class *newclasp, HandleObject callee)
{
@ -2226,7 +2186,6 @@ DefineStandardSlot(JSContext *cx, HandleObject obj, JSProtoKey key, JSAtom *atom
uint32_t slot = GlobalObject::constructorPropertySlot(key);
if (!JSObject::addProperty(cx, obj, id, JS_PropertyStub, JS_StrictPropertyStub, slot, attrs, 0, 0))
return false;
AddTypePropertyId(cx, obj, id, v);
named = true;
return true;
@ -3433,7 +3392,7 @@ CallAddPropertyHook(typename ExecutionModeTraits<mode>::ExclusiveContextType cxA
}
if (value.get() != nominal) {
if (shape->hasSlot())
JSObject::nativeSetSlotWithType(cx, obj, shape, value);
obj->nativeSetSlotWithType(cx, shape, value);
}
}
return true;
@ -3475,16 +3434,43 @@ CallAddPropertyHookDense(typename ExecutionModeTraits<mode>::ExclusiveContextTyp
Rooted<jsid> id(cx, INT_TO_JSID(index));
if (!CallJSPropertyOp(cx->asJSContext(), clasp->addProperty, obj, id, &value)) {
JSObject::setDenseElementHole(cx, obj, index);
obj->setDenseElementHole(cx, index);
return false;
}
if (value.get() != nominal)
JSObject::setDenseElementWithType(cx, obj, index, value);
obj->setDenseElementWithType(cx, index, value);
}
return true;
}
template <ExecutionMode mode>
static bool
UpdateShapeTypeAndValue(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
JSObject *obj, Shape *shape, const Value &value)
{
jsid id = shape->propid();
if (shape->hasSlot()) {
if (mode == ParallelExecution) {
if (!obj->nativeSetSlotIfHasType(shape, value))
return false;
} else {
obj->nativeSetSlotWithType(cx->asExclusiveContext(), shape, value);
}
}
if (!shape->hasSlot() || !shape->writable() ||
!shape->hasDefaultGetter() || !shape->hasDefaultSetter())
{
if (mode == ParallelExecution) {
if (!IsTypePropertyIdMarkedConfigured(obj, id))
return false;
} else {
MarkTypePropertyConfigured(cx->asExclusiveContext(), obj, id);
}
}
return true;
}
template <ExecutionMode mode>
static inline bool
DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
@ -3519,7 +3505,12 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
if (result == JSObject::ED_FAILED)
return false;
if (result == JSObject::ED_OK) {
obj->setDenseElementMaybeConvertDouble(index, value);
if (mode == ParallelExecution) {
if (!obj->setDenseElementIfHasType(index, value))
return false;
} else {
obj->setDenseElementWithType(cx->asExclusiveContext(), index, value);
}
return CallAddPropertyHookDense<mode>(cx, obj->getClass(), obj, index, value);
}
}
@ -3551,8 +3542,8 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
if (!shape)
return false;
if (shape->hasSlot())
obj->nativeSetSlot(shape->slot(), value);
if (!UpdateShapeTypeAndValue<mode>(cx, obj, shape, value))
return false;
/*
* Clear any existing dense index after adding a sparse indexed property,
@ -3596,7 +3587,7 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, Ha
PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow /* = 0 */)
{
JS_ASSERT((defineHow & ~(DNP_DONT_PURGE | DNP_SKIP_TYPE)) == 0);
JS_ASSERT((defineHow & ~DNP_DONT_PURGE) == 0);
JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
@ -3608,10 +3599,6 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, Ha
*/
RootedShape shape(cx);
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
/* Type information for getter/setter properties is unknown. */
AddTypePropertyId(cx, obj, id, types::Type::UnknownType());
MarkTypePropertyConfigured(cx, obj, id);
/*
* If we are defining a getter whose setter was already defined, or
* vice versa, finish the job via obj->changeProperty.
@ -3658,24 +3645,13 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, Ha
if (!setter && !(attrs & JSPROP_SETTER))
setter = clasp->setProperty;
if ((getter == JS_PropertyStub) && !(defineHow & DNP_SKIP_TYPE)) {
/*
* Type information for normal native properties should reflect the
* initial value of the property.
*/
AddTypePropertyId(cx, obj, id, value);
if (attrs & JSPROP_READONLY)
MarkTypePropertyConfigured(cx, obj, id);
}
if (!shape) {
return DefinePropertyOrElement<SequentialExecution>(cx, obj, id, getter, setter,
attrs, flags, shortid, value,
false, false);
}
if (shape->hasSlot())
obj->nativeSetSlot(shape->slot(), value);
JS_ALWAYS_TRUE(UpdateShapeTypeAndValue<SequentialExecution>(cx, obj, shape, value));
return CallAddPropertyHook<SequentialExecution>(cx, clasp, obj, shape, value);
}
@ -4164,7 +4140,7 @@ js::NativeSet(typename ExecutionModeTraits<mode>::ContextType cxArg,
if (!obj->nativeSetSlotIfHasType(shape, vp))
return false;
} else {
obj->nativeSetSlotWithType(cxArg->asExclusiveContext(), obj, shape, vp);
obj->nativeSetSlotWithType(cxArg->asExclusiveContext(), shape, vp);
}
return true;
@ -4199,8 +4175,7 @@ js::NativeSet(typename ExecutionModeTraits<mode>::ContextType cxArg,
if (shape->hasSlot() &&
(JS_LIKELY(cx->runtime()->propertyRemovals == sample) ||
obj->nativeContains(cx, shape)))
{
AddTypePropertyId(cx, obj, shape->propid(), ovp);
{
obj->setSlot(shape->slot(), vp);
}
@ -4244,10 +4219,6 @@ GetPropertyHelperInline(JSContext *cx,
return false;
}
/* Record non-undefined values produced by the class getter hook. */
if (!vp.isUndefined())
AddTypePropertyId(cx, obj, id, vp);
/*
* Give a strict warning if foo.bar is evaluated by a script for an
* object foo with no property named 'bar'.
@ -4832,7 +4803,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
if (mode == ParallelExecution)
obj->setDenseElementIfHasType(index, vp);
else
JSObject::setDenseElementWithType(cxArg->asJSContext(), obj, index, vp);
obj->setDenseElementWithType(cxArg->asJSContext(), index, vp);
return true;
}
@ -4873,9 +4844,6 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
/* Purge the property cache of now-shadowed id in obj's scope chain. */
if (!PurgeScopeChain(cx, obj, id))
return false;
if (getter == JS_PropertyStub)
AddTypePropertyId(cx, obj, id, vp);
}
return DefinePropertyOrElement<mode>(cxArg, obj, id, getter, setter,
@ -4939,9 +4907,15 @@ baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a
return false;
shape = obj->nativeLookup(cx, id);
}
return nobj->isNative()
? JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp)
: JSObject::setGenericAttributes(cx, nobj, id, attrsp);
if (nobj->isNative()) {
if (!JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp))
return false;
if (*attrsp & JSPROP_READONLY)
MarkTypePropertyConfigured(cx, obj, id);
return true;
} else {
return JSObject::setGenericAttributes(cx, nobj, id, attrsp);
}
}
bool
@ -4967,7 +4941,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succe
if (!succeeded)
return true;
JSObject::setDenseElementHole(cx, obj, JSID_TO_INT(id));
obj->setDenseElementHole(cx, JSID_TO_INT(id));
return js_SuppressDeletedProperty(cx, obj, id);
}

View File

@ -415,10 +415,8 @@ class JSObject : public js::ObjectImpl
}
inline bool nativeSetSlotIfHasType(js::Shape *shape, const js::Value &value);
static inline void nativeSetSlotWithType(js::ExclusiveContext *cx,
js::HandleObject, js::Shape *shape,
const js::Value &value);
inline void nativeSetSlotWithType(js::ExclusiveContext *cx, js::Shape *shape,
const js::Value &value);
inline const js::Value &getReservedSlot(uint32_t index) const {
JS_ASSERT(index < JSSLOT_FREE(getClass()));
@ -648,12 +646,11 @@ class JSObject : public js::ObjectImpl
}
inline bool setDenseElementIfHasType(uint32_t index, const js::Value &val);
static inline void setDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj,
uint32_t index, const js::Value &val);
static inline void initDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj,
uint32_t index, const js::Value &val);
static inline void setDenseElementHole(js::ExclusiveContext *cx,
js::HandleObject obj, uint32_t index);
inline void setDenseElementWithType(js::ExclusiveContext *cx, uint32_t index,
const js::Value &val);
inline void initDenseElementWithType(js::ExclusiveContext *cx, uint32_t index,
const js::Value &val);
inline void setDenseElementHole(js::ExclusiveContext *cx, uint32_t index);
static inline void removeDenseElementForSparseIndex(js::ExclusiveContext *cx,
js::HandleObject obj, uint32_t index);
@ -1404,7 +1401,6 @@ const unsigned DNP_DONT_PURGE = 1; /* suppress js_PurgeScopeChain */
const unsigned DNP_UNQUALIFIED = 2; /* Unqualified property set. Only used in
the defineHow argument of
js_SetPropertyHelper. */
const unsigned DNP_SKIP_TYPE = 4; /* Don't update type information */
/*
* Return successfully added or changed shape or nullptr on error.

View File

@ -43,7 +43,6 @@ JSObject::deleteProperty(JSContext *cx, js::HandleObject obj, js::HandleProperty
bool *succeeded)
{
JS::RootedId id(cx, js::NameToId(name));
js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
js::types::MarkTypePropertyConfigured(cx, obj, id);
js::DeletePropertyOp op = obj->getOps()->deleteProperty;
return (op ? op : js::baseops::DeleteProperty)(cx, obj, name, succeeded);
@ -55,7 +54,6 @@ JSObject::deleteElement(JSContext *cx, js::HandleObject obj, uint32_t index, boo
JS::RootedId id(cx);
if (!js::IndexToId(cx, index, &id))
return false;
js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
js::types::MarkTypePropertyConfigured(cx, obj, id);
js::DeleteElementOp op = obj->getOps()->deleteElement;
return (op ? op : js::baseops::DeleteElement)(cx, obj, index, succeeded);
@ -66,7 +64,6 @@ JSObject::deleteSpecial(JSContext *cx, js::HandleObject obj, js::HandleSpecialId
bool *succeeded)
{
JS::RootedId id(cx, SPECIALID_TO_JSID(sid));
js::types::AddTypePropertyId(cx, obj, id, js::types::Type::UndefinedType());
js::types::MarkTypePropertyConfigured(cx, obj, id);
js::DeleteSpecialOp op = obj->getOps()->deleteSpecial;
return (op ? op : js::baseops::DeleteSpecial)(cx, obj, sid, succeeded);
@ -160,32 +157,32 @@ JSObject::setDenseElementIfHasType(uint32_t index, const js::Value &val)
return true;
}
/* static */ inline void
JSObject::setDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index,
inline void
JSObject::setDenseElementWithType(js::ExclusiveContext *cx, uint32_t index,
const js::Value &val)
{
// Avoid a slow AddTypePropertyId call if the type is the same as the type
// of the previous element.
js::types::Type thisType = js::types::GetValueType(val);
if (index == 0 || js::types::GetValueType(obj->elements[index - 1]) != thisType)
js::types::AddTypePropertyId(cx, obj, JSID_VOID, thisType);
obj->setDenseElementMaybeConvertDouble(index, val);
if (index == 0 || js::types::GetValueType(elements[index - 1]) != thisType)
js::types::AddTypePropertyId(cx, this, JSID_VOID, thisType);
setDenseElementMaybeConvertDouble(index, val);
}
/* static */ inline void
JSObject::initDenseElementWithType(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index,
inline void
JSObject::initDenseElementWithType(js::ExclusiveContext *cx, uint32_t index,
const js::Value &val)
{
JS_ASSERT(!obj->shouldConvertDoubleElements());
js::types::AddTypePropertyId(cx, obj, JSID_VOID, val);
obj->initDenseElement(index, val);
JS_ASSERT(!shouldConvertDoubleElements());
js::types::AddTypePropertyId(cx, this, JSID_VOID, val);
initDenseElement(index, val);
}
/* static */ inline void
JSObject::setDenseElementHole(js::ExclusiveContext *cx, js::HandleObject obj, uint32_t index)
inline void
JSObject::setDenseElementHole(js::ExclusiveContext *cx, uint32_t index)
{
js::types::MarkTypeObjectFlags(cx, obj, js::types::OBJECT_FLAG_NON_PACKED);
obj->setDenseElement(index, js::MagicValue(JS_ELEMENTS_HOLE));
js::types::MarkTypeObjectFlags(cx, this, js::types::OBJECT_FLAG_NON_PACKED);
setDenseElement(index, js::MagicValue(JS_ELEMENTS_HOLE));
}
/* static */ inline void
@ -550,12 +547,12 @@ JSObject::nativeSetSlotIfHasType(js::Shape *shape, const js::Value &value)
return true;
}
/* static */ inline void
JSObject::nativeSetSlotWithType(js::ExclusiveContext *cx, js::HandleObject obj, js::Shape *shape,
inline void
JSObject::nativeSetSlotWithType(js::ExclusiveContext *cx, js::Shape *shape,
const js::Value &value)
{
obj->nativeSetSlot(shape->slot(), value);
js::types::AddTypePropertyId(cx, obj, shape->propid(), value);
nativeSetSlot(shape->slot(), value);
js::types::AddTypePropertyId(cx, this, shape->propid(), value);
}
/* static */ inline bool
@ -918,6 +915,10 @@ CopyInitializerObject(JSContext *cx, HandleObject baseobj, NewObjectKind newKind
return obj;
}
JSObject *
NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
NewObjectKind newKind = GenericObject);
JSObject *
NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
gc::AllocKind allocKind, HandleShape shape,
@ -960,7 +961,6 @@ DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
global->setPrototype(key, ObjectValue(*proto));
global->setConstructorPropertySlot(key, ObjectValue(*ctor));
types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
if (!global->addDataProperty(cx, id, GlobalObject::constructorPropertySlot(key), 0)) {
global->setConstructor(key, UndefinedValue());
global->setPrototype(key, UndefinedValue());
@ -968,6 +968,7 @@ DefineConstructorAndPrototype(JSContext *cx, Handle<GlobalObject*> global,
return false;
}
types::AddTypePropertyId(cx, global, id, ObjectValue(*ctor));
return true;
}

View File

@ -23,8 +23,6 @@ ArrayObject::setLength(ExclusiveContext *cx, Handle<ArrayObject*> arr, uint32_t
if (length > INT32_MAX) {
/* Track objects with overflowing lengths in type information. */
types::MarkTypeObjectFlags(cx, arr, types::OBJECT_FLAG_LENGTH_OVERFLOW);
jsid lengthId = NameToId(cx->names().length);
types::AddTypePropertyId(cx, arr, lengthId, types::Type::DoubleType());
}
arr->getElementsHeader()->length = length;

View File

@ -411,7 +411,7 @@ js::intrinsic_UnsafePutElements(JSContext *cx, unsigned argc, Value *vp)
if (arrobj->isNative()) {
JS_ASSERT(idx < arrobj->getDenseInitializedLength());
JSObject::setDenseElementWithType(cx, arrobj, idx, args[elemi]);
arrobj->setDenseElementWithType(cx, idx, args[elemi]);
} else {
JS_ASSERT(idx < arrobj->as<TypedArrayObject>().length());
RootedValue tmp(cx, args[elemi]);

View File

@ -673,6 +673,61 @@ JSObject::addPropertyInternal<ParallelExecution>(ForkJoinSlice *cx,
unsigned flags, int shortid, Shape **spp,
bool allowDictionary);
JSObject *
js::NewReshapedObject(JSContext *cx, HandleTypeObject type, JSObject *parent,
gc::AllocKind allocKind, HandleShape shape, NewObjectKind newKind)
{
RootedObject res(cx, NewObjectWithType(cx, type, parent, allocKind, newKind));
if (!res)
return nullptr;
if (shape->isEmptyShape())
return res;
/* Get all the ids in the object, in order. */
js::AutoIdVector ids(cx);
{
for (unsigned i = 0; i <= shape->slot(); i++) {
if (!ids.append(JSID_VOID))
return nullptr;
}
Shape *nshape = shape;
while (!nshape->isEmptyShape()) {
ids[nshape->slot()] = nshape->propid();
nshape = nshape->previous();
}
}
/* Construct the new shape, without updating type information. */
RootedId id(cx);
RootedShape newShape(cx, res->lastProperty());
for (unsigned i = 0; i < ids.length(); i++) {
id = ids[i];
JS_ASSERT(!res->nativeContains(cx, id));
uint32_t index;
bool indexed = js_IdIsIndex(id, &index);
Rooted<UnownedBaseShape*> nbase(cx, newShape->base()->toUnowned());
if (indexed) {
StackBaseShape base(nbase);
base.flags |= BaseShape::INDEXED;
nbase = GetOrLookupUnownedBaseShape<SequentialExecution>(cx, base);
if (!nbase)
return nullptr;
}
StackShape child(nbase, id, i, res->numFixedSlots(), JSPROP_ENUMERATE, 0, 0);
newShape = cx->compartment()->propertyTree.getChild(cx, newShape, res->numFixedSlots(), child);
if (!newShape)
return nullptr;
if (!JSObject::setLastProperty(cx, res, newShape))
return nullptr;
}
return res;
}
/*
* Check and adjust the new attributes for the shape to make sure that our
* slot access optimizations are sound. It is responsibility of the callers to
@ -925,16 +980,6 @@ JSObject::changeProperty(typename ExecutionModeTraits<mode>::ExclusiveContextTyp
types::MarkTypePropertyConfigured(cx->asExclusiveContext(), obj, shape->propid());
}
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) {
if (mode == ParallelExecution) {
if (!types::HasTypePropertyId(obj, shape->propid(), types::Type::UnknownType()))
return nullptr;
} else {
types::AddTypePropertyId(cx->asExclusiveContext(), obj, shape->propid(),
types::Type::UnknownType());
}
}
if (getter == JS_PropertyStub)
getter = nullptr;
if (setter == JS_StrictPropertyStub)