Backed out changeset 3c4b7e1de629 (bug 1263778) for assertion failures

This commit is contained in:
Carsten "Tomcat" Book 2016-04-28 08:37:48 +02:00
Родитель 279c1e8703
Коммит 6935ac79a5
40 изменённых файлов: 233 добавлений и 255 удалений

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

@ -37,8 +37,9 @@ public:
delete_(JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId, delete_(JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
JS::ObjectOpResult &aResult) const override; JS::ObjectOpResult &aResult) const override;
// No need for getPrototypeIfOrdinary here: window named-properties objects // No need for getPrototypeIfOrdinary here: this object shouldn't have a
// have static prototypes, so this trap is never called. // lazy prototype, so this trap would never be called (and the inherited
// version, from BaseProxyHandler, just crashes).
virtual bool virtual bool
preventExtensions(JSContext* aCx, JS::Handle<JSObject*> aProxy, preventExtensions(JSContext* aCx, JS::Handle<JSObject*> aProxy,

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

@ -924,14 +924,13 @@ nsOuterWindowProxy::getPrototypeIfOrdinary(JSContext* cx,
// //
// https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-getprototypeof // https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-getprototypeof
// //
// We nonetheless can implement it with a static [[Prototype]], because // We nonetheless can implement it here using a non-"lazy" [[Prototype]],
// wrapper-class handlers (particularly, XOW in FilteringWrapper.cpp) supply // because wrapper-class handlers (particularly, XOW in FilteringWrapper.cpp)
// all non-ordinary behavior. // supply all the non-ordinary behavior.
// //
// But from a spec point of view, it's the exact same object in both cases -- // But from a spec point of view, it's the exact same object in both cases --
// only the observer's changed. So this getPrototypeIfOrdinary trap on the // only the observer's changed. So both cases *must* report non-ordinary,
// non-wrapper object *must* report non-ordinary, even if static [[Prototype]] // even if non-"lazy" [[Prototype]] usually means ordinary.
// usually means ordinary.
*isOrdinary = false; *isOrdinary = false;
return true; return true;
} }

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

@ -232,7 +232,7 @@ MapIteratorObject::createResultPair(JSContext* cx)
if (!resultPairObj) if (!resultPairObj)
return nullptr; return nullptr;
Rooted<TaggedProto> proto(cx, resultPairObj->taggedProto()); Rooted<TaggedProto> proto(cx, resultPairObj->getTaggedProto());
ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, resultPairObj->getClass(), proto); ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, resultPairObj->getClass(), proto);
if (!group) if (!group)
return nullptr; return nullptr;

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

@ -611,7 +611,7 @@ js::ObjectCreateImpl(JSContext* cx, HandleObject proto, NewObjectKind newKind,
PlainObject* PlainObject*
js::ObjectCreateWithTemplate(JSContext* cx, HandlePlainObject templateObj) js::ObjectCreateWithTemplate(JSContext* cx, HandlePlainObject templateObj)
{ {
RootedObject proto(cx, templateObj->staticPrototype()); RootedObject proto(cx, templateObj->getProto());
RootedObjectGroup group(cx, templateObj->group()); RootedObjectGroup group(cx, templateObj->group());
return ObjectCreateImpl(cx, proto, GenericObject, group); return ObjectCreateImpl(cx, proto, GenericObject, group);
} }

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

@ -1609,12 +1609,12 @@ js::RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* rx, JSObject* proto, u
return true; return true;
} }
if (!rx->hasStaticPrototype()) { if (rx->hasLazyPrototype()) {
*result = false; *result = false;
return true; return true;
} }
if (rx->staticPrototype() != proto) { if (rx->getTaggedProto().toObjectOrNull() != proto) {
*result = false; *result = false;
return true; return true;
} }

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

@ -1682,7 +1682,7 @@ TypedObject::obj_lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
return true; return true;
} }
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) { if (!proto) {
objp.set(nullptr); objp.set(nullptr);
propp.set(nullptr); propp.set(nullptr);
@ -1754,7 +1754,7 @@ TypedObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool*
} }
} }
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) { if (!proto) {
*foundp = false; *foundp = false;
return true; return true;
@ -1811,7 +1811,7 @@ TypedObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiv
} }
} }
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) { if (!proto) {
vp.setUndefined(); vp.setUndefined();
return true; return true;
@ -1839,7 +1839,7 @@ TypedObject::obj_getElement(JSContext* cx, HandleObject obj, HandleValue receive
return obj_getArrayElement(cx, typedObj, descr, index, vp); return obj_getArrayElement(cx, typedObj, descr, index, vp);
} }
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) { if (!proto) {
vp.setUndefined(); vp.setUndefined();
return true; return true;
@ -2022,7 +2022,7 @@ TypedObject::obj_deleteProperty(JSContext* cx, HandleObject obj, HandleId id, Ob
if (IsOwnId(cx, obj, id)) if (IsOwnId(cx, obj, id))
return ReportPropertyError(cx, JSMSG_CANT_DELETE, id); return ReportPropertyError(cx, JSMSG_CANT_DELETE, id);
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) if (!proto)
return result.succeed(); return result.succeed();

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

@ -530,8 +530,7 @@ class TypedObject : public JSObject
public: public:
TypedProto& typedProto() const { TypedProto& typedProto() const {
// Typed objects' prototypes can't be modified. return getProto()->as<TypedProto>();
return staticPrototype()->as<TypedProto>();
} }
TypeDescr& typeDescr() const { TypeDescr& typeDescr() const {

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

@ -785,14 +785,12 @@ IsCacheableSetPropAddSlot(JSContext* cx, JSObject* obj, Shape* oldShape,
size_t chainDepth = 0; size_t chainDepth = 0;
// Walk up the object prototype chain and ensure that all prototypes are // Walk up the object prototype chain and ensure that all prototypes are
// native, and that all prototypes have no setter defined on the property. // native, and that all prototypes have no setter defined on the property.
for (JSObject* proto = obj->staticPrototype(); proto; proto = proto->staticPrototype()) { for (JSObject* proto = obj->getProto(); proto; proto = proto->getProto()) {
chainDepth++; chainDepth++;
// if prototype is non-native, don't optimize // if prototype is non-native, don't optimize
if (!proto->isNative()) if (!proto->isNative())
return false; return false;
MOZ_ASSERT(proto->hasStaticPrototype());
// if prototype defines this property in a non-plain way, don't optimize // if prototype defines this property in a non-plain way, don't optimize
Shape* protoShape = proto->as<NativeObject>().lookup(cx, id); Shape* protoShape = proto->as<NativeObject>().lookup(cx, id);
if (protoShape && !protoShape->hasDefaultSetter()) if (protoShape && !protoShape->hasDefaultSetter())
@ -2354,13 +2352,13 @@ SetElemAddHasSameShapes(ICSetElem_DenseOrUnboxedArrayAdd* stub, JSObject* obj)
if (obj->maybeShape() != nstub->shape(0)) if (obj->maybeShape() != nstub->shape(0))
return false; return false;
JSObject* proto = obj->staticPrototype(); JSObject* proto = obj->getProto();
for (size_t i = 0; i < stub->protoChainDepth(); i++) { for (size_t i = 0; i < stub->protoChainDepth(); i++) {
if (!proto->isNative()) if (!proto->isNative())
return false; return false;
if (proto->as<NativeObject>().lastProperty() != nstub->shape(i + 1)) if (proto->as<NativeObject>().lastProperty() != nstub->shape(i + 1))
return false; return false;
proto = obj->staticPrototype(); proto = obj->getProto();
if (!proto) { if (!proto) {
if (i != stub->protoChainDepth() - 1) if (i != stub->protoChainDepth() - 1)
return false; return false;
@ -2481,12 +2479,12 @@ CanOptimizeDenseOrUnboxedArraySetElem(JSObject* obj, uint32_t index,
// Scan the prototype and shape chain to make sure that this is not the case. // Scan the prototype and shape chain to make sure that this is not the case.
if (obj->isIndexed()) if (obj->isIndexed())
return false; return false;
JSObject* curObj = obj->staticPrototype(); JSObject* curObj = obj->getProto();
while (curObj) { while (curObj) {
++*protoDepthOut; ++*protoDepthOut;
if (!curObj->isNative() || curObj->isIndexed()) if (!curObj->isNative() || curObj->isIndexed())
return false; return false;
curObj = curObj->staticPrototype(); curObj = curObj->getProto();
} }
if (*protoDepthOut > ICSetElem_DenseOrUnboxedArrayAdd::MAX_PROTO_CHAIN_DEPTH) if (*protoDepthOut > ICSetElem_DenseOrUnboxedArrayAdd::MAX_PROTO_CHAIN_DEPTH)
@ -3700,7 +3698,7 @@ TryAttachGlobalNameValueStub(JSContext* cx, HandleScript script, jsbytecode* pc,
if (current == globalLexical) { if (current == globalLexical) {
current = &globalLexical->global(); current = &globalLexical->global();
} else { } else {
JSObject* proto = current->staticPrototype(); JSObject* proto = current->getProto();
if (!proto || !proto->is<NativeObject>()) if (!proto || !proto->is<NativeObject>())
return true; return true;
current = &proto->as<NativeObject>(); current = &proto->as<NativeObject>();
@ -3775,7 +3773,7 @@ TryAttachGlobalNameAccessorStub(JSContext* cx, HandleScript script, jsbytecode*
shape = current->lookup(cx, id); shape = current->lookup(cx, id);
if (shape) if (shape)
break; break;
JSObject* proto = current->staticPrototype(); JSObject* proto = current->getProto();
if (!proto || !proto->is<NativeObject>()) if (!proto || !proto->is<NativeObject>())
return true; return true;
current = &proto->as<NativeObject>(); current = &proto->as<NativeObject>();

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

@ -133,14 +133,12 @@ GeneratePrototypeGuards(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
if (obj->hasUncacheableProto()) { if (obj->hasUncacheableProto()) {
// If the shape does not imply the proto, emit an explicit proto guard. // If the shape does not imply the proto, emit an explicit proto guard.
writer.guardProto(objId, obj->staticPrototype()); writer.guardProto(objId, obj->getProto());
} }
MOZ_ASSERT(obj->isNative() != IsCacheableDOMProxy(obj), JSObject* pobj = IsCacheableDOMProxy(obj)
"only regular objects, or DOM proxies with static prototype, " ? obj->getTaggedProto().toObjectOrNull()
"should be observed here"); : obj->getProto();
JSObject* pobj = obj->staticPrototype();
if (!pobj) if (!pobj)
return; return;
@ -149,12 +147,12 @@ GeneratePrototypeGuards(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
ObjOperandId protoId = writer.loadObject(pobj); ObjOperandId protoId = writer.loadObject(pobj);
if (pobj->isSingleton()) { if (pobj->isSingleton()) {
// Singletons can have their group's |proto| mutated directly. // Singletons can have their group's |proto| mutated directly.
writer.guardProto(protoId, pobj->staticPrototype()); writer.guardProto(protoId, pobj->getProto());
} else { } else {
writer.guardGroup(protoId, pobj->group()); writer.guardGroup(protoId, pobj->group());
} }
} }
pobj = pobj->staticPrototype(); pobj = pobj->getProto();
} }
} }
@ -197,12 +195,12 @@ EmitReadSlotResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
// The property does not exist. Guard on everything in the prototype // The property does not exist. Guard on everything in the prototype
// chain. This is guaranteed to see only Native objects because of // chain. This is guaranteed to see only Native objects because of
// CanAttachNativeGetProp(). // CanAttachNativeGetProp().
JSObject* proto = obj->taggedProto().toObjectOrNull(); JSObject* proto = obj->getTaggedProto().toObjectOrNull();
ObjOperandId lastObjId = objId; ObjOperandId lastObjId = objId;
while (proto) { while (proto) {
ObjOperandId protoId = writer.loadProto(lastObjId); ObjOperandId protoId = writer.loadProto(lastObjId);
writer.guardShape(protoId, proto->as<NativeObject>().lastProperty()); writer.guardShape(protoId, proto->as<NativeObject>().lastProperty());
proto = proto->staticPrototype(); proto = proto->getProto();
lastObjId = protoId; lastObjId = protoId;
} }
} }

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

@ -6271,7 +6271,7 @@ IonBuilder::createThisScriptedSingleton(JSFunction* target, MDefinition* callee)
return nullptr; return nullptr;
if (!templateObject->is<PlainObject>() && !templateObject->is<UnboxedPlainObject>()) if (!templateObject->is<PlainObject>() && !templateObject->is<UnboxedPlainObject>())
return nullptr; return nullptr;
if (templateObject->staticPrototype() != proto) if (templateObject->getProto() != proto)
return nullptr; return nullptr;
TypeSet::ObjectKey* templateObjectKey = TypeSet::ObjectKey::get(templateObject->group()); TypeSet::ObjectKey* templateObjectKey = TypeSet::ObjectKey::get(templateObject->group());
@ -6318,7 +6318,7 @@ IonBuilder::createThisScriptedBaseline(MDefinition* callee)
return nullptr; return nullptr;
JSObject* proto = checkNurseryObject(&protov.toObject()); JSObject* proto = checkNurseryObject(&protov.toObject());
if (proto != templateObject->staticPrototype()) if (proto != templateObject->getProto())
return nullptr; return nullptr;
TypeSet::ObjectKey* templateObjectKey = TypeSet::ObjectKey::get(templateObject->group()); TypeSet::ObjectKey* templateObjectKey = TypeSet::ObjectKey::get(templateObject->group());
@ -8106,7 +8106,7 @@ IonBuilder::testSingletonProperty(JSObject* obj, jsid id)
if (ObjectHasExtraOwnProperty(compartment, objKey, id)) if (ObjectHasExtraOwnProperty(compartment, objKey, id))
return nullptr; return nullptr;
obj = checkNurseryObject(obj->staticPrototype()); obj = checkNurseryObject(obj->getProto());
} }
return nullptr; return nullptr;

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

@ -422,14 +422,12 @@ GeneratePrototypeGuards(JSContext* cx, IonScript* ion, MacroAssembler& masm, JSO
// use objectReg in the rest of this function. // use objectReg in the rest of this function.
masm.loadPtr(Address(objectReg, JSObject::offsetOfGroup()), scratchReg); masm.loadPtr(Address(objectReg, JSObject::offsetOfGroup()), scratchReg);
Address proto(scratchReg, ObjectGroup::offsetOfProto()); Address proto(scratchReg, ObjectGroup::offsetOfProto());
masm.branchPtr(Assembler::NotEqual, proto, ImmGCPtr(obj->staticPrototype()), failures); masm.branchPtr(Assembler::NotEqual, proto, ImmGCPtr(obj->getProto()), failures);
} }
MOZ_ASSERT(obj->isNative() != IsCacheableDOMProxy(obj), JSObject* pobj = IsCacheableDOMProxy(obj)
"only regular objects, or DOM proxies with static prototype, " ? obj->getTaggedProto().toObjectOrNull()
"should be observed here"); : obj->getProto();
JSObject* pobj = obj->staticPrototype();
if (!pobj) if (!pobj)
return; return;
while (pobj != holder) { while (pobj != holder) {
@ -440,14 +438,12 @@ GeneratePrototypeGuards(JSContext* cx, IonScript* ion, MacroAssembler& masm, JSO
// Singletons can have their group's |proto| mutated directly. // Singletons can have their group's |proto| mutated directly.
masm.loadPtr(groupAddr, scratchReg); masm.loadPtr(groupAddr, scratchReg);
Address protoAddr(scratchReg, ObjectGroup::offsetOfProto()); Address protoAddr(scratchReg, ObjectGroup::offsetOfProto());
masm.branchPtr(Assembler::NotEqual, protoAddr, ImmGCPtr(pobj->staticPrototype()), masm.branchPtr(Assembler::NotEqual, protoAddr, ImmGCPtr(pobj->getProto()), failures);
failures);
} else { } else {
masm.branchPtr(Assembler::NotEqual, groupAddr, ImmGCPtr(pobj->group()), failures); masm.branchPtr(Assembler::NotEqual, groupAddr, ImmGCPtr(pobj->group()), failures);
} }
} }
pobj = pobj->getProto();
pobj = pobj->staticPrototype();
} }
} }
@ -463,7 +459,7 @@ jit::IsCacheableProtoChainForIonOrCacheIR(JSObject* obj, JSObject* holder)
* chain and must check for null proto. The prototype chain can be * chain and must check for null proto. The prototype chain can be
* altered during the lookupProperty call. * altered during the lookupProperty call.
*/ */
JSObject* proto = obj->staticPrototype(); JSObject* proto = obj->getProto();
if (!proto || !proto->isNative()) if (!proto || !proto->isNative())
return false; return false;
obj = proto; obj = proto;
@ -504,7 +500,7 @@ IsCacheableNoProperty(JSObject* obj, JSObject* holder, Shape* shape, jsbytecode*
while (obj2) { while (obj2) {
if (!obj2->isNative()) if (!obj2->isNative())
return false; return false;
obj2 = obj2->staticPrototype(); obj2 = obj2->getProto();
} }
// The pc is nullptr if the cache is idempotent. We cannot share missing // The pc is nullptr if the cache is idempotent. We cannot share missing
@ -823,20 +819,19 @@ GenerateReadSlot(JSContext* cx, IonScript* ion, MacroAssembler& masm,
} else { } else {
// The property does not exist. Guard on everything in the // The property does not exist. Guard on everything in the
// prototype chain. // prototype chain.
JSObject* proto = obj->staticPrototype(); JSObject* proto = obj->getTaggedProto().toObjectOrNull();
Register lastReg = object; Register lastReg = object;
MOZ_ASSERT(scratchReg != object); MOZ_ASSERT(scratchReg != object);
while (proto) { while (proto) {
masm.loadObjProto(lastReg, scratchReg); masm.loadObjProto(lastReg, scratchReg);
// Guard the shape of the current prototype. // Guard the shape of the current prototype.
MOZ_ASSERT(proto->hasStaticPrototype());
masm.branchPtr(Assembler::NotEqual, masm.branchPtr(Assembler::NotEqual,
Address(scratchReg, JSObject::offsetOfShape()), Address(scratchReg, JSObject::offsetOfShape()),
ImmGCPtr(proto->as<NativeObject>().lastProperty()), ImmGCPtr(proto->as<NativeObject>().lastProperty()),
&prototypeFailures); &prototypeFailures);
proto = proto->staticPrototype(); proto = proto->getProto();
lastReg = scratchReg; lastReg = scratchReg;
} }
@ -1808,7 +1803,7 @@ GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext* cx, HandleScript outerScri
MOZ_ASSERT(monitoredResult()); MOZ_ASSERT(monitoredResult());
MOZ_ASSERT(output().hasValue()); MOZ_ASSERT(output().hasValue());
RootedObject checkObj(cx, obj->staticPrototype()); RootedObject checkObj(cx, obj->getTaggedProto().toObjectOrNull());
RootedNativeObject holder(cx); RootedNativeObject holder(cx);
RootedShape shape(cx); RootedShape shape(cx);
@ -2911,7 +2906,7 @@ IsCacheableDOMProxyUnshadowedSetterCall(JSContext* cx, HandleObject obj, HandleI
{ {
MOZ_ASSERT(IsCacheableDOMProxy(obj)); MOZ_ASSERT(IsCacheableDOMProxy(obj));
RootedObject checkObj(cx, obj->staticPrototype()); RootedObject checkObj(cx, obj->getTaggedProto().toObjectOrNull());
if (!checkObj) if (!checkObj)
return false; return false;
@ -3034,7 +3029,7 @@ GenerateAddSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
CheckTypeSetForWrite(masm, obj, newShape->propid(), tempReg, value, failures); CheckTypeSetForWrite(masm, obj, newShape->propid(), tempReg, value, failures);
// Guard shapes along prototype chain. // Guard shapes along prototype chain.
JSObject* proto = obj->staticPrototype(); JSObject* proto = obj->getProto();
Register protoReg = tempReg; Register protoReg = tempReg;
bool first = true; bool first = true;
while (proto) { while (proto) {
@ -3047,7 +3042,7 @@ GenerateAddSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
// Ensure that its shape matches. // Ensure that its shape matches.
masm.branchTestObjShape(Assembler::NotEqual, protoReg, protoShape, failures); masm.branchTestObjShape(Assembler::NotEqual, protoReg, protoShape, failures);
proto = proto->staticPrototype(); proto = proto->getProto();
} }
// Call a stub to (re)allocate dynamic slots, if necessary. // Call a stub to (re)allocate dynamic slots, if necessary.
@ -3253,7 +3248,7 @@ PrototypeChainShadowsPropertyAdd(JSContext* cx, JSObject* obj, jsid id)
// Walk up the object prototype chain and ensure that all prototypes // Walk up the object prototype chain and ensure that all prototypes
// are native, and that all prototypes have no getter or setter // are native, and that all prototypes have no getter or setter
// defined on the property // defined on the property
for (JSObject* proto = obj->staticPrototype(); proto; proto = proto->staticPrototype()) { for (JSObject* proto = obj->getProto(); proto; proto = proto->getProto()) {
// If prototype is non-native, don't optimize // If prototype is non-native, don't optimize
if (!proto->isNative()) if (!proto->isNative())
return true; return true;
@ -3854,7 +3849,7 @@ GetPropertyIC::canAttachDenseElementHole(JSObject* obj, HandleValue idval, Typed
if (ClassCanHaveExtraProperties(obj->getClass())) if (ClassCanHaveExtraProperties(obj->getClass()))
return false; return false;
JSObject* proto = obj->staticPrototype(); JSObject* proto = obj->getProto();
if (!proto) if (!proto)
break; break;
@ -3890,10 +3885,10 @@ GenerateDenseElementHole(JSContext* cx, MacroAssembler& masm, IonCache::StubAtta
if (obj->hasUncacheableProto()) { if (obj->hasUncacheableProto()) {
masm.loadPtr(Address(object, JSObject::offsetOfGroup()), scratchReg); masm.loadPtr(Address(object, JSObject::offsetOfGroup()), scratchReg);
Address proto(scratchReg, ObjectGroup::offsetOfProto()); Address proto(scratchReg, ObjectGroup::offsetOfProto());
masm.branchPtr(Assembler::NotEqual, proto, ImmGCPtr(obj->staticPrototype()), &failures); masm.branchPtr(Assembler::NotEqual, proto, ImmGCPtr(obj->getProto()), &failures);
} }
JSObject* pobj = obj->staticPrototype(); JSObject* pobj = obj->getProto();
while (pobj) { while (pobj) {
MOZ_ASSERT(pobj->as<NativeObject>().lastProperty()); MOZ_ASSERT(pobj->as<NativeObject>().lastProperty());
@ -3919,7 +3914,7 @@ GenerateDenseElementHole(JSContext* cx, MacroAssembler& masm, IonCache::StubAtta
Address initLength(scratchReg, ObjectElements::offsetOfInitializedLength()); Address initLength(scratchReg, ObjectElements::offsetOfInitializedLength());
masm.branch32(Assembler::NotEqual, initLength, Imm32(0), &failures); masm.branch32(Assembler::NotEqual, initLength, Imm32(0), &failures);
pobj = pobj->staticPrototype(); pobj = pobj->getProto();
} }
// Ensure the index is an int32 value. // Ensure the index is an int32 value.
@ -4323,7 +4318,7 @@ IsDenseElementSetInlineable(JSObject* obj, const Value& idval, ConstantOrRegiste
// Scan the prototype and shape chain to make sure that this is not the case. // Scan the prototype and shape chain to make sure that this is not the case.
JSObject* curObj = obj; JSObject* curObj = obj;
while (curObj) { while (curObj) {
// Ensure object is native. (This guarantees static prototype below.) // Ensure object is native.
if (!curObj->isNative()) if (!curObj->isNative())
return false; return false;
@ -4331,7 +4326,7 @@ IsDenseElementSetInlineable(JSObject* obj, const Value& idval, ConstantOrRegiste
if (curObj->isIndexed()) if (curObj->isIndexed())
return false; return false;
curObj = curObj->staticPrototype(); curObj = curObj->getProto();
} }
*checkTypeset = false; *checkTypeset = false;

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

@ -2064,7 +2064,7 @@ IonBuilder::inlineObjectCreate(CallInfo& callInfo)
// Ensure the argument matches the template object's prototype. // Ensure the argument matches the template object's prototype.
MDefinition* arg = callInfo.getArg(0); MDefinition* arg = callInfo.getArg(0);
if (JSObject* proto = templateObject->staticPrototype()) { if (JSObject* proto = templateObject->getProto()) {
if (IsInsideNursery(proto)) if (IsInsideNursery(proto))
return InliningStatus_NotInlined; return InliningStatus_NotInlined;

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

@ -5564,7 +5564,7 @@ jit::PropertyReadNeedsTypeBarrier(JSContext* propertycx,
if (key->isSingleton()) if (key->isSingleton())
obj = key->singleton(); obj = key->singleton();
else else
obj = key->proto().isDynamic() ? nullptr : key->proto().toObjectOrNull(); obj = key->proto().isLazy() ? nullptr : key->proto().toObjectOrNull();
while (obj) { while (obj) {
if (!obj->getClass()->isNative()) if (!obj->getClass()->isNative())
@ -5588,7 +5588,7 @@ jit::PropertyReadNeedsTypeBarrier(JSContext* propertycx,
} }
} }
obj = obj->staticPrototype(); obj = obj->getProto();
} }
} }
@ -5776,7 +5776,7 @@ PrototypeHasIndexedProperty(IonBuilder* builder, JSObject* obj)
HeapTypeSetKey index = key->property(JSID_VOID); HeapTypeSetKey index = key->property(JSID_VOID);
if (index.nonData(builder->constraints()) || index.isOwnProperty(builder->constraints())) if (index.nonData(builder->constraints()) || index.isOwnProperty(builder->constraints()))
return true; return true;
obj = obj->staticPrototype(); obj = obj->getProto();
} while (obj); } while (obj);
return false; return false;

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

@ -2182,7 +2182,7 @@ JSObject*
GetDOMProxyProto(JSObject* obj) GetDOMProxyProto(JSObject* obj)
{ {
MOZ_ASSERT(IsCacheableDOMProxy(obj)); MOZ_ASSERT(IsCacheableDOMProxy(obj));
return obj->staticPrototype(); return obj->getTaggedProto().toObjectOrNull();
} }
// Look up a property's shape on an object, being careful never to do any effectful // Look up a property's shape on an object, being careful never to do any effectful
@ -2253,25 +2253,30 @@ IsCacheableProtoChain(JSObject* obj, JSObject* holder, bool isDOMProxy)
} }
} }
// Don't handle objects which require a prototype guard. This should
// be uncommon so handling it is likely not worth the complexity.
if (obj->hasUncacheableProto())
return false;
JSObject* cur = obj; JSObject* cur = obj;
while (cur != holder) { while (cur != holder) {
// We cannot assume that we find the holder object on the prototype // We cannot assume that we find the holder object on the prototype
// chain and must check for null proto. The prototype chain can be // chain and must check for null proto. The prototype chain can be
// altered during the lookupProperty call. // altered during the lookupProperty call.
MOZ_ASSERT(!cur->hasDynamicPrototype()); JSObject* proto;
if (isDOMProxy && cur == obj)
proto = cur->getTaggedProto().toObjectOrNull();
else
proto = cur->getProto();
// Don't handle objects which require a prototype guard. This should if (!proto || !proto->isNative())
// be uncommon so handling it is likely not worth the complexity.
if (cur->hasUncacheableProto())
return false; return false;
JSObject* proto = cur->staticPrototype(); if (proto->hasUncacheableProto())
if (!proto || !proto->isNative())
return false; return false;
cur = proto; cur = proto;
} }
return true; return true;
} }
@ -2709,7 +2714,7 @@ CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, PropertyName* name,
return false; return false;
} }
JSObject* proto = curObj->staticPrototype(); JSObject* proto = curObj->getTaggedProto().toObjectOrNull();
if (!proto) if (!proto)
break; break;
@ -3138,15 +3143,13 @@ ICGetPropNativeCompiler::generateStubCode(MacroAssembler& masm)
bool bool
GetProtoShapes(JSObject* obj, size_t protoChainDepth, MutableHandle<ShapeVector> shapes) GetProtoShapes(JSObject* obj, size_t protoChainDepth, MutableHandle<ShapeVector> shapes)
{ {
JSObject* curProto = obj->staticPrototype(); JSObject* curProto = obj->getProto();
for (size_t i = 0; i < protoChainDepth; i++) { for (size_t i = 0; i < protoChainDepth; i++) {
if (!shapes.append(curProto->as<NativeObject>().lastProperty())) if (!shapes.append(curProto->as<NativeObject>().lastProperty()))
return false; return false;
curProto = curProto->staticPrototype(); curProto = curProto->getProto();
} }
MOZ_ASSERT(!curProto);
MOZ_ASSERT(!curProto,
"longer prototype chain encountered than this stub permits!");
return true; return true;
} }

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

@ -1133,7 +1133,7 @@ JS_MayResolveStandardClass(const JSAtomState& names, jsid id, JSObject* maybeObj
// The global object's resolve hook is special: JS_ResolveStandardClass // The global object's resolve hook is special: JS_ResolveStandardClass
// initializes the prototype chain lazily. Only attempt to optimize here // initializes the prototype chain lazily. Only attempt to optimize here
// if we know the prototype chain has been initialized. // if we know the prototype chain has been initialized.
if (!maybeObj || !maybeObj->staticPrototype()) if (!maybeObj || !maybeObj->getProto())
return true; return true;
if (!JSID_IS_ATOM(id)) if (!JSID_IS_ATOM(id))

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

@ -828,33 +828,26 @@ ObjectMayHaveExtraIndexedOwnProperties(JSObject* obj)
obj->getClass(), INT_TO_JSID(0), obj); obj->getClass(), INT_TO_JSID(0), obj);
} }
/*
* Whether obj may have indexed properties anywhere besides its dense
* elements. This includes other indexed properties in its shape hierarchy, and
* indexed properties or elements along its prototype chain.
*/
bool bool
js::ObjectMayHaveExtraIndexedProperties(JSObject* obj) js::ObjectMayHaveExtraIndexedProperties(JSObject* obj)
{ {
MOZ_ASSERT_IF(obj->hasDynamicPrototype(), !obj->isNative()); /*
* Whether obj may have indexed properties anywhere besides its dense
* elements. This includes other indexed properties in its shape hierarchy,
* and indexed properties or elements along its prototype chain.
*/
if (ObjectMayHaveExtraIndexedOwnProperties(obj)) if (ObjectMayHaveExtraIndexedOwnProperties(obj))
return true; return true;
do { while ((obj = obj->getProto()) != nullptr) {
MOZ_ASSERT(obj->hasStaticPrototype(),
"dynamic-prototype objects must be non-native, ergo must "
"have failed ObjectMayHaveExtraIndexedOwnProperties");
obj = obj->staticPrototype();
if (!obj)
return false; // no extra indexed properties found
if (ObjectMayHaveExtraIndexedOwnProperties(obj)) if (ObjectMayHaveExtraIndexedOwnProperties(obj))
return true; return true;
if (GetAnyBoxedOrUnboxedInitializedLength(obj) != 0) if (GetAnyBoxedOrUnboxedInitializedLength(obj) != 0)
return true; return true;
} while (true); }
return false;
} }
static bool static bool
@ -2699,7 +2692,7 @@ GetIndexedPropertiesInRange(JSContext* cx, HandleObject obj, uint32_t begin, uin
do { do {
if (!pobj->isNative() || pobj->getClass()->getResolve() || pobj->getOpsLookupProperty()) if (!pobj->isNative() || pobj->getClass()->getResolve() || pobj->getOpsLookupProperty())
return true; return true;
} while ((pobj = pobj->staticPrototype())); } while ((pobj = pobj->getProto()));
// Collect indexed property names. // Collect indexed property names.
pobj = obj; pobj = obj;
@ -2744,7 +2737,7 @@ GetIndexedPropertiesInRange(JSContext* cx, HandleObject obj, uint32_t begin, uin
return false; return false;
} }
} }
} while ((pobj = pobj->staticPrototype())); } while ((pobj = pobj->getProto()));
// Sort the indexes. // Sort the indexes.
Vector<uint32_t> tmp(cx); Vector<uint32_t> tmp(cx);
@ -3608,7 +3601,7 @@ NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
if (!obj->is<ArrayObject>() && !obj->is<UnboxedArrayObject>()) if (!obj->is<ArrayObject>() && !obj->is<UnboxedArrayObject>())
return NewArray<maxLength>(cx, length, nullptr, newKind); return NewArray<maxLength>(cx, length, nullptr, newKind);
if (obj->staticPrototype() != cx->global()->maybeGetArrayPrototype()) if (obj->getProto() != cx->global()->maybeGetArrayPrototype())
return NewArray<maxLength>(cx, length, nullptr, newKind); return NewArray<maxLength>(cx, length, nullptr, newKind);
RootedObjectGroup group(cx, obj->getGroup(cx)); RootedObjectGroup group(cx, obj->getGroup(cx));

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

@ -456,7 +456,7 @@ JSCompartment::wrap(JSContext* cx, MutableHandleObject obj, HandleObject existin
RootedObject existing(cx, existingArg); RootedObject existing(cx, existingArg);
if (existing) { if (existing) {
// Is it possible to reuse |existing|? // Is it possible to reuse |existing|?
if (existing->hasStaticPrototype() || if (!existing->getTaggedProto().isLazy() ||
// Note: Class asserted above, so all that's left to check is callability // Note: Class asserted above, so all that's left to check is callability
existing->isCallable() || existing->isCallable() ||
obj->isCallable()) obj->isCallable())

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

@ -347,7 +347,8 @@ JS_FRIEND_API(JSObject*)
js::GetPrototypeNoProxy(JSObject* obj) js::GetPrototypeNoProxy(JSObject* obj)
{ {
MOZ_ASSERT(!obj->is<js::ProxyObject>()); MOZ_ASSERT(!obj->is<js::ProxyObject>());
return obj->staticPrototype(); MOZ_ASSERT(!obj->getTaggedProto().isLazy());
return obj->getTaggedProto().toObjectOrNull();
} }
JS_FRIEND_API(void) JS_FRIEND_API(void)

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

@ -2007,7 +2007,7 @@ js::CloneFunctionReuseScript(JSContext* cx, HandleFunction fun, HandleObject par
* Clone the function, reusing its script. We can use the same group as * Clone the function, reusing its script. We can use the same group as
* the original function provided that its prototype is correct. * the original function provided that its prototype is correct.
*/ */
if (fun->staticPrototype() == clone->staticPrototype()) if (fun->getProto() == clone->getProto())
clone->setGroup(fun->group()); clone->setGroup(fun->group());
return clone; return clone;
} }
@ -2160,8 +2160,8 @@ js::ReportIncompatibleMethod(JSContext* cx, CallReceiver call, const Class* clas
if (thisv.isObject()) { if (thisv.isObject()) {
MOZ_ASSERT(thisv.toObject().getClass() != clasp || MOZ_ASSERT(thisv.toObject().getClass() != clasp ||
!thisv.toObject().isNative() || !thisv.toObject().isNative() ||
!thisv.toObject().staticPrototype() || !thisv.toObject().getProto() ||
thisv.toObject().staticPrototype()->getClass() != clasp); thisv.toObject().getProto()->getClass() != clasp);
} else if (thisv.isString()) { } else if (thisv.isString()) {
MOZ_ASSERT(clasp != &StringObject::class_); MOZ_ASSERT(clasp != &StringObject::class_);
} else if (thisv.isNumber()) { } else if (thisv.isNumber()) {

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

@ -111,10 +111,8 @@ Enumerate(JSContext* cx, HandleObject pobj, jsid id,
// It's not necessary to add properties to the hash table at the end of // It's not necessary to add properties to the hash table at the end of
// the prototype chain, but custom enumeration behaviors might return // the prototype chain, but custom enumeration behaviors might return
// duplicated properties, so always add in such cases. // duplicated properties, so always add in such cases.
if (pobj->is<ProxyObject>() || pobj->staticPrototype() || pobj->getOpsEnumerate()) { if ((pobj->is<ProxyObject>() || pobj->getProto() || pobj->getOpsEnumerate()) && !ht->add(p, id))
if (!ht->add(p, id)) return false;
return false;
}
} }
// Symbol-keyed properties and nonenumerable properties are skipped unless // Symbol-keyed properties and nonenumerable properties are skipped unless
@ -703,11 +701,7 @@ VectorToKeyIterator(JSContext* cx, HandleObject obj, unsigned flags, AutoIdVecto
size_t ind = 0; size_t ind = 0;
do { do {
ni->guard_array[ind++].init(ReceiverGuard(pobj)); ni->guard_array[ind++].init(ReceiverGuard(pobj));
pobj = pobj->getProto();
// The one caller of this method that passes |numGuards > 0|, does
// so only if the entire chain consists of cacheable objects (that
// necessarily have static prototypes).
pobj = pobj->staticPrototype();
} while (pobj); } while (pobj);
MOZ_ASSERT(ind == numGuards); MOZ_ASSERT(ind == numGuards);
} }
@ -849,10 +843,10 @@ js::GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleOb
CanCompareIterableObjectToCache(obj) && CanCompareIterableObjectToCache(obj) &&
ReceiverGuard(obj) == lastni->guard_array[0]) ReceiverGuard(obj) == lastni->guard_array[0])
{ {
JSObject* proto = obj->staticPrototype(); JSObject* proto = obj->getProto();
if (CanCompareIterableObjectToCache(proto) && if (CanCompareIterableObjectToCache(proto) &&
ReceiverGuard(proto) == lastni->guard_array[1] && ReceiverGuard(proto) == lastni->guard_array[1] &&
!proto->staticPrototype()) !proto->getProto())
{ {
objp.set(last); objp.set(last);
UpdateNativeIterator(lastni, obj); UpdateNativeIterator(lastni, obj);
@ -862,9 +856,12 @@ js::GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleOb
} }
} }
// The iterator object for JSITER_ENUMERATE never escapes, so we don't /*
// care that the "proper" prototype is set. This also lets us reuse an * The iterator object for JSITER_ENUMERATE never escapes, so we
// old, inactive iterator object. * don't care for the proper parent/proto to be set. This also
* allows us to re-use a previous iterator object that is not
* currently active.
*/
{ {
JSObject* pobj = obj; JSObject* pobj = obj;
do { do {
@ -872,13 +869,11 @@ js::GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleOb
guards.clear(); guards.clear();
goto miss; goto miss;
} }
ReceiverGuard guard(pobj); ReceiverGuard guard(pobj);
key = (key + (key << 16)) ^ guard.hash(); key = (key + (key << 16)) ^ guard.hash();
if (!guards.append(guard)) if (!guards.append(guard))
return false; return false;
pobj = pobj->getProto();
pobj = pobj->staticPrototype();
} while (pobj); } while (pobj);
} }

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

@ -501,7 +501,7 @@ js::SetIntegrityLevel(JSContext* cx, HandleObject obj, IntegrityLevel level)
// generic path below then any non-empty object will be converted to // generic path below then any non-empty object will be converted to
// dictionary mode. // dictionary mode.
RootedShape last(cx, EmptyShape::getInitialShape(cx, nobj->getClass(), RootedShape last(cx, EmptyShape::getInitialShape(cx, nobj->getClass(),
nobj->taggedProto(), nobj->getTaggedProto(),
nobj->numFixedSlots(), nobj->numFixedSlots(),
nobj->lastProperty()->getObjectFlags())); nobj->lastProperty()->getObjectFlags()));
if (!last) if (!last)
@ -689,7 +689,7 @@ NewObjectCache::fillProto(EntryIndex entry, const Class* clasp, js::TaggedProto
gc::AllocKind kind, NativeObject* obj) gc::AllocKind kind, NativeObject* obj)
{ {
MOZ_ASSERT_IF(proto.isObject(), !proto.toObject()->is<GlobalObject>()); MOZ_ASSERT_IF(proto.isObject(), !proto.toObject()->is<GlobalObject>());
MOZ_ASSERT(obj->taggedProto() == proto); MOZ_ASSERT(obj->getTaggedProto() == proto);
return fill(entry, clasp, proto.raw(), kind, obj); return fill(entry, clasp, proto.raw(), kind, obj);
} }
@ -914,7 +914,7 @@ CreateThisForFunctionWithGroup(JSContext* cx, HandleObjectGroup group,
return nullptr; return nullptr;
if (newKind == SingletonObject) { if (newKind == SingletonObject) {
Rooted<TaggedProto> proto(cx, TaggedProto(templateObject->staticPrototype())); Rooted<TaggedProto> proto(cx, TaggedProto(templateObject->getProto()));
if (!res->splicePrototype(cx, &PlainObject::class_, proto)) if (!res->splicePrototype(cx, &PlainObject::class_, proto))
return nullptr; return nullptr;
} else { } else {
@ -1341,13 +1341,13 @@ InitializePropertiesFromCompatibleNativeObject(JSContext* cx,
MOZ_ASSERT(!src->hasPrivate()); MOZ_ASSERT(!src->hasPrivate());
RootedShape shape(cx); RootedShape shape(cx);
if (src->staticPrototype() == dst->staticPrototype()) { if (src->getProto() == dst->getProto()) {
shape = src->lastProperty(); shape = src->lastProperty();
} else { } else {
// We need to generate a new shape for dst that has dst's proto but all // We need to generate a new shape for dst that has dst's proto but all
// the property information from src. Note that we asserted above that // the property information from src. Note that we asserted above that
// dst's object flags are 0. // dst's object flags are 0.
shape = EmptyShape::getInitialShape(cx, dst->getClass(), dst->taggedProto(), shape = EmptyShape::getInitialShape(cx, dst->getClass(), dst->getTaggedProto(),
dst->numFixedSlots(), 0); dst->numFixedSlots(), 0);
if (!shape) if (!shape)
return false; return false;
@ -1943,7 +1943,7 @@ js::SetClassAndProto(JSContext* cx, HandleObject obj,
MOZ_ASSERT(obj == oldproto); MOZ_ASSERT(obj == oldproto);
break; break;
} }
oldproto = oldproto->staticPrototype(); oldproto = oldproto->getProto();
} }
if (proto.isObject() && !proto.toObject()->setDelegate(cx)) if (proto.isObject() && !proto.toObject()->setDelegate(cx))
@ -1993,7 +1993,7 @@ JSObject::changeToSingleton(JSContext* cx, HandleObject obj)
MarkObjectGroupUnknownProperties(cx, obj->group()); MarkObjectGroupUnknownProperties(cx, obj->group());
ObjectGroup* group = ObjectGroup::lazySingletonGroup(cx, obj->getClass(), ObjectGroup* group = ObjectGroup::lazySingletonGroup(cx, obj->getClass(),
obj->taggedProto()); obj->getTaggedProto());
if (!group) if (!group)
return false; return false;
@ -2295,7 +2295,7 @@ js::LookupPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSObject**
return true; return true;
} }
obj = obj->staticPrototype(); obj = obj->getProto();
} while (obj); } while (obj);
*objp = nullptr; *objp = nullptr;
@ -2498,13 +2498,13 @@ bool
js::GetPrototypeIfOrdinary(JSContext* cx, HandleObject obj, bool* isOrdinary, js::GetPrototypeIfOrdinary(JSContext* cx, HandleObject obj, bool* isOrdinary,
MutableHandleObject protop) MutableHandleObject protop)
{ {
if (obj->hasDynamicPrototype()) { if (obj->getTaggedProto().isLazy()) {
MOZ_ASSERT(obj->is<js::ProxyObject>()); MOZ_ASSERT(obj->is<js::ProxyObject>());
return js::Proxy::getPrototypeIfOrdinary(cx, obj, isOrdinary, protop); return js::Proxy::getPrototypeIfOrdinary(cx, obj, isOrdinary, protop);
} }
*isOrdinary = true; *isOrdinary = true;
protop.set(obj->staticPrototype()); protop.set(obj->getTaggedProto().toObjectOrNull());
return true; return true;
} }
@ -2527,15 +2527,19 @@ JS_ImmutablePrototypesEnabled()
bool bool
js::SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto, JS::ObjectOpResult& result) js::SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto, JS::ObjectOpResult& result)
{ {
// The proxy trap subsystem fully handles prototype-setting for proxies /*
// with dynamic [[Prototype]]s. * If |obj| has a "lazy" [[Prototype]], it is 1) a proxy 2) whose handler's
if (obj->hasDynamicPrototype()) { * {get,set}Prototype and setImmutablePrototype methods mediate access to
* |obj.[[Prototype]]|. The Proxy subsystem is responsible for responding
* to such attempts.
*/
if (obj->hasLazyPrototype()) {
MOZ_ASSERT(obj->is<ProxyObject>()); MOZ_ASSERT(obj->is<ProxyObject>());
return Proxy::setPrototype(cx, obj, proto, result); return Proxy::setPrototype(cx, obj, proto, result);
} }
/* Disallow mutation of immutable [[Prototype]]s. */ /* Disallow mutation of immutable [[Prototype]]s. */
if (obj->staticPrototypeIsImmutable() && ImmutablePrototypesEnabled) if (obj->nonLazyPrototypeIsImmutable() && ImmutablePrototypesEnabled)
return result.fail(JSMSG_CANT_SET_PROTO); return result.fail(JSMSG_CANT_SET_PROTO);
/* /*
@ -2572,7 +2576,7 @@ js::SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto, JS::Object
* ES6 9.1.2 step 3-4 if |obj.[[Prototype]]| has SameValue as |proto| return true. * ES6 9.1.2 step 3-4 if |obj.[[Prototype]]| has SameValue as |proto| return true.
* Since the values in question are objects, we can just compare pointers. * Since the values in question are objects, we can just compare pointers.
*/ */
if (proto == obj->staticPrototype()) if (proto == obj->getProto())
return result.succeed(); return result.succeed();
/* ES6 9.1.2 step 5 forbids changing [[Prototype]] if not [[Extensible]]. */ /* ES6 9.1.2 step 5 forbids changing [[Prototype]] if not [[Extensible]]. */
@ -2782,7 +2786,7 @@ js::DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, Handle
bool bool
js::SetImmutablePrototype(ExclusiveContext* cx, HandleObject obj, bool* succeeded) js::SetImmutablePrototype(ExclusiveContext* cx, HandleObject obj, bool* succeeded)
{ {
if (obj->hasDynamicPrototype()) { if (obj->hasLazyPrototype()) {
if (!cx->shouldBeJSContext()) if (!cx->shouldBeJSContext())
return false; return false;
return Proxy::setImmutablePrototype(cx->asJSContext(), obj, succeeded); return Proxy::setImmutablePrototype(cx->asJSContext(), obj, succeeded);
@ -3467,8 +3471,7 @@ JSObject::dump()
if (obj->hasUncacheableProto()) fprintf(stderr, " has_uncacheable_proto"); if (obj->hasUncacheableProto()) fprintf(stderr, " has_uncacheable_proto");
if (obj->hadElementsAccess()) fprintf(stderr, " had_elements_access"); if (obj->hadElementsAccess()) fprintf(stderr, " had_elements_access");
if (obj->wasNewScriptCleared()) fprintf(stderr, " new_script_cleared"); if (obj->wasNewScriptCleared()) fprintf(stderr, " new_script_cleared");
if (obj->hasStaticPrototype() && obj->staticPrototypeIsImmutable()) if (!obj->hasLazyPrototype() && obj->nonLazyPrototypeIsImmutable()) fprintf(stderr, " immutable_prototype");
fprintf(stderr, " immutable_prototype");
if (obj->isNative()) { if (obj->isNative()) {
NativeObject* nobj = &obj->as<NativeObject>(); NativeObject* nobj = &obj->as<NativeObject>();
@ -3494,9 +3497,9 @@ JSObject::dump()
} }
fprintf(stderr, "proto "); fprintf(stderr, "proto ");
TaggedProto proto = obj->taggedProto(); TaggedProto proto = obj->getTaggedProto();
if (proto.isDynamic()) if (proto.isLazy())
fprintf(stderr, "<dynamic>"); fprintf(stderr, "<lazy>");
else else
dumpValue(ObjectOrNullValue(proto.toObjectOrNull())); dumpValue(ObjectOrNullValue(proto.toObjectOrNull()));
fputc('\n', stderr); fputc('\n', stderr);

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

@ -265,9 +265,6 @@ class JSObject : public js::gc::Cell
// hasUncacheableProto flag. // hasUncacheableProto flag.
inline bool hasUncacheableProto() const; inline bool hasUncacheableProto() const;
bool setUncacheableProto(js::ExclusiveContext* cx) { bool setUncacheableProto(js::ExclusiveContext* cx) {
MOZ_ASSERT(hasStaticPrototype(),
"uncacheability as a concept is only applicable to static "
"(not dynamically-computed) prototypes");
return setFlags(cx, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE); return setFlags(cx, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE);
} }
@ -358,26 +355,20 @@ class JSObject : public js::gc::Cell
} }
/* /*
* We permit proxies to dynamically compute their prototype if desired. * We allow the prototype of an object to be lazily computed if the object
* (Not all proxies will so desire: in particular, most DOM proxies can * is a proxy. In the lazy case, we store (JSObject*)0x1 in the proto field
* track their prototype with a single, nullable JSObject*.) If a proxy * of the object's group. We offer three ways of getting the prototype:
* so desires, we store (JSObject*)0x1 in the proto field of the object's
* group.
* *
* We offer three ways to get an object's prototype: * 1. obj->getProto() returns the prototype, but asserts if obj is a proxy
* * with a relevant getPrototype() handler.
* 1. obj->staticPrototype() returns the prototype, but it asserts if obj * 2. obj->getTaggedProto() returns a TaggedProto, which can be tested to
* is a proxy, and the proxy has opted to dynamically compute its
* prototype using a getPrototype() handler.
* 2. obj->taggedProto() returns a TaggedProto, which can be tested to
* check if the proto is an object, nullptr, or lazily computed. * check if the proto is an object, nullptr, or lazily computed.
* 3. js::GetPrototype(cx, obj, &proto) computes the proto of an object. * 3. js::GetPrototype(cx, obj, &proto) computes the proto of an object.
* If obj is a proxy with dynamically-computed prototype, this code may * If obj is a proxy and the proto is lazy, this code may allocate or
* perform arbitrary behavior (allocation, GC, run JS) while computing * GC in order to compute the proto. Currently, it will not run JS code.
* the proto.
*/ */
js::TaggedProto taggedProto() const { js::TaggedProto getTaggedProto() const {
return group_->proto(); return group_->proto();
} }
@ -385,34 +376,37 @@ class JSObject : public js::gc::Cell
bool uninlinedIsProxy() const; bool uninlinedIsProxy() const;
JSObject* staticPrototype() const { JSObject* getProto() const {
MOZ_ASSERT(hasStaticPrototype()); MOZ_ASSERT(!hasLazyPrototype());
return taggedProto().toObjectOrNull(); return getTaggedProto().toObjectOrNull();
} }
// Normal objects and a subset of proxies have an uninteresting, static // Normal objects and a subset of proxies have uninteresting [[Prototype]].
// (albeit perhaps mutable) [[Prototype]]. For such objects the // For such objects the [[Prototype]] is just a value returned when needed
// [[Prototype]] is just a value returned when needed for accesses, or // for accesses, or modified in response to requests. These objects store
// modified in response to requests. These objects store the // the [[Prototype]] directly within |obj->type_|.
// [[Prototype]] directly within |obj->group_|. //
bool hasStaticPrototype() const { // Proxies that don't have such a simple [[Prototype]] instead have a
return !hasDynamicPrototype(); // "lazy" [[Prototype]]. Accessing the [[Prototype]] of such an object
// requires going through the proxy handler {get,set}Prototype and
// setImmutablePrototype methods. This is most commonly useful for proxies
// that are wrappers around other objects. If the [[Prototype]] of the
// underlying object changes, the [[Prototype]] of the wrapper must also
// simultaneously change. We implement this by having the handler methods
// simply delegate to the wrapped object, forwarding its response to the
// caller.
//
// This method returns true if this object has a non-simple [[Prototype]]
// as described above, or false otherwise.
bool hasLazyPrototype() const {
bool lazy = getTaggedProto().isLazy();
MOZ_ASSERT_IF(lazy, uninlinedIsProxy());
return lazy;
} }
// The remaining proxies have a [[Prototype]] requiring dynamic computation // True iff this object's [[Prototype]] is immutable. Must not be called
// for every access, going through the proxy handler {get,set}Prototype and // on proxies with lazy [[Prototype]]!
// setImmutablePrototype methods. (Wrappers particularly use this to keep inline bool nonLazyPrototypeIsImmutable() const;
// the wrapper/wrappee [[Prototype]]s consistent.)
bool hasDynamicPrototype() const {
bool dynamic = taggedProto().isDynamic();
MOZ_ASSERT_IF(dynamic, uninlinedIsProxy());
MOZ_ASSERT_IF(dynamic, !isNative());
return dynamic;
}
// True iff this object's [[Prototype]] is immutable. Must be called only
// on objects with a static [[Prototype]]!
inline bool staticPrototypeIsImmutable() const;
inline void setGroup(js::ObjectGroup* group); inline void setGroup(js::ObjectGroup* group);

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

@ -117,7 +117,7 @@ JSObject::setSingleton(js::ExclusiveContext* cx, js::HandleObject obj)
MOZ_ASSERT_IF(cx->isJSContext(), !IsInsideNursery(obj)); MOZ_ASSERT_IF(cx->isJSContext(), !IsInsideNursery(obj));
js::ObjectGroup* group = js::ObjectGroup::lazySingletonGroup(cx, obj->getClass(), js::ObjectGroup* group = js::ObjectGroup::lazySingletonGroup(cx, obj->getClass(),
obj->taggedProto()); obj->getTaggedProto());
if (!group) if (!group)
return false; return false;
@ -152,13 +152,13 @@ JSObject::setGroup(js::ObjectGroup* group)
inline bool inline bool
js::GetPrototype(JSContext* cx, js::HandleObject obj, js::MutableHandleObject protop) js::GetPrototype(JSContext* cx, js::HandleObject obj, js::MutableHandleObject protop)
{ {
if (obj->hasDynamicPrototype()) { if (obj->getTaggedProto().isLazy()) {
MOZ_ASSERT(obj->is<js::ProxyObject>()); MOZ_ASSERT(obj->is<js::ProxyObject>());
return js::Proxy::getPrototype(cx, obj, protop); return js::Proxy::getPrototype(cx, obj, protop);
} else {
protop.set(obj->getTaggedProto().toObjectOrNull());
return true;
} }
protop.set(obj->taggedProto().toObjectOrNull());
return true;
} }
inline bool inline bool
@ -487,9 +487,9 @@ JSObject::isIndexed() const
} }
inline bool inline bool
JSObject::staticPrototypeIsImmutable() const JSObject::nonLazyPrototypeIsImmutable() const
{ {
MOZ_ASSERT(hasStaticPrototype()); MOZ_ASSERT(!hasLazyPrototype());
return hasAllFlags(js::BaseShape::IMMUTABLE_PROTOTYPE); return hasAllFlags(js::BaseShape::IMMUTABLE_PROTOTYPE);
} }
@ -564,7 +564,7 @@ ClassMethodIsNative(JSContext* cx, NativeObject* obj, const Class* clasp, jsid m
Value v; Value v;
if (!HasDataProperty(cx, obj, methodid, &v)) { if (!HasDataProperty(cx, obj, methodid, &v)) {
JSObject* proto = obj->staticPrototype(); JSObject* proto = obj->getProto();
if (!proto || proto->getClass() != clasp || !HasDataProperty(cx, &proto->as<NativeObject>(), methodid, &v)) if (!proto || proto->getClass() != clasp || !HasDataProperty(cx, &proto->as<NativeObject>(), methodid, &v))
return false; return false;
} }
@ -585,7 +585,7 @@ HasObjectValueOf(JSObject* obj, JSContext* cx)
Value v; Value v;
while (!HasDataProperty(cx, &obj->as<NativeObject>(), valueOf, &v)) { while (!HasDataProperty(cx, &obj->as<NativeObject>(), valueOf, &v)) {
obj = obj->staticPrototype(); obj = obj->getProto();
if (!obj || obj->is<ProxyObject>() || !obj->isNative()) if (!obj || obj->is<ProxyObject>() || !obj->isNative())
return false; return false;
} }

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

@ -396,14 +396,14 @@ BaseProxyHandler::weakmapKeyDelegate(JSObject* proxy) const
bool bool
BaseProxyHandler::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject protop) const BaseProxyHandler::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject protop) const
{ {
MOZ_CRASH("must override getPrototype with dynamic prototype"); MOZ_CRASH("must override getPrototype with lazy prototype");
} }
bool bool
BaseProxyHandler::setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto, BaseProxyHandler::setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
ObjectOpResult& result) const ObjectOpResult& result) const
{ {
// Disallow sets of protos on proxies with dynamic prototypes but no hook. // Disallow sets of protos on proxies with lazy protos, but no hook.
// This keeps us away from the footgun of having the first proto set opt // This keeps us away from the footgun of having the first proto set opt
// you out of having dynamic protos altogether. // you out of having dynamic protos altogether.
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF, JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
@ -415,7 +415,7 @@ bool
BaseProxyHandler::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary, BaseProxyHandler::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
MutableHandleObject protop) const MutableHandleObject protop) const
{ {
MOZ_CRASH("must override getPrototypeIfOrdinary with dynamic prototype"); MOZ_CRASH("must override getPrototypeIfOrdinary with lazy prototype");
} }
bool bool

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

@ -183,7 +183,7 @@ js::AppendUnique(JSContext* cx, AutoIdVector& base, AutoIdVector& others)
/* static */ bool /* static */ bool
Proxy::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject proto) Proxy::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject proto)
{ {
MOZ_ASSERT(proxy->hasDynamicPrototype()); MOZ_ASSERT(proxy->hasLazyPrototype());
JS_CHECK_RECURSION(cx, return false); JS_CHECK_RECURSION(cx, return false);
return proxy->as<ProxyObject>().handler()->getPrototype(cx, proxy, proto); return proxy->as<ProxyObject>().handler()->getPrototype(cx, proxy, proto);
} }
@ -191,7 +191,7 @@ Proxy::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject proto
/* static */ bool /* static */ bool
Proxy::setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto, ObjectOpResult& result) Proxy::setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto, ObjectOpResult& result)
{ {
MOZ_ASSERT(proxy->hasDynamicPrototype()); MOZ_ASSERT(proxy->hasLazyPrototype());
JS_CHECK_RECURSION(cx, return false); JS_CHECK_RECURSION(cx, return false);
return proxy->as<ProxyObject>().handler()->setPrototype(cx, proxy, proto, result); return proxy->as<ProxyObject>().handler()->setPrototype(cx, proxy, proto, result);
} }
@ -200,7 +200,7 @@ Proxy::setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto, Objec
Proxy::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary, Proxy::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
MutableHandleObject proto) MutableHandleObject proto)
{ {
MOZ_ASSERT(proxy->hasDynamicPrototype()); MOZ_ASSERT(proxy->hasLazyPrototype());
JS_CHECK_RECURSION(cx, return false); JS_CHECK_RECURSION(cx, return false);
return proxy->as<ProxyObject>().handler()->getPrototypeIfOrdinary(cx, proxy, isOrdinary, return proxy->as<ProxyObject>().handler()->getPrototypeIfOrdinary(cx, proxy, isOrdinary,
proto); proto);
@ -782,7 +782,7 @@ ProxyObject::renew(JSContext* cx, const BaseProxyHandler* handler, Value priv)
MOZ_ASSERT_IF(IsCrossCompartmentWrapper(this), IsDeadProxyObject(this)); MOZ_ASSERT_IF(IsCrossCompartmentWrapper(this), IsDeadProxyObject(this));
MOZ_ASSERT(getClass() == &ProxyObject::proxyClass); MOZ_ASSERT(getClass() == &ProxyObject::proxyClass);
MOZ_ASSERT(!IsWindowProxy(this)); MOZ_ASSERT(!IsWindowProxy(this));
MOZ_ASSERT(hasDynamicPrototype()); MOZ_ASSERT(hasLazyPrototype());
setHandler(handler); setHandler(handler);
setCrossCompartmentPrivate(priv); setCrossCompartmentPrivate(priv);

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

@ -3363,8 +3363,7 @@ CASE(JSOP_LAMBDA)
JSObject* obj = Lambda(cx, fun, REGS.fp()->scopeChain()); JSObject* obj = Lambda(cx, fun, REGS.fp()->scopeChain());
if (!obj) if (!obj)
goto error; goto error;
MOZ_ASSERT(obj->getProto());
MOZ_ASSERT(obj->staticPrototype());
PUSH_OBJECT(*obj); PUSH_OBJECT(*obj);
} }
END_CASE(JSOP_LAMBDA) END_CASE(JSOP_LAMBDA)
@ -3377,8 +3376,7 @@ CASE(JSOP_LAMBDA_ARROW)
JSObject* obj = LambdaArrow(cx, fun, REGS.fp()->scopeChain(), newTarget); JSObject* obj = LambdaArrow(cx, fun, REGS.fp()->scopeChain(), newTarget);
if (!obj) if (!obj)
goto error; goto error;
MOZ_ASSERT(obj->getProto());
MOZ_ASSERT(obj->staticPrototype());
REGS.sp[-1].setObject(*obj); REGS.sp[-1].setObject(*obj);
} }
END_CASE(JSOP_LAMBDA_ARROW) END_CASE(JSOP_LAMBDA_ARROW)

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

@ -566,7 +566,7 @@ LookupPropertyInline(ExclusiveContext* cx,
return true; return true;
} }
typename MaybeRooted<JSObject*, allowGC>::RootType proto(cx, current->staticPrototype()); typename MaybeRooted<JSObject*, allowGC>::RootType proto(cx, current->getProto());
if (!proto) if (!proto)
break; break;

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

@ -1080,7 +1080,7 @@ PurgeProtoChain(ExclusiveContext* cx, JSObject* objArg, HandleId id)
if (shape) if (shape)
return obj->as<NativeObject>().shadowingShapeChange(cx, *shape); return obj->as<NativeObject>().shadowingShapeChange(cx, *shape);
obj = obj->staticPrototype(); obj = obj->getProto();
} }
return true; return true;
@ -1099,7 +1099,7 @@ PurgeScopeChainHelper(ExclusiveContext* cx, HandleObject objArg, HandleId id)
if (JSID_IS_INT(id)) if (JSID_IS_INT(id))
return true; return true;
if (!PurgeProtoChain(cx, obj->staticPrototype(), id)) if (!PurgeProtoChain(cx, obj->getProto(), id))
return false; return false;
/* /*
@ -1640,7 +1640,7 @@ js::NativeHasProperty(JSContext* cx, HandleNativeObject obj, HandleId id, bool*
// What they all have in common is we do not want to keep walking // What they all have in common is we do not want to keep walking
// the prototype chain, and always claim that the property // the prototype chain, and always claim that the property
// doesn't exist. // doesn't exist.
RootedObject proto(cx, done ? nullptr : pobj->staticPrototype()); RootedObject proto(cx, done ? nullptr : pobj->getProto());
// Step 8. // Step 8.
if (!proto) { if (!proto) {
@ -2012,7 +2012,7 @@ NativeGetPropertyInline(JSContext* cx,
// being resolved. // being resolved.
// What they all have in common is we do not want to keep walking // What they all have in common is we do not want to keep walking
// the prototype chain. // the prototype chain.
RootedObject proto(cx, done ? nullptr : pobj->staticPrototype()); RootedObject proto(cx, done ? nullptr : pobj->getProto());
// Step 4.c. The spec algorithm simply returns undefined if proto is // Step 4.c. The spec algorithm simply returns undefined if proto is
// null, but see the comment on GetNonexistentProperty. // null, but see the comment on GetNonexistentProperty.
@ -2222,10 +2222,9 @@ js::SetPropertyOnProto(JSContext* cx, HandleObject obj, HandleId id, HandleValue
{ {
MOZ_ASSERT(!obj->is<ProxyObject>()); MOZ_ASSERT(!obj->is<ProxyObject>());
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (proto) if (proto)
return SetProperty(cx, proto, id, v, receiver, result); return SetProperty(cx, proto, id, v, receiver, result);
return SetPropertyByDefining(cx, id, v, receiver, result); return SetPropertyByDefining(cx, id, v, receiver, result);
} }
@ -2399,7 +2398,7 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Handle
// being resolved. // being resolved.
// What they all have in common is we do not want to keep walking // What they all have in common is we do not want to keep walking
// the prototype chain. // the prototype chain.
RootedObject proto(cx, done ? nullptr : pobj->staticPrototype()); RootedObject proto(cx, done ? nullptr : pobj->getProto());
if (!proto) { if (!proto) {
// Step 4.d.i (and step 5). // Step 4.d.i (and step 5).
return SetNonexistentProperty(cx, id, v, receiver, qualified, result); return SetNonexistentProperty(cx, id, v, receiver, qualified, result);

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

@ -260,7 +260,7 @@ JSObject::shouldSplicePrototype(JSContext* cx)
* object if their __proto__ had previously been set to null, as this * object if their __proto__ had previously been set to null, as this
* will change the prototype for all other objects with the same type. * will change the prototype for all other objects with the same type.
*/ */
if (staticPrototype() != nullptr) if (getProto() != nullptr)
return false; return false;
return isSingleton(); return isSingleton();
} }
@ -327,7 +327,7 @@ JSObject::makeLazyGroup(JSContext* cx, HandleObject obj)
if (obj->is<ArrayObject>() && obj->as<ArrayObject>().length() > INT32_MAX) if (obj->is<ArrayObject>() && obj->as<ArrayObject>().length() > INT32_MAX)
initialFlags |= OBJECT_FLAG_LENGTH_OVERFLOW; initialFlags |= OBJECT_FLAG_LENGTH_OVERFLOW;
Rooted<TaggedProto> proto(cx, obj->taggedProto()); Rooted<TaggedProto> proto(cx, obj->getTaggedProto());
ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, obj->getClass(), proto, ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, obj->getClass(), proto,
initialFlags); initialFlags);
if (!group) if (!group)
@ -501,7 +501,7 @@ ObjectGroup::defaultNewGroup(ExclusiveContext* cx, const Class* clasp,
} }
ObjectGroupFlags initialFlags = 0; ObjectGroupFlags initialFlags = 0;
if (proto.isDynamic() || (proto.isObject() && proto.toObject()->isNewGroupUnknown())) if (proto.isLazy() || (proto.isObject() && proto.toObject()->isNewGroupUnknown()))
initialFlags = OBJECT_FLAG_DYNAMIC_MASK; initialFlags = OBJECT_FLAG_DYNAMIC_MASK;
Rooted<TaggedProto> protoRoot(cx, proto); Rooted<TaggedProto> protoRoot(cx, proto);
@ -1220,7 +1220,7 @@ ObjectGroup::newPlainObject(ExclusiveContext* cx, IdValuePair* properties, size_
// default (which will have unknown properties) so that the group we // default (which will have unknown properties) so that the group we
// just created will be collected by the GC. // just created will be collected by the GC.
if (obj->slotSpan() != nproperties) { if (obj->slotSpan() != nproperties) {
ObjectGroup* group = defaultNewGroup(cx, obj->getClass(), obj->taggedProto()); ObjectGroup* group = defaultNewGroup(cx, obj->getClass(), obj->getTaggedProto());
if (!group) if (!group)
return nullptr; return nullptr;
obj->setGroup(group); obj->setGroup(group);

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

@ -99,10 +99,6 @@ class ObjectGroup : public gc::TenuredCell
clasp_ = clasp; clasp_ = clasp;
} }
bool hasDynamicPrototype() const {
return proto_.isDynamic();
}
const HeapPtr<TaggedProto>& proto() const { const HeapPtr<TaggedProto>& proto() const {
return proto_; return proto_;
} }

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

@ -181,7 +181,14 @@ bool
js::ForOfPIC::Chain::isOptimizableArray(JSObject* obj) js::ForOfPIC::Chain::isOptimizableArray(JSObject* obj)
{ {
MOZ_ASSERT(obj->is<ArrayObject>()); MOZ_ASSERT(obj->is<ArrayObject>());
return obj->staticPrototype() == arrayProto_;
// Ensure object's prototype is the actual Array.prototype
if (!obj->getTaggedProto().isObject())
return false;
if (obj->getTaggedProto().toObject() != arrayProto_)
return false;
return true;
} }
bool bool

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

@ -849,7 +849,7 @@ RegExpCompartment::createMatchResultTemplateObject(JSContext* cx)
return matchResultTemplateObject_; // = nullptr return matchResultTemplateObject_; // = nullptr
// Create a new group for the template. // Create a new group for the template.
Rooted<TaggedProto> proto(cx, templateObject->taggedProto()); Rooted<TaggedProto> proto(cx, templateObject->getTaggedProto());
ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, templateObject->getClass(), proto); ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, templateObject->getClass(), proto);
if (!group) if (!group)
return matchResultTemplateObject_; // = nullptr return matchResultTemplateObject_; // = nullptr

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

@ -897,7 +897,7 @@ class NestedScopeObject : public ScopeObject
public: public:
// Return the static scope corresponding to this scope chain object. // Return the static scope corresponding to this scope chain object.
inline NestedStaticScope* staticScope() { inline NestedStaticScope* staticScope() {
return &staticPrototype()->as<NestedStaticScope>(); return &getProto()->as<NestedStaticScope>();
} }
void initEnclosingScope(JSObject* obj) { void initEnclosingScope(JSObject* obj) {
@ -927,7 +927,7 @@ class DynamicWithObject : public NestedScopeObject
WithKind kind = SyntacticWith); WithKind kind = SyntacticWith);
StaticWithScope& staticWith() const { StaticWithScope& staticWith() const {
return staticPrototype()->as<StaticWithScope>(); return getProto()->as<StaticWithScope>();
} }
/* Return the 'o' in 'with (o)'. */ /* Return the 'o' in 'with (o)'. */
@ -1007,7 +1007,7 @@ class ClonedBlockObject : public NestedScopeObject
public: public:
/* The static block from which this block was cloned. */ /* The static block from which this block was cloned. */
StaticBlockScope& staticBlock() const { StaticBlockScope& staticBlock() const {
return staticPrototype()->as<StaticBlockScope>(); return getProto()->as<StaticBlockScope>();
} }
/* Assuming 'put' has been called, return the value of the ith let var. */ /* Assuming 'put' has been called, return the value of the ith let var. */
@ -1387,7 +1387,7 @@ template<>
inline bool inline bool
JSObject::is<js::StaticBlockScope>() const JSObject::is<js::StaticBlockScope>() const
{ {
return hasClass(&js::ClonedBlockObject::class_) && !staticPrototype(); return hasClass(&js::ClonedBlockObject::class_) && !getProto();
} }
template<> template<>
@ -1411,7 +1411,7 @@ template<>
inline bool inline bool
JSObject::is<js::ClonedBlockObject>() const JSObject::is<js::ClonedBlockObject>() const
{ {
return hasClass(&js::ClonedBlockObject::class_) && staticPrototype(); return hasClass(&js::ClonedBlockObject::class_) && !!getProto();
} }
template<> template<>

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

@ -479,7 +479,7 @@ intrinsic_FinishBoundFunctionInit(JSContext* cx, unsigned argc, Value* vp)
if (!GetPrototype(cx, targetObj, &proto)) if (!GetPrototype(cx, targetObj, &proto))
return false; return false;
if (bound->staticPrototype() != proto) { if (bound->getProto() != proto) {
if (!SetPrototype(cx, bound, proto)) if (!SetPrototype(cx, bound, proto))
return false; return false;
} }

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

@ -126,7 +126,7 @@ EmptyShape::ensureInitialCustomShape(ExclusiveContext* cx, Handle<ObjectSubclass
// Cache the initial shape for non-prototype objects, however, so that // Cache the initial shape for non-prototype objects, however, so that
// future instances will begin life with that shape. // future instances will begin life with that shape.
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
EmptyShape::insertInitialShape(cx, shape, proto); EmptyShape::insertInitialShape(cx, shape, proto);
return true; return true;
} }

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

@ -1194,7 +1194,7 @@ JSObject::setFlags(ExclusiveContext* cx, BaseShape::Flag flags, GenerateShape ge
if (!existingShape) if (!existingShape)
return false; return false;
Shape* newShape = Shape::setObjectFlags(cx, flags, self->taggedProto(), existingShape); Shape* newShape = Shape::setObjectFlags(cx, flags, self->getTaggedProto(), existingShape);
if (!newShape) if (!newShape)
return false; return false;

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

@ -49,7 +49,7 @@ js::TaggedProto::hashCode() const
uint64_t uint64_t
js::TaggedProto::uniqueId() const js::TaggedProto::uniqueId() const
{ {
if (isDynamic()) if (isLazy())
return uint64_t(1); return uint64_t(1);
JSObject* obj = toObjectOrNull(); JSObject* obj = toObjectOrNull();
if (!obj) if (!obj)

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

@ -24,7 +24,7 @@ class TaggedProto
uintptr_t toWord() const { return uintptr_t(proto); } uintptr_t toWord() const { return uintptr_t(proto); }
bool isDynamic() const { bool isLazy() const {
return proto == LazyProto; return proto == LazyProto;
} }
bool isObject() const { bool isObject() const {
@ -83,7 +83,7 @@ class TaggedProtoOperations
public: public:
uintptr_t toWord() const { return value().toWord(); } uintptr_t toWord() const { return value().toWord(); }
inline bool isDynamic() const { return value().isDynamic(); } inline bool isLazy() const { return value().isLazy(); }
inline bool isObject() const { return value().isObject(); } inline bool isObject() const { return value().isObject(); }
inline JSObject* toObject() const { return value().toObject(); } inline JSObject* toObject() const { return value().toObject(); }
inline JSObject* toObjectOrNull() const { return value().toObjectOrNull(); } inline JSObject* toObjectOrNull() const { return value().toObjectOrNull(); }

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

@ -1215,7 +1215,7 @@ TypeSet::ObjectKey::clasp()
TaggedProto TaggedProto
TypeSet::ObjectKey::proto() TypeSet::ObjectKey::proto()
{ {
return isGroup() ? group()->proto() : singleton()->taggedProto(); return isGroup() ? group()->proto() : singleton()->getTaggedProto();
} }
TypeNewScript* TypeNewScript*
@ -2420,7 +2420,7 @@ TemporaryTypeSet::getCommonPrototype(CompilerConstraintList* constraints, JSObje
TaggedProto nproto = key->proto(); TaggedProto nproto = key->proto();
if (isFirst) { if (isFirst) {
if (nproto.isDynamic()) if (nproto.isLazy())
return false; return false;
*proto = nproto.toObjectOrNull(); *proto = nproto.toObjectOrNull();
isFirst = false; isFirst = false;
@ -3007,11 +3007,8 @@ ObjectGroup::print()
TaggedProto tagged(proto()); TaggedProto tagged(proto());
fprintf(stderr, "%s : %s", fprintf(stderr, "%s : %s",
TypeSet::ObjectGroupString(this), TypeSet::ObjectGroupString(this),
tagged.isObject() tagged.isObject() ? TypeSet::TypeString(TypeSet::ObjectType(tagged.toObject()))
? TypeSet::TypeString(TypeSet::ObjectType(tagged.toObject())) : (tagged.isLazy() ? "(lazy)" : "(null)"));
: tagged.isDynamic()
? "(dynamic)"
: "(null)");
if (unknownProperties()) { if (unknownProperties()) {
fprintf(stderr, " unknown"); fprintf(stderr, " unknown");
@ -3122,7 +3119,7 @@ js::AddClearDefiniteGetterSetterForPrototypeChain(JSContext* cx, ObjectGroup* gr
return false; return false;
if (!protoTypes->addConstraint(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteGetterSetter>(group))) if (!protoTypes->addConstraint(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteGetterSetter>(group)))
return false; return false;
proto = proto->staticPrototype(); proto = proto->getProto();
} }
return true; return true;
} }
@ -3322,7 +3319,7 @@ JSFunction::setTypeForScriptedFunction(ExclusiveContext* cx, HandleFunction fun,
if (!setSingleton(cx, fun)) if (!setSingleton(cx, fun))
return false; return false;
} else { } else {
RootedObject funProto(cx, fun->staticPrototype()); RootedObject funProto(cx, fun->getProto());
Rooted<TaggedProto> taggedProto(cx, TaggedProto(funProto)); Rooted<TaggedProto> taggedProto(cx, TaggedProto(funProto));
ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, &JSFunction::class_, ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, &JSFunction::class_,
taggedProto); taggedProto);
@ -3615,7 +3612,9 @@ ChangeObjectFixedSlotCount(JSContext* cx, PlainObject* obj, gc::AllocKind allocK
{ {
MOZ_ASSERT(OnlyHasDataProperties(obj->lastProperty())); MOZ_ASSERT(OnlyHasDataProperties(obj->lastProperty()));
Shape* newShape = ReshapeForAllocKind(cx, obj->lastProperty(), obj->taggedProto(), allocKind); Shape* newShape = ReshapeForAllocKind(cx, obj->lastProperty(),
obj->getTaggedProto(),
allocKind);
if (!newShape) if (!newShape)
return false; return false;

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

@ -721,7 +721,7 @@ UnboxedPlainObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
return true; return true;
} }
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) { if (!proto) {
objp.set(nullptr); objp.set(nullptr);
propp.set(nullptr); propp.set(nullptr);
@ -772,7 +772,7 @@ UnboxedPlainObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id
return true; return true;
} }
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) { if (!proto) {
*foundp = false; *foundp = false;
return true; return true;
@ -799,7 +799,7 @@ UnboxedPlainObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue
} }
} }
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) { if (!proto) {
vp.setUndefined(); vp.setUndefined();
return true; return true;
@ -1421,7 +1421,7 @@ UnboxedArrayObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
return true; return true;
} }
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) { if (!proto) {
objp.set(nullptr); objp.set(nullptr);
propp.set(nullptr); propp.set(nullptr);
@ -1472,7 +1472,7 @@ UnboxedArrayObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id
return true; return true;
} }
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) { if (!proto) {
*foundp = false; *foundp = false;
return true; return true;
@ -1493,7 +1493,7 @@ UnboxedArrayObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue
return true; return true;
} }
RootedObject proto(cx, obj->staticPrototype()); RootedObject proto(cx, obj->getProto());
if (!proto) { if (!proto) {
vp.setUndefined(); vp.setUndefined();
return true; return true;