зеркало из 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()));
|
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);
|
||||||
|
|
138
js/src/jsobj.cpp
138
js/src/jsobj.cpp
|
@ -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)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче