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:
Jeff Walden 2016-03-18 16:45:31 -07:00
Родитель aa3a4bea25
Коммит e69489250b
40 изменённых файлов: 247 добавлений и 233 удалений

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

@ -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,9 +111,11 @@ 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))
if (pobj->is<ProxyObject>() || pobj->staticPrototype() || pobj->getOpsEnumerate()) {
if (!ht->add(p, id))
return false;
}
}
// Symbol-keyed properties and nonenumerable properties are skipped unless
// the caller specifically asks for them. A caller can also filter out
@ -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;