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
Родитель 8ce5c1241b
Коммит 2140481adb
12 изменённых файлов: 157 добавлений и 150 удалений

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -1444,9 +1444,9 @@ js::NewObjectWithClassProtoCommon(ExclusiveContext *cxArg,
* Create a plain object with the specified type. This bypasses getNewType to * Create a plain object with the specified type. This bypasses getNewType to
* avoid losing creation site information for objects made by scripted 'new'. * avoid losing creation site information for objects made by scripted 'new'.
*/ */
static JSObject * JSObject *
NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind, js::NewObjectWithType(JSContext *cx, HandleTypeObject type, JSObject *parent, gc::AllocKind allocKind,
NewObjectKind newKind = GenericObject) NewObjectKind newKind)
{ {
JS_ASSERT(type->proto->hasNewType(&JSObject::class_, type)); JS_ASSERT(type->proto->hasNewType(&JSObject::class_, type));
JS_ASSERT(parent); JS_ASSERT(parent);
@ -1502,46 +1502,6 @@ js::NewObjectScriptedCall(JSContext *cx, MutableHandleObject pobj)
return true; 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* JSObject*
js::CreateThis(JSContext *cx, const Class *newclasp, HandleObject callee) 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); uint32_t slot = GlobalObject::constructorPropertySlot(key);
if (!JSObject::addProperty(cx, obj, id, JS_PropertyStub, JS_StrictPropertyStub, slot, attrs, 0, 0)) if (!JSObject::addProperty(cx, obj, id, JS_PropertyStub, JS_StrictPropertyStub, slot, attrs, 0, 0))
return false; return false;
AddTypePropertyId(cx, obj, id, v);
named = true; named = true;
return true; return true;
@ -3433,7 +3392,7 @@ CallAddPropertyHook(typename ExecutionModeTraits<mode>::ExclusiveContextType cxA
} }
if (value.get() != nominal) { if (value.get() != nominal) {
if (shape->hasSlot()) if (shape->hasSlot())
JSObject::nativeSetSlotWithType(cx, obj, shape, value); obj->nativeSetSlotWithType(cx, shape, value);
} }
} }
return true; return true;
@ -3475,16 +3434,43 @@ CallAddPropertyHookDense(typename ExecutionModeTraits<mode>::ExclusiveContextTyp
Rooted<jsid> id(cx, INT_TO_JSID(index)); Rooted<jsid> id(cx, INT_TO_JSID(index));
if (!CallJSPropertyOp(cx->asJSContext(), clasp->addProperty, obj, id, &value)) { if (!CallJSPropertyOp(cx->asJSContext(), clasp->addProperty, obj, id, &value)) {
JSObject::setDenseElementHole(cx, obj, index); obj->setDenseElementHole(cx, index);
return false; return false;
} }
if (value.get() != nominal) if (value.get() != nominal)
JSObject::setDenseElementWithType(cx, obj, index, value); obj->setDenseElementWithType(cx, index, value);
} }
return true; 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> template <ExecutionMode mode>
static inline bool static inline bool
DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType cx, DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType cx,
@ -3519,7 +3505,12 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
if (result == JSObject::ED_FAILED) if (result == JSObject::ED_FAILED)
return false; return false;
if (result == JSObject::ED_OK) { 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); return CallAddPropertyHookDense<mode>(cx, obj->getClass(), obj, index, value);
} }
} }
@ -3551,8 +3542,8 @@ DefinePropertyOrElement(typename ExecutionModeTraits<mode>::ExclusiveContextType
if (!shape) if (!shape)
return false; return false;
if (shape->hasSlot()) if (!UpdateShapeTypeAndValue<mode>(cx, obj, shape, value))
obj->nativeSetSlot(shape->slot(), value); return false;
/* /*
* Clear any existing dense index after adding a sparse indexed property, * 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, PropertyOp getter, StrictPropertyOp setter, unsigned attrs,
unsigned flags, int shortid, unsigned defineHow /* = 0 */) 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)); JS_ASSERT(!(attrs & JSPROP_NATIVE_ACCESSORS));
AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter); AutoRooterGetterSetter gsRoot(cx, attrs, &getter, &setter);
@ -3608,10 +3599,6 @@ js::DefineNativeProperty(ExclusiveContext *cx, HandleObject obj, HandleId id, Ha
*/ */
RootedShape shape(cx); RootedShape shape(cx);
if (attrs & (JSPROP_GETTER | JSPROP_SETTER)) { 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 * If we are defining a getter whose setter was already defined, or
* vice versa, finish the job via obj->changeProperty. * 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)) if (!setter && !(attrs & JSPROP_SETTER))
setter = clasp->setProperty; 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) { if (!shape) {
return DefinePropertyOrElement<SequentialExecution>(cx, obj, id, getter, setter, return DefinePropertyOrElement<SequentialExecution>(cx, obj, id, getter, setter,
attrs, flags, shortid, value, attrs, flags, shortid, value,
false, false); false, false);
} }
if (shape->hasSlot()) JS_ALWAYS_TRUE(UpdateShapeTypeAndValue<SequentialExecution>(cx, obj, shape, value));
obj->nativeSetSlot(shape->slot(), value);
return CallAddPropertyHook<SequentialExecution>(cx, clasp, 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)) if (!obj->nativeSetSlotIfHasType(shape, vp))
return false; return false;
} else { } else {
obj->nativeSetSlotWithType(cxArg->asExclusiveContext(), obj, shape, vp); obj->nativeSetSlotWithType(cxArg->asExclusiveContext(), shape, vp);
} }
return true; return true;
@ -4199,8 +4175,7 @@ js::NativeSet(typename ExecutionModeTraits<mode>::ContextType cxArg,
if (shape->hasSlot() && if (shape->hasSlot() &&
(JS_LIKELY(cx->runtime()->propertyRemovals == sample) || (JS_LIKELY(cx->runtime()->propertyRemovals == sample) ||
obj->nativeContains(cx, shape))) obj->nativeContains(cx, shape)))
{ {
AddTypePropertyId(cx, obj, shape->propid(), ovp);
obj->setSlot(shape->slot(), vp); obj->setSlot(shape->slot(), vp);
} }
@ -4244,10 +4219,6 @@ GetPropertyHelperInline(JSContext *cx,
return false; 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 * Give a strict warning if foo.bar is evaluated by a script for an
* object foo with no property named 'bar'. * object foo with no property named 'bar'.
@ -4832,7 +4803,7 @@ baseops::SetPropertyHelper(typename ExecutionModeTraits<mode>::ContextType cxArg
if (mode == ParallelExecution) if (mode == ParallelExecution)
obj->setDenseElementIfHasType(index, vp); obj->setDenseElementIfHasType(index, vp);
else else
JSObject::setDenseElementWithType(cxArg->asJSContext(), obj, index, vp); obj->setDenseElementWithType(cxArg->asJSContext(), index, vp);
return true; 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. */ /* Purge the property cache of now-shadowed id in obj's scope chain. */
if (!PurgeScopeChain(cx, obj, id)) if (!PurgeScopeChain(cx, obj, id))
return false; return false;
if (getter == JS_PropertyStub)
AddTypePropertyId(cx, obj, id, vp);
} }
return DefinePropertyOrElement<mode>(cxArg, obj, id, getter, setter, return DefinePropertyOrElement<mode>(cxArg, obj, id, getter, setter,
@ -4939,9 +4907,15 @@ baseops::SetAttributes(JSContext *cx, HandleObject obj, HandleId id, unsigned *a
return false; return false;
shape = obj->nativeLookup(cx, id); shape = obj->nativeLookup(cx, id);
} }
return nobj->isNative() if (nobj->isNative()) {
? JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp) if (!JSObject::changePropertyAttributes(cx, nobj, shape, *attrsp))
: JSObject::setGenericAttributes(cx, nobj, id, attrsp); return false;
if (*attrsp & JSPROP_READONLY)
MarkTypePropertyConfigured(cx, obj, id);
return true;
} else {
return JSObject::setGenericAttributes(cx, nobj, id, attrsp);
}
} }
bool bool
@ -4967,7 +4941,7 @@ baseops::DeleteGeneric(JSContext *cx, HandleObject obj, HandleId id, bool *succe
if (!succeeded) if (!succeeded)
return true; return true;
JSObject::setDenseElementHole(cx, obj, JSID_TO_INT(id)); obj->setDenseElementHole(cx, JSID_TO_INT(id));
return js_SuppressDeletedProperty(cx, obj, id); return js_SuppressDeletedProperty(cx, obj, id);
} }

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

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

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

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

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

@ -23,8 +23,6 @@ ArrayObject::setLength(ExclusiveContext *cx, Handle<ArrayObject*> arr, uint32_t
if (length > INT32_MAX) { if (length > INT32_MAX) {
/* Track objects with overflowing lengths in type information. */ /* Track objects with overflowing lengths in type information. */
types::MarkTypeObjectFlags(cx, arr, types::OBJECT_FLAG_LENGTH_OVERFLOW); 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; arr->getElementsHeader()->length = length;

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

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

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

@ -673,6 +673,61 @@ JSObject::addPropertyInternal<ParallelExecution>(ForkJoinSlice *cx,
unsigned flags, int shortid, Shape **spp, unsigned flags, int shortid, Shape **spp,
bool allowDictionary); 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 * 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 * 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()); 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) if (getter == JS_PropertyStub)
getter = nullptr; getter = nullptr;
if (setter == JS_StrictPropertyStub) if (setter == JS_StrictPropertyStub)