зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1263778 - Rename a bunch of low-level [[Prototype]] access methods to make their interactions with statically-known and dynamically-computed [[Prototype]]s clearer. r=efaust
--HG-- extra : rebase_source : 8c1cf4b354f6e1170da08920df5517888936d28f
This commit is contained in:
Родитель
aa3a4bea25
Коммит
e69489250b
|
@ -37,9 +37,8 @@ public:
|
|||
delete_(JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
|
||||
JS::ObjectOpResult &aResult) const override;
|
||||
|
||||
// No need for getPrototypeIfOrdinary here: this object shouldn't have a
|
||||
// lazy prototype, so this trap would never be called (and the inherited
|
||||
// version, from BaseProxyHandler, just crashes).
|
||||
// No need for getPrototypeIfOrdinary here: window named-properties objects
|
||||
// have static prototypes, so this trap is never called.
|
||||
|
||||
virtual bool
|
||||
preventExtensions(JSContext* aCx, JS::Handle<JSObject*> aProxy,
|
||||
|
|
|
@ -925,13 +925,14 @@ nsOuterWindowProxy::getPrototypeIfOrdinary(JSContext* cx,
|
|||
//
|
||||
// https://html.spec.whatwg.org/multipage/browsers.html#windowproxy-getprototypeof
|
||||
//
|
||||
// We nonetheless can implement it here using a non-"lazy" [[Prototype]],
|
||||
// because wrapper-class handlers (particularly, XOW in FilteringWrapper.cpp)
|
||||
// supply all the non-ordinary behavior.
|
||||
// We nonetheless can implement it with a static [[Prototype]], because
|
||||
// wrapper-class handlers (particularly, XOW in FilteringWrapper.cpp) supply
|
||||
// all non-ordinary behavior.
|
||||
//
|
||||
// But from a spec point of view, it's the exact same object in both cases --
|
||||
// only the observer's changed. So both cases *must* report non-ordinary,
|
||||
// even if non-"lazy" [[Prototype]] usually means ordinary.
|
||||
// only the observer's changed. So this getPrototypeIfOrdinary trap on the
|
||||
// non-wrapper object *must* report non-ordinary, even if static [[Prototype]]
|
||||
// usually means ordinary.
|
||||
*isOrdinary = false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ MapIteratorObject::createResultPair(JSContext* cx)
|
|||
if (!resultPairObj)
|
||||
return nullptr;
|
||||
|
||||
Rooted<TaggedProto> proto(cx, resultPairObj->getTaggedProto());
|
||||
Rooted<TaggedProto> proto(cx, resultPairObj->taggedProto());
|
||||
ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, resultPairObj->getClass(), proto);
|
||||
if (!group)
|
||||
return nullptr;
|
||||
|
|
|
@ -611,7 +611,7 @@ js::ObjectCreateImpl(JSContext* cx, HandleObject proto, NewObjectKind newKind,
|
|||
PlainObject*
|
||||
js::ObjectCreateWithTemplate(JSContext* cx, HandlePlainObject templateObj)
|
||||
{
|
||||
RootedObject proto(cx, templateObj->getProto());
|
||||
RootedObject proto(cx, templateObj->staticPrototype());
|
||||
RootedObjectGroup group(cx, templateObj->group());
|
||||
return ObjectCreateImpl(cx, proto, GenericObject, group);
|
||||
}
|
||||
|
|
|
@ -1609,12 +1609,12 @@ js::RegExpInstanceOptimizableRaw(JSContext* cx, JSObject* rx, JSObject* proto, u
|
|||
return true;
|
||||
}
|
||||
|
||||
if (rx->hasLazyPrototype()) {
|
||||
if (!rx->hasStaticPrototype()) {
|
||||
*result = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (rx->getTaggedProto().toObjectOrNull() != proto) {
|
||||
if (rx->staticPrototype() != proto) {
|
||||
*result = false;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1679,7 +1679,7 @@ TypedObject::obj_lookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
|||
return true;
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
objp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
|
@ -1751,7 +1751,7 @@ TypedObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id, bool*
|
|||
}
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
*foundp = false;
|
||||
return true;
|
||||
|
@ -1808,7 +1808,7 @@ TypedObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiv
|
|||
}
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
vp.setUndefined();
|
||||
return true;
|
||||
|
@ -1836,7 +1836,7 @@ TypedObject::obj_getElement(JSContext* cx, HandleObject obj, HandleValue receive
|
|||
return obj_getArrayElement(cx, typedObj, descr, index, vp);
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
vp.setUndefined();
|
||||
return true;
|
||||
|
@ -2019,7 +2019,7 @@ TypedObject::obj_deleteProperty(JSContext* cx, HandleObject obj, HandleId id, Ob
|
|||
if (IsOwnId(cx, obj, id))
|
||||
return ReportPropertyError(cx, JSMSG_CANT_DELETE, id);
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto)
|
||||
return result.succeed();
|
||||
|
||||
|
|
|
@ -530,7 +530,8 @@ class TypedObject : public JSObject
|
|||
|
||||
public:
|
||||
TypedProto& typedProto() const {
|
||||
return getProto()->as<TypedProto>();
|
||||
// Typed objects' prototypes can't be modified.
|
||||
return staticPrototype()->as<TypedProto>();
|
||||
}
|
||||
|
||||
TypeDescr& typeDescr() const {
|
||||
|
|
|
@ -785,12 +785,14 @@ IsCacheableSetPropAddSlot(JSContext* cx, JSObject* obj, Shape* oldShape,
|
|||
size_t chainDepth = 0;
|
||||
// Walk up the object prototype chain and ensure that all prototypes are
|
||||
// native, and that all prototypes have no setter defined on the property.
|
||||
for (JSObject* proto = obj->getProto(); proto; proto = proto->getProto()) {
|
||||
for (JSObject* proto = obj->staticPrototype(); proto; proto = proto->staticPrototype()) {
|
||||
chainDepth++;
|
||||
// if prototype is non-native, don't optimize
|
||||
if (!proto->isNative())
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(proto->hasStaticPrototype());
|
||||
|
||||
// if prototype defines this property in a non-plain way, don't optimize
|
||||
Shape* protoShape = proto->as<NativeObject>().lookup(cx, id);
|
||||
if (protoShape && !protoShape->hasDefaultSetter())
|
||||
|
@ -2352,13 +2354,13 @@ SetElemAddHasSameShapes(ICSetElem_DenseOrUnboxedArrayAdd* stub, JSObject* obj)
|
|||
if (obj->maybeShape() != nstub->shape(0))
|
||||
return false;
|
||||
|
||||
JSObject* proto = obj->getProto();
|
||||
JSObject* proto = obj->staticPrototype();
|
||||
for (size_t i = 0; i < stub->protoChainDepth(); i++) {
|
||||
if (!proto->isNative())
|
||||
return false;
|
||||
if (proto->as<NativeObject>().lastProperty() != nstub->shape(i + 1))
|
||||
return false;
|
||||
proto = obj->getProto();
|
||||
proto = obj->staticPrototype();
|
||||
if (!proto) {
|
||||
if (i != stub->protoChainDepth() - 1)
|
||||
return false;
|
||||
|
@ -2479,12 +2481,12 @@ CanOptimizeDenseOrUnboxedArraySetElem(JSObject* obj, uint32_t index,
|
|||
// Scan the prototype and shape chain to make sure that this is not the case.
|
||||
if (obj->isIndexed())
|
||||
return false;
|
||||
JSObject* curObj = obj->getProto();
|
||||
JSObject* curObj = obj->staticPrototype();
|
||||
while (curObj) {
|
||||
++*protoDepthOut;
|
||||
if (!curObj->isNative() || curObj->isIndexed())
|
||||
return false;
|
||||
curObj = curObj->getProto();
|
||||
curObj = curObj->staticPrototype();
|
||||
}
|
||||
|
||||
if (*protoDepthOut > ICSetElem_DenseOrUnboxedArrayAdd::MAX_PROTO_CHAIN_DEPTH)
|
||||
|
@ -3698,7 +3700,7 @@ TryAttachGlobalNameValueStub(JSContext* cx, HandleScript script, jsbytecode* pc,
|
|||
if (current == globalLexical) {
|
||||
current = &globalLexical->global();
|
||||
} else {
|
||||
JSObject* proto = current->getProto();
|
||||
JSObject* proto = current->staticPrototype();
|
||||
if (!proto || !proto->is<NativeObject>())
|
||||
return true;
|
||||
current = &proto->as<NativeObject>();
|
||||
|
@ -3773,7 +3775,7 @@ TryAttachGlobalNameAccessorStub(JSContext* cx, HandleScript script, jsbytecode*
|
|||
shape = current->lookup(cx, id);
|
||||
if (shape)
|
||||
break;
|
||||
JSObject* proto = current->getProto();
|
||||
JSObject* proto = current->staticPrototype();
|
||||
if (!proto || !proto->is<NativeObject>())
|
||||
return true;
|
||||
current = &proto->as<NativeObject>();
|
||||
|
|
|
@ -137,12 +137,10 @@ GeneratePrototypeGuards(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
|
|||
|
||||
if (obj->hasUncacheableProto()) {
|
||||
// If the shape does not imply the proto, emit an explicit proto guard.
|
||||
writer.guardProto(objId, obj->getProto());
|
||||
writer.guardProto(objId, obj->staticPrototype());
|
||||
}
|
||||
|
||||
JSObject* pobj = IsCacheableDOMProxy(obj)
|
||||
? obj->getTaggedProto().toObjectOrNull()
|
||||
: obj->getProto();
|
||||
JSObject* pobj = obj->staticPrototype();
|
||||
if (!pobj)
|
||||
return;
|
||||
|
||||
|
@ -151,12 +149,12 @@ GeneratePrototypeGuards(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
|
|||
ObjOperandId protoId = writer.loadObject(pobj);
|
||||
if (pobj->isSingleton()) {
|
||||
// Singletons can have their group's |proto| mutated directly.
|
||||
writer.guardProto(protoId, pobj->getProto());
|
||||
writer.guardProto(protoId, pobj->staticPrototype());
|
||||
} else {
|
||||
writer.guardGroup(protoId, pobj->group());
|
||||
}
|
||||
}
|
||||
pobj = pobj->getProto();
|
||||
pobj = pobj->staticPrototype();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,12 +197,12 @@ EmitReadSlotResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
|
|||
// The property does not exist. Guard on everything in the prototype
|
||||
// chain. This is guaranteed to see only Native objects because of
|
||||
// CanAttachNativeGetProp().
|
||||
JSObject* proto = obj->getTaggedProto().toObjectOrNull();
|
||||
JSObject* proto = obj->taggedProto().toObjectOrNull();
|
||||
ObjOperandId lastObjId = objId;
|
||||
while (proto) {
|
||||
ObjOperandId protoId = writer.loadProto(lastObjId);
|
||||
writer.guardShape(protoId, proto->as<NativeObject>().lastProperty());
|
||||
proto = proto->getProto();
|
||||
proto = proto->staticPrototype();
|
||||
lastObjId = protoId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6271,7 +6271,7 @@ IonBuilder::createThisScriptedSingleton(JSFunction* target, MDefinition* callee)
|
|||
return nullptr;
|
||||
if (!templateObject->is<PlainObject>() && !templateObject->is<UnboxedPlainObject>())
|
||||
return nullptr;
|
||||
if (templateObject->getProto() != proto)
|
||||
if (templateObject->staticPrototype() != proto)
|
||||
return nullptr;
|
||||
|
||||
TypeSet::ObjectKey* templateObjectKey = TypeSet::ObjectKey::get(templateObject->group());
|
||||
|
@ -6318,7 +6318,7 @@ IonBuilder::createThisScriptedBaseline(MDefinition* callee)
|
|||
return nullptr;
|
||||
|
||||
JSObject* proto = checkNurseryObject(&protov.toObject());
|
||||
if (proto != templateObject->getProto())
|
||||
if (proto != templateObject->staticPrototype())
|
||||
return nullptr;
|
||||
|
||||
TypeSet::ObjectKey* templateObjectKey = TypeSet::ObjectKey::get(templateObject->group());
|
||||
|
@ -8106,7 +8106,7 @@ IonBuilder::testSingletonProperty(JSObject* obj, jsid id)
|
|||
if (ObjectHasExtraOwnProperty(compartment, objKey, id))
|
||||
return nullptr;
|
||||
|
||||
obj = checkNurseryObject(obj->getProto());
|
||||
obj = checkNurseryObject(obj->staticPrototype());
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
|
|
@ -422,12 +422,10 @@ GeneratePrototypeGuards(JSContext* cx, IonScript* ion, MacroAssembler& masm, JSO
|
|||
// use objectReg in the rest of this function.
|
||||
masm.loadPtr(Address(objectReg, JSObject::offsetOfGroup()), scratchReg);
|
||||
Address proto(scratchReg, ObjectGroup::offsetOfProto());
|
||||
masm.branchPtr(Assembler::NotEqual, proto, ImmGCPtr(obj->getProto()), failures);
|
||||
masm.branchPtr(Assembler::NotEqual, proto, ImmGCPtr(obj->staticPrototype()), failures);
|
||||
}
|
||||
|
||||
JSObject* pobj = IsCacheableDOMProxy(obj)
|
||||
? obj->getTaggedProto().toObjectOrNull()
|
||||
: obj->getProto();
|
||||
JSObject* pobj = obj->staticPrototype();
|
||||
if (!pobj)
|
||||
return;
|
||||
while (pobj != holder) {
|
||||
|
@ -438,12 +436,14 @@ GeneratePrototypeGuards(JSContext* cx, IonScript* ion, MacroAssembler& masm, JSO
|
|||
// Singletons can have their group's |proto| mutated directly.
|
||||
masm.loadPtr(groupAddr, scratchReg);
|
||||
Address protoAddr(scratchReg, ObjectGroup::offsetOfProto());
|
||||
masm.branchPtr(Assembler::NotEqual, protoAddr, ImmGCPtr(pobj->getProto()), failures);
|
||||
masm.branchPtr(Assembler::NotEqual, protoAddr, ImmGCPtr(pobj->staticPrototype()),
|
||||
failures);
|
||||
} else {
|
||||
masm.branchPtr(Assembler::NotEqual, groupAddr, ImmGCPtr(pobj->group()), failures);
|
||||
}
|
||||
}
|
||||
pobj = pobj->getProto();
|
||||
|
||||
pobj = pobj->staticPrototype();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,7 +459,7 @@ jit::IsCacheableProtoChainForIonOrCacheIR(JSObject* obj, JSObject* holder)
|
|||
* chain and must check for null proto. The prototype chain can be
|
||||
* altered during the lookupProperty call.
|
||||
*/
|
||||
JSObject* proto = obj->getProto();
|
||||
JSObject* proto = obj->staticPrototype();
|
||||
if (!proto || !proto->isNative())
|
||||
return false;
|
||||
obj = proto;
|
||||
|
@ -500,7 +500,7 @@ IsCacheableNoProperty(JSObject* obj, JSObject* holder, Shape* shape, jsbytecode*
|
|||
while (obj2) {
|
||||
if (!obj2->isNative())
|
||||
return false;
|
||||
obj2 = obj2->getProto();
|
||||
obj2 = obj2->staticPrototype();
|
||||
}
|
||||
|
||||
// The pc is nullptr if the cache is idempotent. We cannot share missing
|
||||
|
@ -819,19 +819,20 @@ GenerateReadSlot(JSContext* cx, IonScript* ion, MacroAssembler& masm,
|
|||
} else {
|
||||
// The property does not exist. Guard on everything in the
|
||||
// prototype chain.
|
||||
JSObject* proto = obj->getTaggedProto().toObjectOrNull();
|
||||
JSObject* proto = obj->staticPrototype();
|
||||
Register lastReg = object;
|
||||
MOZ_ASSERT(scratchReg != object);
|
||||
while (proto) {
|
||||
masm.loadObjProto(lastReg, scratchReg);
|
||||
|
||||
// Guard the shape of the current prototype.
|
||||
MOZ_ASSERT(proto->hasStaticPrototype());
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(scratchReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(proto->as<NativeObject>().lastProperty()),
|
||||
&prototypeFailures);
|
||||
|
||||
proto = proto->getProto();
|
||||
proto = proto->staticPrototype();
|
||||
lastReg = scratchReg;
|
||||
}
|
||||
|
||||
|
@ -1803,7 +1804,7 @@ GetPropertyIC::tryAttachDOMProxyUnshadowed(JSContext* cx, HandleScript outerScri
|
|||
MOZ_ASSERT(monitoredResult());
|
||||
MOZ_ASSERT(output().hasValue());
|
||||
|
||||
RootedObject checkObj(cx, obj->getTaggedProto().toObjectOrNull());
|
||||
RootedObject checkObj(cx, obj->staticPrototype());
|
||||
RootedNativeObject holder(cx);
|
||||
RootedShape shape(cx);
|
||||
|
||||
|
@ -2906,7 +2907,7 @@ IsCacheableDOMProxyUnshadowedSetterCall(JSContext* cx, HandleObject obj, HandleI
|
|||
{
|
||||
MOZ_ASSERT(IsCacheableDOMProxy(obj));
|
||||
|
||||
RootedObject checkObj(cx, obj->getTaggedProto().toObjectOrNull());
|
||||
RootedObject checkObj(cx, obj->staticPrototype());
|
||||
if (!checkObj)
|
||||
return false;
|
||||
|
||||
|
@ -3029,7 +3030,7 @@ GenerateAddSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
|
|||
CheckTypeSetForWrite(masm, obj, newShape->propid(), tempReg, value, failures);
|
||||
|
||||
// Guard shapes along prototype chain.
|
||||
JSObject* proto = obj->getProto();
|
||||
JSObject* proto = obj->staticPrototype();
|
||||
Register protoReg = tempReg;
|
||||
bool first = true;
|
||||
while (proto) {
|
||||
|
@ -3042,7 +3043,7 @@ GenerateAddSlot(JSContext* cx, MacroAssembler& masm, IonCache::StubAttacher& att
|
|||
// Ensure that its shape matches.
|
||||
masm.branchTestObjShape(Assembler::NotEqual, protoReg, protoShape, failures);
|
||||
|
||||
proto = proto->getProto();
|
||||
proto = proto->staticPrototype();
|
||||
}
|
||||
|
||||
// Call a stub to (re)allocate dynamic slots, if necessary.
|
||||
|
@ -3248,7 +3249,7 @@ PrototypeChainShadowsPropertyAdd(JSContext* cx, JSObject* obj, jsid id)
|
|||
// Walk up the object prototype chain and ensure that all prototypes
|
||||
// are native, and that all prototypes have no getter or setter
|
||||
// defined on the property
|
||||
for (JSObject* proto = obj->getProto(); proto; proto = proto->getProto()) {
|
||||
for (JSObject* proto = obj->staticPrototype(); proto; proto = proto->staticPrototype()) {
|
||||
// If prototype is non-native, don't optimize
|
||||
if (!proto->isNative())
|
||||
return true;
|
||||
|
@ -3849,7 +3850,7 @@ GetPropertyIC::canAttachDenseElementHole(JSObject* obj, HandleValue idval, Typed
|
|||
if (ClassCanHaveExtraProperties(obj->getClass()))
|
||||
return false;
|
||||
|
||||
JSObject* proto = obj->getProto();
|
||||
JSObject* proto = obj->staticPrototype();
|
||||
if (!proto)
|
||||
break;
|
||||
|
||||
|
@ -3885,10 +3886,10 @@ GenerateDenseElementHole(JSContext* cx, MacroAssembler& masm, IonCache::StubAtta
|
|||
if (obj->hasUncacheableProto()) {
|
||||
masm.loadPtr(Address(object, JSObject::offsetOfGroup()), scratchReg);
|
||||
Address proto(scratchReg, ObjectGroup::offsetOfProto());
|
||||
masm.branchPtr(Assembler::NotEqual, proto, ImmGCPtr(obj->getProto()), &failures);
|
||||
masm.branchPtr(Assembler::NotEqual, proto, ImmGCPtr(obj->staticPrototype()), &failures);
|
||||
}
|
||||
|
||||
JSObject* pobj = obj->getProto();
|
||||
JSObject* pobj = obj->staticPrototype();
|
||||
while (pobj) {
|
||||
MOZ_ASSERT(pobj->as<NativeObject>().lastProperty());
|
||||
|
||||
|
@ -3914,7 +3915,7 @@ GenerateDenseElementHole(JSContext* cx, MacroAssembler& masm, IonCache::StubAtta
|
|||
Address initLength(scratchReg, ObjectElements::offsetOfInitializedLength());
|
||||
masm.branch32(Assembler::NotEqual, initLength, Imm32(0), &failures);
|
||||
|
||||
pobj = pobj->getProto();
|
||||
pobj = pobj->staticPrototype();
|
||||
}
|
||||
|
||||
// Ensure the index is an int32 value.
|
||||
|
@ -4318,7 +4319,7 @@ IsDenseElementSetInlineable(JSObject* obj, const Value& idval, ConstantOrRegiste
|
|||
// Scan the prototype and shape chain to make sure that this is not the case.
|
||||
JSObject* curObj = obj;
|
||||
while (curObj) {
|
||||
// Ensure object is native.
|
||||
// Ensure object is native. (This guarantees static prototype below.)
|
||||
if (!curObj->isNative())
|
||||
return false;
|
||||
|
||||
|
@ -4326,7 +4327,7 @@ IsDenseElementSetInlineable(JSObject* obj, const Value& idval, ConstantOrRegiste
|
|||
if (curObj->isIndexed())
|
||||
return false;
|
||||
|
||||
curObj = curObj->getProto();
|
||||
curObj = curObj->staticPrototype();
|
||||
}
|
||||
|
||||
*checkTypeset = false;
|
||||
|
|
|
@ -2064,7 +2064,7 @@ IonBuilder::inlineObjectCreate(CallInfo& callInfo)
|
|||
|
||||
// Ensure the argument matches the template object's prototype.
|
||||
MDefinition* arg = callInfo.getArg(0);
|
||||
if (JSObject* proto = templateObject->getProto()) {
|
||||
if (JSObject* proto = templateObject->staticPrototype()) {
|
||||
if (IsInsideNursery(proto))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
|
|
|
@ -5623,7 +5623,7 @@ jit::PropertyReadNeedsTypeBarrier(JSContext* propertycx,
|
|||
if (key->isSingleton())
|
||||
obj = key->singleton();
|
||||
else
|
||||
obj = key->proto().isLazy() ? nullptr : key->proto().toObjectOrNull();
|
||||
obj = key->proto().isDynamic() ? nullptr : key->proto().toObjectOrNull();
|
||||
|
||||
while (obj) {
|
||||
if (!obj->getClass()->isNative())
|
||||
|
@ -5647,7 +5647,7 @@ jit::PropertyReadNeedsTypeBarrier(JSContext* propertycx,
|
|||
}
|
||||
}
|
||||
|
||||
obj = obj->getProto();
|
||||
obj = obj->staticPrototype();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5835,7 +5835,7 @@ PrototypeHasIndexedProperty(IonBuilder* builder, JSObject* obj)
|
|||
HeapTypeSetKey index = key->property(JSID_VOID);
|
||||
if (index.nonData(builder->constraints()) || index.isOwnProperty(builder->constraints()))
|
||||
return true;
|
||||
obj = obj->getProto();
|
||||
obj = obj->staticPrototype();
|
||||
} while (obj);
|
||||
|
||||
return false;
|
||||
|
|
|
@ -2172,7 +2172,7 @@ JSObject*
|
|||
GetDOMProxyProto(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(IsCacheableDOMProxy(obj));
|
||||
return obj->getTaggedProto().toObjectOrNull();
|
||||
return obj->staticPrototype();
|
||||
}
|
||||
|
||||
// Look up a property's shape on an object, being careful never to do any effectful
|
||||
|
@ -2243,30 +2243,25 @@ 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;
|
||||
while (cur != holder) {
|
||||
// We cannot assume that we find the holder object on the prototype
|
||||
// chain and must check for null proto. The prototype chain can be
|
||||
// altered during the lookupProperty call.
|
||||
JSObject* proto;
|
||||
if (isDOMProxy && cur == obj)
|
||||
proto = cur->getTaggedProto().toObjectOrNull();
|
||||
else
|
||||
proto = cur->getProto();
|
||||
MOZ_ASSERT(!cur->hasDynamicPrototype());
|
||||
|
||||
if (!proto || !proto->isNative())
|
||||
// Don't handle objects which require a prototype guard. This should
|
||||
// be uncommon so handling it is likely not worth the complexity.
|
||||
if (cur->hasUncacheableProto())
|
||||
return false;
|
||||
|
||||
if (proto->hasUncacheableProto())
|
||||
JSObject* proto = cur->staticPrototype();
|
||||
if (!proto || !proto->isNative())
|
||||
return false;
|
||||
|
||||
cur = proto;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2630,7 +2625,7 @@ CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, PropertyName* name,
|
|||
return false;
|
||||
}
|
||||
|
||||
JSObject* proto = curObj->getTaggedProto().toObjectOrNull();
|
||||
JSObject* proto = curObj->staticPrototype();
|
||||
if (!proto)
|
||||
break;
|
||||
|
||||
|
@ -3049,13 +3044,15 @@ ICGetPropNativeCompiler::generateStubCode(MacroAssembler& masm)
|
|||
bool
|
||||
GetProtoShapes(JSObject* obj, size_t protoChainDepth, MutableHandle<ShapeVector> shapes)
|
||||
{
|
||||
JSObject* curProto = obj->getProto();
|
||||
JSObject* curProto = obj->staticPrototype();
|
||||
for (size_t i = 0; i < protoChainDepth; i++) {
|
||||
if (!shapes.append(curProto->as<NativeObject>().lastProperty()))
|
||||
return false;
|
||||
curProto = curProto->getProto();
|
||||
curProto = curProto->staticPrototype();
|
||||
}
|
||||
MOZ_ASSERT(!curProto);
|
||||
|
||||
MOZ_ASSERT(!curProto,
|
||||
"longer prototype chain encountered than this stub permits!");
|
||||
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
|
||||
// initializes the prototype chain lazily. Only attempt to optimize here
|
||||
// if we know the prototype chain has been initialized.
|
||||
if (!maybeObj || !maybeObj->getProto())
|
||||
if (!maybeObj || !maybeObj->staticPrototype())
|
||||
return true;
|
||||
|
||||
if (!JSID_IS_ATOM(id))
|
||||
|
|
|
@ -828,26 +828,33 @@ ObjectMayHaveExtraIndexedOwnProperties(JSObject* 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
|
||||
js::ObjectMayHaveExtraIndexedProperties(JSObject* 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.
|
||||
*/
|
||||
MOZ_ASSERT_IF(obj->hasDynamicPrototype(), !obj->isNative());
|
||||
|
||||
if (ObjectMayHaveExtraIndexedOwnProperties(obj))
|
||||
return true;
|
||||
|
||||
while ((obj = obj->getProto()) != nullptr) {
|
||||
do {
|
||||
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))
|
||||
return true;
|
||||
if (GetAnyBoxedOrUnboxedInitializedLength(obj) != 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
} while (true);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -2696,7 +2703,7 @@ GetIndexedPropertiesInRange(JSContext* cx, HandleObject obj, uint32_t begin, uin
|
|||
do {
|
||||
if (!pobj->isNative() || pobj->getClass()->getResolve() || pobj->getOpsLookupProperty())
|
||||
return true;
|
||||
} while ((pobj = pobj->getProto()));
|
||||
} while ((pobj = pobj->staticPrototype()));
|
||||
|
||||
// Collect indexed property names.
|
||||
pobj = obj;
|
||||
|
@ -2741,7 +2748,7 @@ GetIndexedPropertiesInRange(JSContext* cx, HandleObject obj, uint32_t begin, uin
|
|||
return false;
|
||||
}
|
||||
}
|
||||
} while ((pobj = pobj->getProto()));
|
||||
} while ((pobj = pobj->staticPrototype()));
|
||||
|
||||
// Sort the indexes.
|
||||
Vector<uint32_t> tmp(cx);
|
||||
|
@ -3605,7 +3612,7 @@ NewArrayTryReuseGroup(JSContext* cx, JSObject* obj, size_t length,
|
|||
if (!obj->is<ArrayObject>() && !obj->is<UnboxedArrayObject>())
|
||||
return NewArray<maxLength>(cx, length, nullptr, newKind);
|
||||
|
||||
if (obj->getProto() != cx->global()->maybeGetArrayPrototype())
|
||||
if (obj->staticPrototype() != cx->global()->maybeGetArrayPrototype())
|
||||
return NewArray<maxLength>(cx, length, nullptr, newKind);
|
||||
|
||||
RootedObjectGroup group(cx, obj->getGroup(cx));
|
||||
|
|
|
@ -456,7 +456,7 @@ JSCompartment::wrap(JSContext* cx, MutableHandleObject obj, HandleObject existin
|
|||
RootedObject existing(cx, existingArg);
|
||||
if (existing) {
|
||||
// Is it possible to reuse |existing|?
|
||||
if (!existing->getTaggedProto().isLazy() ||
|
||||
if (existing->hasStaticPrototype() ||
|
||||
// Note: Class asserted above, so all that's left to check is callability
|
||||
existing->isCallable() ||
|
||||
obj->isCallable())
|
||||
|
|
|
@ -353,8 +353,7 @@ JS_FRIEND_API(JSObject*)
|
|||
js::GetPrototypeNoProxy(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(!obj->is<js::ProxyObject>());
|
||||
MOZ_ASSERT(!obj->getTaggedProto().isLazy());
|
||||
return obj->getTaggedProto().toObjectOrNull();
|
||||
return obj->staticPrototype();
|
||||
}
|
||||
|
||||
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
|
||||
* the original function provided that its prototype is correct.
|
||||
*/
|
||||
if (fun->getProto() == clone->getProto())
|
||||
if (fun->staticPrototype() == clone->staticPrototype())
|
||||
clone->setGroup(fun->group());
|
||||
return clone;
|
||||
}
|
||||
|
@ -2160,8 +2160,8 @@ js::ReportIncompatibleMethod(JSContext* cx, CallReceiver call, const Class* clas
|
|||
if (thisv.isObject()) {
|
||||
MOZ_ASSERT(thisv.toObject().getClass() != clasp ||
|
||||
!thisv.toObject().isNative() ||
|
||||
!thisv.toObject().getProto() ||
|
||||
thisv.toObject().getProto()->getClass() != clasp);
|
||||
!thisv.toObject().staticPrototype() ||
|
||||
thisv.toObject().staticPrototype()->getClass() != clasp);
|
||||
} else if (thisv.isString()) {
|
||||
MOZ_ASSERT(clasp != &StringObject::class_);
|
||||
} else if (thisv.isNumber()) {
|
||||
|
|
|
@ -111,8 +111,10 @@ Enumerate(JSContext* cx, HandleObject pobj, jsid id,
|
|||
// It's not necessary to add properties to the hash table at the end of
|
||||
// the prototype chain, but custom enumeration behaviors might return
|
||||
// duplicated properties, so always add in such cases.
|
||||
if ((pobj->is<ProxyObject>() || pobj->getProto() || pobj->getOpsEnumerate()) && !ht->add(p, id))
|
||||
return false;
|
||||
if (pobj->is<ProxyObject>() || pobj->staticPrototype() || pobj->getOpsEnumerate()) {
|
||||
if (!ht->add(p, id))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Symbol-keyed properties and nonenumerable properties are skipped unless
|
||||
|
@ -701,7 +703,11 @@ VectorToKeyIterator(JSContext* cx, HandleObject obj, unsigned flags, AutoIdVecto
|
|||
size_t ind = 0;
|
||||
do {
|
||||
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);
|
||||
MOZ_ASSERT(ind == numGuards);
|
||||
}
|
||||
|
@ -843,10 +849,10 @@ js::GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleOb
|
|||
CanCompareIterableObjectToCache(obj) &&
|
||||
ReceiverGuard(obj) == lastni->guard_array[0])
|
||||
{
|
||||
JSObject* proto = obj->getProto();
|
||||
JSObject* proto = obj->staticPrototype();
|
||||
if (CanCompareIterableObjectToCache(proto) &&
|
||||
ReceiverGuard(proto) == lastni->guard_array[1] &&
|
||||
!proto->getProto())
|
||||
!proto->staticPrototype())
|
||||
{
|
||||
objp.set(last);
|
||||
UpdateNativeIterator(lastni, obj);
|
||||
|
@ -856,12 +862,9 @@ js::GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleOb
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The iterator object for JSITER_ENUMERATE never escapes, so we
|
||||
* 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.
|
||||
*/
|
||||
// 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
|
||||
// old, inactive iterator object.
|
||||
{
|
||||
JSObject* pobj = obj;
|
||||
do {
|
||||
|
@ -869,11 +872,13 @@ js::GetIterator(JSContext* cx, HandleObject obj, unsigned flags, MutableHandleOb
|
|||
guards.clear();
|
||||
goto miss;
|
||||
}
|
||||
|
||||
ReceiverGuard guard(pobj);
|
||||
key = (key + (key << 16)) ^ guard.hash();
|
||||
if (!guards.append(guard))
|
||||
return false;
|
||||
pobj = pobj->getProto();
|
||||
|
||||
pobj = pobj->staticPrototype();
|
||||
} 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
|
||||
// dictionary mode.
|
||||
RootedShape last(cx, EmptyShape::getInitialShape(cx, nobj->getClass(),
|
||||
nobj->getTaggedProto(),
|
||||
nobj->taggedProto(),
|
||||
nobj->numFixedSlots(),
|
||||
nobj->lastProperty()->getObjectFlags()));
|
||||
if (!last)
|
||||
|
@ -689,7 +689,7 @@ NewObjectCache::fillProto(EntryIndex entry, const Class* clasp, js::TaggedProto
|
|||
gc::AllocKind kind, NativeObject* obj)
|
||||
{
|
||||
MOZ_ASSERT_IF(proto.isObject(), !proto.toObject()->is<GlobalObject>());
|
||||
MOZ_ASSERT(obj->getTaggedProto() == proto);
|
||||
MOZ_ASSERT(obj->taggedProto() == proto);
|
||||
return fill(entry, clasp, proto.raw(), kind, obj);
|
||||
}
|
||||
|
||||
|
@ -914,7 +914,7 @@ CreateThisForFunctionWithGroup(JSContext* cx, HandleObjectGroup group,
|
|||
return nullptr;
|
||||
|
||||
if (newKind == SingletonObject) {
|
||||
Rooted<TaggedProto> proto(cx, TaggedProto(templateObject->getProto()));
|
||||
Rooted<TaggedProto> proto(cx, TaggedProto(templateObject->staticPrototype()));
|
||||
if (!res->splicePrototype(cx, &PlainObject::class_, proto))
|
||||
return nullptr;
|
||||
} else {
|
||||
|
@ -1341,13 +1341,13 @@ InitializePropertiesFromCompatibleNativeObject(JSContext* cx,
|
|||
|
||||
MOZ_ASSERT(!src->hasPrivate());
|
||||
RootedShape shape(cx);
|
||||
if (src->getProto() == dst->getProto()) {
|
||||
if (src->staticPrototype() == dst->staticPrototype()) {
|
||||
shape = src->lastProperty();
|
||||
} else {
|
||||
// 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
|
||||
// dst's object flags are 0.
|
||||
shape = EmptyShape::getInitialShape(cx, dst->getClass(), dst->getTaggedProto(),
|
||||
shape = EmptyShape::getInitialShape(cx, dst->getClass(), dst->taggedProto(),
|
||||
dst->numFixedSlots(), 0);
|
||||
if (!shape)
|
||||
return false;
|
||||
|
@ -1943,7 +1943,7 @@ js::SetClassAndProto(JSContext* cx, HandleObject obj,
|
|||
MOZ_ASSERT(obj == oldproto);
|
||||
break;
|
||||
}
|
||||
oldproto = oldproto->getProto();
|
||||
oldproto = oldproto->staticPrototype();
|
||||
}
|
||||
|
||||
if (proto.isObject() && !proto.toObject()->setDelegate(cx))
|
||||
|
@ -1993,7 +1993,7 @@ JSObject::changeToSingleton(JSContext* cx, HandleObject obj)
|
|||
MarkObjectGroupUnknownProperties(cx, obj->group());
|
||||
|
||||
ObjectGroup* group = ObjectGroup::lazySingletonGroup(cx, obj->getClass(),
|
||||
obj->getTaggedProto());
|
||||
obj->taggedProto());
|
||||
if (!group)
|
||||
return false;
|
||||
|
||||
|
@ -2295,7 +2295,7 @@ js::LookupPropertyPure(ExclusiveContext* cx, JSObject* obj, jsid id, JSObject**
|
|||
return true;
|
||||
}
|
||||
|
||||
obj = obj->getProto();
|
||||
obj = obj->staticPrototype();
|
||||
} while (obj);
|
||||
|
||||
*objp = nullptr;
|
||||
|
@ -2498,13 +2498,13 @@ bool
|
|||
js::GetPrototypeIfOrdinary(JSContext* cx, HandleObject obj, bool* isOrdinary,
|
||||
MutableHandleObject protop)
|
||||
{
|
||||
if (obj->getTaggedProto().isLazy()) {
|
||||
if (obj->hasDynamicPrototype()) {
|
||||
MOZ_ASSERT(obj->is<js::ProxyObject>());
|
||||
return js::Proxy::getPrototypeIfOrdinary(cx, obj, isOrdinary, protop);
|
||||
}
|
||||
|
||||
*isOrdinary = true;
|
||||
protop.set(obj->getTaggedProto().toObjectOrNull());
|
||||
protop.set(obj->staticPrototype());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2527,19 +2527,15 @@ JS_ImmutablePrototypesEnabled()
|
|||
bool
|
||||
js::SetPrototype(JSContext* cx, HandleObject obj, HandleObject proto, JS::ObjectOpResult& result)
|
||||
{
|
||||
/*
|
||||
* If |obj| has a "lazy" [[Prototype]], it is 1) a proxy 2) whose handler's
|
||||
* {get,set}Prototype and setImmutablePrototype methods mediate access to
|
||||
* |obj.[[Prototype]]|. The Proxy subsystem is responsible for responding
|
||||
* to such attempts.
|
||||
*/
|
||||
if (obj->hasLazyPrototype()) {
|
||||
// The proxy trap subsystem fully handles prototype-setting for proxies
|
||||
// with dynamic [[Prototype]]s.
|
||||
if (obj->hasDynamicPrototype()) {
|
||||
MOZ_ASSERT(obj->is<ProxyObject>());
|
||||
return Proxy::setPrototype(cx, obj, proto, result);
|
||||
}
|
||||
|
||||
/* Disallow mutation of immutable [[Prototype]]s. */
|
||||
if (obj->nonLazyPrototypeIsImmutable() && ImmutablePrototypesEnabled)
|
||||
if (obj->staticPrototypeIsImmutable() && ImmutablePrototypesEnabled)
|
||||
return result.fail(JSMSG_CANT_SET_PROTO);
|
||||
|
||||
/*
|
||||
|
@ -2576,7 +2572,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.
|
||||
* Since the values in question are objects, we can just compare pointers.
|
||||
*/
|
||||
if (proto == obj->getProto())
|
||||
if (proto == obj->staticPrototype())
|
||||
return result.succeed();
|
||||
|
||||
/* ES6 9.1.2 step 5 forbids changing [[Prototype]] if not [[Extensible]]. */
|
||||
|
@ -2786,7 +2782,7 @@ js::DefineElement(ExclusiveContext* cx, HandleObject obj, uint32_t index, Handle
|
|||
bool
|
||||
js::SetImmutablePrototype(ExclusiveContext* cx, HandleObject obj, bool* succeeded)
|
||||
{
|
||||
if (obj->hasLazyPrototype()) {
|
||||
if (obj->hasDynamicPrototype()) {
|
||||
if (!cx->shouldBeJSContext())
|
||||
return false;
|
||||
return Proxy::setImmutablePrototype(cx->asJSContext(), obj, succeeded);
|
||||
|
@ -3471,7 +3467,8 @@ JSObject::dump()
|
|||
if (obj->hasUncacheableProto()) fprintf(stderr, " has_uncacheable_proto");
|
||||
if (obj->hadElementsAccess()) fprintf(stderr, " had_elements_access");
|
||||
if (obj->wasNewScriptCleared()) fprintf(stderr, " new_script_cleared");
|
||||
if (!obj->hasLazyPrototype() && obj->nonLazyPrototypeIsImmutable()) fprintf(stderr, " immutable_prototype");
|
||||
if (obj->hasStaticPrototype() && obj->staticPrototypeIsImmutable())
|
||||
fprintf(stderr, " immutable_prototype");
|
||||
|
||||
if (obj->isNative()) {
|
||||
NativeObject* nobj = &obj->as<NativeObject>();
|
||||
|
@ -3497,9 +3494,9 @@ JSObject::dump()
|
|||
}
|
||||
|
||||
fprintf(stderr, "proto ");
|
||||
TaggedProto proto = obj->getTaggedProto();
|
||||
if (proto.isLazy())
|
||||
fprintf(stderr, "<lazy>");
|
||||
TaggedProto proto = obj->taggedProto();
|
||||
if (proto.isDynamic())
|
||||
fprintf(stderr, "<dynamic>");
|
||||
else
|
||||
dumpValue(ObjectOrNullValue(proto.toObjectOrNull()));
|
||||
fputc('\n', stderr);
|
||||
|
|
|
@ -265,6 +265,9 @@ class JSObject : public js::gc::Cell
|
|||
// hasUncacheableProto flag.
|
||||
inline bool hasUncacheableProto() const;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -355,20 +358,26 @@ class JSObject : public js::gc::Cell
|
|||
}
|
||||
|
||||
/*
|
||||
* We allow the prototype of an object to be lazily computed if the object
|
||||
* is a proxy. In the lazy case, we store (JSObject*)0x1 in the proto field
|
||||
* of the object's group. We offer three ways of getting the prototype:
|
||||
* We permit proxies to dynamically compute their prototype if desired.
|
||||
* (Not all proxies will so desire: in particular, most DOM proxies can
|
||||
* track their prototype with a single, nullable JSObject*.) If a proxy
|
||||
* so desires, we store (JSObject*)0x1 in the proto field of the object's
|
||||
* group.
|
||||
*
|
||||
* 1. obj->getProto() returns the prototype, but asserts if obj is a proxy
|
||||
* with a relevant getPrototype() handler.
|
||||
* 2. obj->getTaggedProto() returns a TaggedProto, which can be tested to
|
||||
* We offer three ways to get an object's prototype:
|
||||
*
|
||||
* 1. obj->staticPrototype() returns the prototype, but it asserts if obj
|
||||
* 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.
|
||||
* 3. js::GetPrototype(cx, obj, &proto) computes the proto of an object.
|
||||
* If obj is a proxy and the proto is lazy, this code may allocate or
|
||||
* GC in order to compute the proto. Currently, it will not run JS code.
|
||||
* If obj is a proxy with dynamically-computed prototype, this code may
|
||||
* perform arbitrary behavior (allocation, GC, run JS) while computing
|
||||
* the proto.
|
||||
*/
|
||||
|
||||
js::TaggedProto getTaggedProto() const {
|
||||
js::TaggedProto taggedProto() const {
|
||||
return group_->proto();
|
||||
}
|
||||
|
||||
|
@ -376,37 +385,34 @@ class JSObject : public js::gc::Cell
|
|||
|
||||
bool uninlinedIsProxy() const;
|
||||
|
||||
JSObject* getProto() const {
|
||||
MOZ_ASSERT(!hasLazyPrototype());
|
||||
return getTaggedProto().toObjectOrNull();
|
||||
JSObject* staticPrototype() const {
|
||||
MOZ_ASSERT(hasStaticPrototype());
|
||||
return taggedProto().toObjectOrNull();
|
||||
}
|
||||
|
||||
// Normal objects and a subset of proxies have uninteresting [[Prototype]].
|
||||
// For such objects the [[Prototype]] is just a value returned when needed
|
||||
// for accesses, or modified in response to requests. These objects store
|
||||
// the [[Prototype]] directly within |obj->type_|.
|
||||
//
|
||||
// Proxies that don't have such a simple [[Prototype]] instead have a
|
||||
// "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;
|
||||
// Normal objects and a subset of proxies have an uninteresting, static
|
||||
// (albeit perhaps mutable) [[Prototype]]. For such objects the
|
||||
// [[Prototype]] is just a value returned when needed for accesses, or
|
||||
// modified in response to requests. These objects store the
|
||||
// [[Prototype]] directly within |obj->group_|.
|
||||
bool hasStaticPrototype() const {
|
||||
return !hasDynamicPrototype();
|
||||
}
|
||||
|
||||
// True iff this object's [[Prototype]] is immutable. Must not be called
|
||||
// on proxies with lazy [[Prototype]]!
|
||||
inline bool nonLazyPrototypeIsImmutable() const;
|
||||
// The remaining proxies have a [[Prototype]] requiring dynamic computation
|
||||
// for every access, going through the proxy handler {get,set}Prototype and
|
||||
// setImmutablePrototype methods. (Wrappers particularly use this to keep
|
||||
// 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);
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ JSObject::setSingleton(js::ExclusiveContext* cx, js::HandleObject obj)
|
|||
MOZ_ASSERT_IF(cx->isJSContext(), !IsInsideNursery(obj));
|
||||
|
||||
js::ObjectGroup* group = js::ObjectGroup::lazySingletonGroup(cx, obj->getClass(),
|
||||
obj->getTaggedProto());
|
||||
obj->taggedProto());
|
||||
if (!group)
|
||||
return false;
|
||||
|
||||
|
@ -152,13 +152,13 @@ JSObject::setGroup(js::ObjectGroup* group)
|
|||
inline bool
|
||||
js::GetPrototype(JSContext* cx, js::HandleObject obj, js::MutableHandleObject protop)
|
||||
{
|
||||
if (obj->getTaggedProto().isLazy()) {
|
||||
if (obj->hasDynamicPrototype()) {
|
||||
MOZ_ASSERT(obj->is<js::ProxyObject>());
|
||||
return js::Proxy::getPrototype(cx, obj, protop);
|
||||
} else {
|
||||
protop.set(obj->getTaggedProto().toObjectOrNull());
|
||||
return true;
|
||||
}
|
||||
|
||||
protop.set(obj->taggedProto().toObjectOrNull());
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
@ -487,9 +487,9 @@ JSObject::isIndexed() const
|
|||
}
|
||||
|
||||
inline bool
|
||||
JSObject::nonLazyPrototypeIsImmutable() const
|
||||
JSObject::staticPrototypeIsImmutable() const
|
||||
{
|
||||
MOZ_ASSERT(!hasLazyPrototype());
|
||||
MOZ_ASSERT(hasStaticPrototype());
|
||||
return hasAllFlags(js::BaseShape::IMMUTABLE_PROTOTYPE);
|
||||
}
|
||||
|
||||
|
@ -564,7 +564,7 @@ ClassMethodIsNative(JSContext* cx, NativeObject* obj, const Class* clasp, jsid m
|
|||
|
||||
Value v;
|
||||
if (!HasDataProperty(cx, obj, methodid, &v)) {
|
||||
JSObject* proto = obj->getProto();
|
||||
JSObject* proto = obj->staticPrototype();
|
||||
if (!proto || proto->getClass() != clasp || !HasDataProperty(cx, &proto->as<NativeObject>(), methodid, &v))
|
||||
return false;
|
||||
}
|
||||
|
@ -585,7 +585,7 @@ HasObjectValueOf(JSObject* obj, JSContext* cx)
|
|||
|
||||
Value v;
|
||||
while (!HasDataProperty(cx, &obj->as<NativeObject>(), valueOf, &v)) {
|
||||
obj = obj->getProto();
|
||||
obj = obj->staticPrototype();
|
||||
if (!obj || obj->is<ProxyObject>() || !obj->isNative())
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -396,14 +396,14 @@ BaseProxyHandler::weakmapKeyDelegate(JSObject* proxy) const
|
|||
bool
|
||||
BaseProxyHandler::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject protop) const
|
||||
{
|
||||
MOZ_CRASH("must override getPrototype with lazy prototype");
|
||||
MOZ_CRASH("must override getPrototype with dynamic prototype");
|
||||
}
|
||||
|
||||
bool
|
||||
BaseProxyHandler::setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
|
||||
ObjectOpResult& result) const
|
||||
{
|
||||
// Disallow sets of protos on proxies with lazy protos, but no hook.
|
||||
// Disallow sets of protos on proxies with dynamic prototypes but no hook.
|
||||
// This keeps us away from the footgun of having the first proto set opt
|
||||
// you out of having dynamic protos altogether.
|
||||
JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_CANT_SET_PROTO_OF,
|
||||
|
@ -415,7 +415,7 @@ bool
|
|||
BaseProxyHandler::getPrototypeIfOrdinary(JSContext* cx, HandleObject proxy, bool* isOrdinary,
|
||||
MutableHandleObject protop) const
|
||||
{
|
||||
MOZ_CRASH("must override getPrototypeIfOrdinary with lazy prototype");
|
||||
MOZ_CRASH("must override getPrototypeIfOrdinary with dynamic prototype");
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -183,7 +183,7 @@ js::AppendUnique(JSContext* cx, AutoIdVector& base, AutoIdVector& others)
|
|||
/* static */ bool
|
||||
Proxy::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject proto)
|
||||
{
|
||||
MOZ_ASSERT(proxy->hasLazyPrototype());
|
||||
MOZ_ASSERT(proxy->hasDynamicPrototype());
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
return proxy->as<ProxyObject>().handler()->getPrototype(cx, proxy, proto);
|
||||
}
|
||||
|
@ -191,7 +191,7 @@ Proxy::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject proto
|
|||
/* static */ bool
|
||||
Proxy::setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto, ObjectOpResult& result)
|
||||
{
|
||||
MOZ_ASSERT(proxy->hasLazyPrototype());
|
||||
MOZ_ASSERT(proxy->hasDynamicPrototype());
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
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,
|
||||
MutableHandleObject proto)
|
||||
{
|
||||
MOZ_ASSERT(proxy->hasLazyPrototype());
|
||||
MOZ_ASSERT(proxy->hasDynamicPrototype());
|
||||
JS_CHECK_RECURSION(cx, return false);
|
||||
return proxy->as<ProxyObject>().handler()->getPrototypeIfOrdinary(cx, proxy, isOrdinary,
|
||||
proto);
|
||||
|
@ -782,7 +782,7 @@ ProxyObject::renew(JSContext* cx, const BaseProxyHandler* handler, Value priv)
|
|||
MOZ_ASSERT_IF(IsCrossCompartmentWrapper(this), IsDeadProxyObject(this));
|
||||
MOZ_ASSERT(getClass() == &ProxyObject::proxyClass);
|
||||
MOZ_ASSERT(!IsWindowProxy(this));
|
||||
MOZ_ASSERT(hasLazyPrototype());
|
||||
MOZ_ASSERT(hasDynamicPrototype());
|
||||
|
||||
setHandler(handler);
|
||||
setCrossCompartmentPrivate(priv);
|
||||
|
|
|
@ -3363,7 +3363,8 @@ CASE(JSOP_LAMBDA)
|
|||
JSObject* obj = Lambda(cx, fun, REGS.fp()->scopeChain());
|
||||
if (!obj)
|
||||
goto error;
|
||||
MOZ_ASSERT(obj->getProto());
|
||||
|
||||
MOZ_ASSERT(obj->staticPrototype());
|
||||
PUSH_OBJECT(*obj);
|
||||
}
|
||||
END_CASE(JSOP_LAMBDA)
|
||||
|
@ -3376,7 +3377,8 @@ CASE(JSOP_LAMBDA_ARROW)
|
|||
JSObject* obj = LambdaArrow(cx, fun, REGS.fp()->scopeChain(), newTarget);
|
||||
if (!obj)
|
||||
goto error;
|
||||
MOZ_ASSERT(obj->getProto());
|
||||
|
||||
MOZ_ASSERT(obj->staticPrototype());
|
||||
REGS.sp[-1].setObject(*obj);
|
||||
}
|
||||
END_CASE(JSOP_LAMBDA_ARROW)
|
||||
|
|
|
@ -566,7 +566,7 @@ LookupPropertyInline(ExclusiveContext* cx,
|
|||
return true;
|
||||
}
|
||||
|
||||
typename MaybeRooted<JSObject*, allowGC>::RootType proto(cx, current->getProto());
|
||||
typename MaybeRooted<JSObject*, allowGC>::RootType proto(cx, current->staticPrototype());
|
||||
|
||||
if (!proto)
|
||||
break;
|
||||
|
|
|
@ -1086,7 +1086,7 @@ PurgeProtoChain(ExclusiveContext* cx, JSObject* objArg, HandleId id)
|
|||
if (shape)
|
||||
return obj->as<NativeObject>().shadowingShapeChange(cx, *shape);
|
||||
|
||||
obj = obj->getProto();
|
||||
obj = obj->staticPrototype();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1105,7 +1105,7 @@ PurgeScopeChainHelper(ExclusiveContext* cx, HandleObject objArg, HandleId id)
|
|||
if (JSID_IS_INT(id))
|
||||
return true;
|
||||
|
||||
if (!PurgeProtoChain(cx, obj->getProto(), id))
|
||||
if (!PurgeProtoChain(cx, obj->staticPrototype(), id))
|
||||
return false;
|
||||
|
||||
/*
|
||||
|
@ -1646,7 +1646,7 @@ js::NativeHasProperty(JSContext* cx, HandleNativeObject obj, HandleId id, bool*
|
|||
// What they all have in common is we do not want to keep walking
|
||||
// the prototype chain, and always claim that the property
|
||||
// doesn't exist.
|
||||
RootedObject proto(cx, done ? nullptr : pobj->getProto());
|
||||
RootedObject proto(cx, done ? nullptr : pobj->staticPrototype());
|
||||
|
||||
// Step 8.
|
||||
if (!proto) {
|
||||
|
@ -2018,7 +2018,7 @@ NativeGetPropertyInline(JSContext* cx,
|
|||
// being resolved.
|
||||
// What they all have in common is we do not want to keep walking
|
||||
// the prototype chain.
|
||||
RootedObject proto(cx, done ? nullptr : pobj->getProto());
|
||||
RootedObject proto(cx, done ? nullptr : pobj->staticPrototype());
|
||||
|
||||
// Step 4.c. The spec algorithm simply returns undefined if proto is
|
||||
// null, but see the comment on GetNonexistentProperty.
|
||||
|
@ -2228,9 +2228,10 @@ js::SetPropertyOnProto(JSContext* cx, HandleObject obj, HandleId id, HandleValue
|
|||
{
|
||||
MOZ_ASSERT(!obj->is<ProxyObject>());
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (proto)
|
||||
return SetProperty(cx, proto, id, v, receiver, result);
|
||||
|
||||
return SetPropertyByDefining(cx, id, v, receiver, result);
|
||||
}
|
||||
|
||||
|
@ -2404,7 +2405,7 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Handle
|
|||
// being resolved.
|
||||
// What they all have in common is we do not want to keep walking
|
||||
// the prototype chain.
|
||||
RootedObject proto(cx, done ? nullptr : pobj->getProto());
|
||||
RootedObject proto(cx, done ? nullptr : pobj->staticPrototype());
|
||||
if (!proto) {
|
||||
// Step 4.d.i (and step 5).
|
||||
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
|
||||
* will change the prototype for all other objects with the same type.
|
||||
*/
|
||||
if (getProto() != nullptr)
|
||||
if (staticPrototype() != nullptr)
|
||||
return false;
|
||||
return isSingleton();
|
||||
}
|
||||
|
@ -327,7 +327,7 @@ JSObject::makeLazyGroup(JSContext* cx, HandleObject obj)
|
|||
if (obj->is<ArrayObject>() && obj->as<ArrayObject>().length() > INT32_MAX)
|
||||
initialFlags |= OBJECT_FLAG_LENGTH_OVERFLOW;
|
||||
|
||||
Rooted<TaggedProto> proto(cx, obj->getTaggedProto());
|
||||
Rooted<TaggedProto> proto(cx, obj->taggedProto());
|
||||
ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, obj->getClass(), proto,
|
||||
initialFlags);
|
||||
if (!group)
|
||||
|
@ -501,7 +501,7 @@ ObjectGroup::defaultNewGroup(ExclusiveContext* cx, const Class* clasp,
|
|||
}
|
||||
|
||||
ObjectGroupFlags initialFlags = 0;
|
||||
if (proto.isLazy() || (proto.isObject() && proto.toObject()->isNewGroupUnknown()))
|
||||
if (proto.isDynamic() || (proto.isObject() && proto.toObject()->isNewGroupUnknown()))
|
||||
initialFlags = OBJECT_FLAG_DYNAMIC_MASK;
|
||||
|
||||
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
|
||||
// just created will be collected by the GC.
|
||||
if (obj->slotSpan() != nproperties) {
|
||||
ObjectGroup* group = defaultNewGroup(cx, obj->getClass(), obj->getTaggedProto());
|
||||
ObjectGroup* group = defaultNewGroup(cx, obj->getClass(), obj->taggedProto());
|
||||
if (!group)
|
||||
return nullptr;
|
||||
obj->setGroup(group);
|
||||
|
|
|
@ -99,6 +99,10 @@ class ObjectGroup : public gc::TenuredCell
|
|||
clasp_ = clasp;
|
||||
}
|
||||
|
||||
bool hasDynamicPrototype() const {
|
||||
return proto_.isDynamic();
|
||||
}
|
||||
|
||||
const HeapPtr<TaggedProto>& proto() const {
|
||||
return proto_;
|
||||
}
|
||||
|
|
|
@ -181,14 +181,7 @@ bool
|
|||
js::ForOfPIC::Chain::isOptimizableArray(JSObject* obj)
|
||||
{
|
||||
MOZ_ASSERT(obj->is<ArrayObject>());
|
||||
|
||||
// Ensure object's prototype is the actual Array.prototype
|
||||
if (!obj->getTaggedProto().isObject())
|
||||
return false;
|
||||
if (obj->getTaggedProto().toObject() != arrayProto_)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
return obj->staticPrototype() == arrayProto_;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -849,7 +849,7 @@ RegExpCompartment::createMatchResultTemplateObject(JSContext* cx)
|
|||
return matchResultTemplateObject_; // = nullptr
|
||||
|
||||
// Create a new group for the template.
|
||||
Rooted<TaggedProto> proto(cx, templateObject->getTaggedProto());
|
||||
Rooted<TaggedProto> proto(cx, templateObject->taggedProto());
|
||||
ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, templateObject->getClass(), proto);
|
||||
if (!group)
|
||||
return matchResultTemplateObject_; // = nullptr
|
||||
|
|
|
@ -897,7 +897,7 @@ class NestedScopeObject : public ScopeObject
|
|||
public:
|
||||
// Return the static scope corresponding to this scope chain object.
|
||||
inline NestedStaticScope* staticScope() {
|
||||
return &getProto()->as<NestedStaticScope>();
|
||||
return &staticPrototype()->as<NestedStaticScope>();
|
||||
}
|
||||
|
||||
void initEnclosingScope(JSObject* obj) {
|
||||
|
@ -927,7 +927,7 @@ class DynamicWithObject : public NestedScopeObject
|
|||
WithKind kind = SyntacticWith);
|
||||
|
||||
StaticWithScope& staticWith() const {
|
||||
return getProto()->as<StaticWithScope>();
|
||||
return staticPrototype()->as<StaticWithScope>();
|
||||
}
|
||||
|
||||
/* Return the 'o' in 'with (o)'. */
|
||||
|
@ -1007,7 +1007,7 @@ class ClonedBlockObject : public NestedScopeObject
|
|||
public:
|
||||
/* The static block from which this block was cloned. */
|
||||
StaticBlockScope& staticBlock() const {
|
||||
return getProto()->as<StaticBlockScope>();
|
||||
return staticPrototype()->as<StaticBlockScope>();
|
||||
}
|
||||
|
||||
/* Assuming 'put' has been called, return the value of the ith let var. */
|
||||
|
@ -1387,7 +1387,7 @@ template<>
|
|||
inline bool
|
||||
JSObject::is<js::StaticBlockScope>() const
|
||||
{
|
||||
return hasClass(&js::ClonedBlockObject::class_) && !getProto();
|
||||
return hasClass(&js::ClonedBlockObject::class_) && !staticPrototype();
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1411,7 +1411,7 @@ template<>
|
|||
inline bool
|
||||
JSObject::is<js::ClonedBlockObject>() const
|
||||
{
|
||||
return hasClass(&js::ClonedBlockObject::class_) && !!getProto();
|
||||
return hasClass(&js::ClonedBlockObject::class_) && staticPrototype();
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
|
@ -479,7 +479,7 @@ intrinsic_FinishBoundFunctionInit(JSContext* cx, unsigned argc, Value* vp)
|
|||
if (!GetPrototype(cx, targetObj, &proto))
|
||||
return false;
|
||||
|
||||
if (bound->getProto() != proto) {
|
||||
if (bound->staticPrototype() != proto) {
|
||||
if (!SetPrototype(cx, bound, proto))
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -134,7 +134,7 @@ EmptyShape::ensureInitialCustomShape(ExclusiveContext* cx, Handle<ObjectSubclass
|
|||
|
||||
// Cache the initial shape for non-prototype objects, however, so that
|
||||
// future instances will begin life with that shape.
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
EmptyShape::insertInitialShape(cx, shape, proto);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1194,7 +1194,7 @@ JSObject::setFlags(ExclusiveContext* cx, BaseShape::Flag flags, GenerateShape ge
|
|||
if (!existingShape)
|
||||
return false;
|
||||
|
||||
Shape* newShape = Shape::setObjectFlags(cx, flags, self->getTaggedProto(), existingShape);
|
||||
Shape* newShape = Shape::setObjectFlags(cx, flags, self->taggedProto(), existingShape);
|
||||
if (!newShape)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ js::TaggedProto::hashCode() const
|
|||
uint64_t
|
||||
js::TaggedProto::uniqueId() const
|
||||
{
|
||||
if (isLazy())
|
||||
if (isDynamic())
|
||||
return uint64_t(1);
|
||||
JSObject* obj = toObjectOrNull();
|
||||
if (!obj)
|
||||
|
|
|
@ -24,7 +24,7 @@ class TaggedProto
|
|||
|
||||
uintptr_t toWord() const { return uintptr_t(proto); }
|
||||
|
||||
bool isLazy() const {
|
||||
bool isDynamic() const {
|
||||
return proto == LazyProto;
|
||||
}
|
||||
bool isObject() const {
|
||||
|
@ -83,7 +83,7 @@ class TaggedProtoOperations
|
|||
|
||||
public:
|
||||
uintptr_t toWord() const { return value().toWord(); }
|
||||
inline bool isLazy() const { return value().isLazy(); }
|
||||
inline bool isDynamic() const { return value().isDynamic(); }
|
||||
inline bool isObject() const { return value().isObject(); }
|
||||
inline JSObject* toObject() const { return value().toObject(); }
|
||||
inline JSObject* toObjectOrNull() const { return value().toObjectOrNull(); }
|
||||
|
|
|
@ -1215,7 +1215,7 @@ TypeSet::ObjectKey::clasp()
|
|||
TaggedProto
|
||||
TypeSet::ObjectKey::proto()
|
||||
{
|
||||
return isGroup() ? group()->proto() : singleton()->getTaggedProto();
|
||||
return isGroup() ? group()->proto() : singleton()->taggedProto();
|
||||
}
|
||||
|
||||
TypeNewScript*
|
||||
|
@ -2420,7 +2420,7 @@ TemporaryTypeSet::getCommonPrototype(CompilerConstraintList* constraints, JSObje
|
|||
|
||||
TaggedProto nproto = key->proto();
|
||||
if (isFirst) {
|
||||
if (nproto.isLazy())
|
||||
if (nproto.isDynamic())
|
||||
return false;
|
||||
*proto = nproto.toObjectOrNull();
|
||||
isFirst = false;
|
||||
|
@ -3007,8 +3007,11 @@ ObjectGroup::print()
|
|||
TaggedProto tagged(proto());
|
||||
fprintf(stderr, "%s : %s",
|
||||
TypeSet::ObjectGroupString(this),
|
||||
tagged.isObject() ? TypeSet::TypeString(TypeSet::ObjectType(tagged.toObject()))
|
||||
: (tagged.isLazy() ? "(lazy)" : "(null)"));
|
||||
tagged.isObject()
|
||||
? TypeSet::TypeString(TypeSet::ObjectType(tagged.toObject()))
|
||||
: tagged.isDynamic()
|
||||
? "(dynamic)"
|
||||
: "(null)");
|
||||
|
||||
if (unknownProperties()) {
|
||||
fprintf(stderr, " unknown");
|
||||
|
@ -3119,7 +3122,7 @@ js::AddClearDefiniteGetterSetterForPrototypeChain(JSContext* cx, ObjectGroup* gr
|
|||
return false;
|
||||
if (!protoTypes->addConstraint(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteGetterSetter>(group)))
|
||||
return false;
|
||||
proto = proto->getProto();
|
||||
proto = proto->staticPrototype();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -3319,7 +3322,7 @@ JSFunction::setTypeForScriptedFunction(ExclusiveContext* cx, HandleFunction fun,
|
|||
if (!setSingleton(cx, fun))
|
||||
return false;
|
||||
} else {
|
||||
RootedObject funProto(cx, fun->getProto());
|
||||
RootedObject funProto(cx, fun->staticPrototype());
|
||||
Rooted<TaggedProto> taggedProto(cx, TaggedProto(funProto));
|
||||
ObjectGroup* group = ObjectGroupCompartment::makeGroup(cx, &JSFunction::class_,
|
||||
taggedProto);
|
||||
|
@ -3612,9 +3615,7 @@ ChangeObjectFixedSlotCount(JSContext* cx, PlainObject* obj, gc::AllocKind allocK
|
|||
{
|
||||
MOZ_ASSERT(OnlyHasDataProperties(obj->lastProperty()));
|
||||
|
||||
Shape* newShape = ReshapeForAllocKind(cx, obj->lastProperty(),
|
||||
obj->getTaggedProto(),
|
||||
allocKind);
|
||||
Shape* newShape = ReshapeForAllocKind(cx, obj->lastProperty(), obj->taggedProto(), allocKind);
|
||||
if (!newShape)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -727,7 +727,7 @@ UnboxedPlainObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
|
|||
return true;
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
objp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
|
@ -778,7 +778,7 @@ UnboxedPlainObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id
|
|||
return true;
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
*foundp = false;
|
||||
return true;
|
||||
|
@ -805,7 +805,7 @@ UnboxedPlainObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue
|
|||
}
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
vp.setUndefined();
|
||||
return true;
|
||||
|
@ -1428,7 +1428,7 @@ UnboxedArrayObject::obj_lookupProperty(JSContext* cx, HandleObject obj,
|
|||
return true;
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
objp.set(nullptr);
|
||||
propp.set(nullptr);
|
||||
|
@ -1479,7 +1479,7 @@ UnboxedArrayObject::obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id
|
|||
return true;
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
*foundp = false;
|
||||
return true;
|
||||
|
@ -1500,7 +1500,7 @@ UnboxedArrayObject::obj_getProperty(JSContext* cx, HandleObject obj, HandleValue
|
|||
return true;
|
||||
}
|
||||
|
||||
RootedObject proto(cx, obj->getProto());
|
||||
RootedObject proto(cx, obj->staticPrototype());
|
||||
if (!proto) {
|
||||
vp.setUndefined();
|
||||
return true;
|
||||
|
|
Загрузка…
Ссылка в новой задаче