зеркало из https://github.com/mozilla/gecko-dev.git
Bug 935324 - Clean up adding of type properties to objects, r=jandem.
This commit is contained in:
Родитель
8ce5c1241b
Коммит
2140481adb
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
bool needsBarrier = property.needsBarrier(constraints());
|
||||
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.
|
||||
Shape *shape = obj->nativeLookup(cx, name);
|
||||
JS_ASSERT(shape && shape->hasSlot());
|
||||
JSObject::nativeSetSlotWithType(cx, obj, shape, value);
|
||||
obj->nativeSetSlotWithType(cx, shape, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>()) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
136
js/src/jsobj.cpp
136
js/src/jsobj.cpp
|
@ -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;
|
||||
|
@ -4200,7 +4176,6 @@ js::NativeSet(typename ExecutionModeTraits<mode>::ContextType cxArg,
|
|||
(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -415,9 +415,7 @@ 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,
|
||||
inline void nativeSetSlotWithType(js::ExclusiveContext *cx, js::Shape *shape,
|
||||
const js::Value &value);
|
||||
|
||||
inline const js::Value &getReservedSlot(uint32_t index) const {
|
||||
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче