bool GetPropIRGenerator::tryAttachDenseElementHole(HandleObject obj, ObjOperandId objId, ValOperandId indexId) { MOZ_ASSERT(idVal_.isInt32()); if (idVal_.toInt32() < 0) return false; if (!obj->isNative() || !CanAttachDenseElementHole(obj)) return false; // Guard on the shape, to prevent non-dense elements from appearing. writer.guardShape(objId, obj->as<NativeObject>().lastProperty()); if (obj->hasUncacheableProto()) { // If the shape does not imply the proto, emit an explicit proto guard. writer.guardProto(objId, obj->staticPrototype()); } JSObject* pobj = obj->staticPrototype(); while (pobj) { ObjOperandId protoId = writer.loadObject(pobj); // Non-singletons with uncacheable protos can change their proto // without a shape change, so also guard on the group (which determines // the proto) in this case. if (pobj->hasUncacheableProto() && !pobj->isSingleton()) writer.guardGroup(protoId, pobj->group()); // Make sure the shape matches, to avoid non-dense elements or anything // else that is being checked by CanAttachDenseElementHole. writer.guardShape(protoId, pobj->as<NativeObject>().lastProperty()); // Also make sure there are no dense elements. writer.guardNoDenseElements(protoId); pobj = pobj->staticPrototype(); } Int32OperandId int32IndexId = writer.guardIsInt32(indexId); writer.loadDenseElementHoleResult(objId, int32IndexId); writer.typeMonitorResult(); return true; }
bool GetPropIRGenerator::tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId, HandleId id) { MOZ_ASSERT(IsCacheableDOMProxy(obj)); RootedObject checkObj(cx_, obj->staticPrototype()); RootedNativeObject holder(cx_); RootedShape shape(cx_); NativeGetPropCacheability canCache = CanAttachNativeGetProp(cx_, checkObj, id, &holder, &shape, pc_, engine_, isTemporarilyUnoptimizable_); if (canCache == CanAttachNone) return false; maybeEmitIdGuard(id); writer.guardShape(objId, obj->maybeShape()); // Guard that our expando object hasn't started shadowing this property. CheckDOMProxyExpandoDoesNotShadow(writer, obj, id, objId); if (holder) { // Found the property on the prototype chain. Treat it like a native // getprop. GeneratePrototypeGuards(writer, obj, holder, objId); // Guard on the holder of the property. ObjOperandId holderId = writer.loadObject(holder); writer.guardShape(holderId, holder->lastProperty()); if (canCache == CanAttachReadSlot) { EmitLoadSlotResult(writer, holderId, holder, shape); writer.typeMonitorResult(); } else { // EmitCallGetterResultNoGuards expects |obj| to be the object the // property is on to do some checks. Since we actually looked at // checkObj, and no extra guards will be generated, we can just // pass that instead. MOZ_ASSERT(canCache == CanAttachCallGetter); EmitCallGetterResultNoGuards(writer, checkObj, holder, shape, objId); } } else { // Property was not found on the prototype chain. Deoptimize down to // proxy get call. writer.callProxyGetResult(objId, id); writer.typeMonitorResult(); } return true; }
static inline bool Enumerate(JSContext* cx, HandleObject pobj, jsid id, bool enumerable, unsigned flags, Maybe<IdSet>& ht, AutoIdVector* props) { if (CheckForDuplicates) { if (!ht) { ht.emplace(cx); // Most of the time there are only a handful of entries. if (!ht->init(5)) return false; } // If we've already seen this, we definitely won't add it. IdSet::AddPtr p = ht->lookupForAdd(id); if (MOZ_UNLIKELY(!!p)) return true; // 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->staticPrototype() || pobj->getClass()->getNewEnumerate()) { if (!ht->add(p, id)) return false; } } if (!enumerable && !(flags & JSITER_HIDDEN)) return true; // Symbol-keyed properties and nonenumerable properties are skipped unless // the caller specifically asks for them. A caller can also filter out // non-symbols by asking for JSITER_SYMBOLSONLY. if (JSID_IS_SYMBOL(id) ? !(flags & JSITER_SYMBOLS) : (flags & JSITER_SYMBOLSONLY)) return true; return props->append(id); }