JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o) { ASSERT(!o->structure()->enumerationCache() || o->structure()->enumerationCache()->cachedStructure() != o->structure() || o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec)); PropertyNameArray propertyNames(exec); o->methodTable()->getPropertyNames(o, exec, propertyNames, ExcludeDontEnumProperties); size_t numCacheableSlots = 0; if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasGetterSetterProperties() && !o->structure()->isUncacheableDictionary() && !o->structure()->typeInfo().overridesGetPropertyNames()) numCacheableSlots = o->structure()->totalStorageSize(); JSPropertyNameIterator* jsPropertyNameIterator = new (NotNull, allocateCell<JSPropertyNameIterator>(*exec->heap())) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots); jsPropertyNameIterator->finishCreation(exec, propertyNames.data(), o); if (o->structure()->isDictionary()) return jsPropertyNameIterator; if (o->structure()->typeInfo().overridesGetPropertyNames()) return jsPropertyNameIterator; size_t count = normalizePrototypeChain(exec, o); StructureChain* structureChain = o->structure()->prototypeChain(exec); WriteBarrier<Structure>* structure = structureChain->head(); for (size_t i = 0; i < count; ++i) { if (structure[i]->typeInfo().overridesGetPropertyNames()) return jsPropertyNameIterator; } jsPropertyNameIterator->setCachedPrototypeChain(exec->globalData(), structureChain); jsPropertyNameIterator->setCachedStructure(exec->globalData(), o->structure()); o->structure()->setEnumerationCache(exec->globalData(), jsPropertyNameIterator); return jsPropertyNameIterator; }
JSPropertyNameIterator* JSPropertyNameIterator::create(ExecState* exec, JSObject* o) { ASSERT(!o->structure()->enumerationCache() || o->structure()->enumerationCache()->cachedStructure() != o->structure() || o->structure()->enumerationCache()->cachedPrototypeChain() != o->structure()->prototypeChain(exec)); PropertyNameArray propertyNames(exec); o->getPropertyNames(exec, propertyNames); size_t numCacheableSlots = 0; if (!o->structure()->hasNonEnumerableProperties() && !o->structure()->hasAnonymousSlots() && !o->structure()->isUncacheableDictionary() && !o->structure()->typeInfo().overridesGetPropertyNames()) numCacheableSlots = o->structure()->propertyStorageSize(); JSPropertyNameIterator* jsPropertyNameIterator = new (exec) JSPropertyNameIterator(exec, propertyNames.data(), numCacheableSlots); if (o->structure()->isDictionary()) return jsPropertyNameIterator; if (o->structure()->typeInfo().overridesGetPropertyNames()) return jsPropertyNameIterator; size_t count = normalizePrototypeChain(exec, o); StructureChain* structureChain = o->structure()->prototypeChain(exec); RefPtr<Structure>* structure = structureChain->head(); for (size_t i = 0; i < count; ++i) { if (structure[i]->typeInfo().overridesGetPropertyNames()) return jsPropertyNameIterator; } jsPropertyNameIterator->setCachedPrototypeChain(structureChain); jsPropertyNameIterator->setCachedStructure(o->structure()); o->structure()->setEnumerationCache(jsPropertyNameIterator); return jsPropertyNameIterator; }
void StructureChain::visitChildren(JSCell* cell, SlotVisitor& visitor) { StructureChain* thisObject = jsCast<StructureChain*>(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, info()); ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); size_t i = 0; while (thisObject->m_vector[i]) visitor.append(&thisObject->m_vector[i++]); }
void Structure::getEnumerablePropertyNames(ExecState* exec, PropertyNameArray& propertyNames, JSObject* baseObject) { bool shouldCache = propertyNames.shouldCache() && !(propertyNames.size() || isDictionary()); if (shouldCache && m_cachedPropertyNameArrayData) { if (m_cachedPropertyNameArrayData->cachedPrototypeChain() == prototypeChain(exec)) { propertyNames.setData(m_cachedPropertyNameArrayData); return; } clearEnumerationCache(); } baseObject->getOwnPropertyNames(exec, propertyNames); if (m_prototype.isObject()) { propertyNames.setShouldCache(false); // No need for our prototypes to waste memory on caching, since they're not being enumerated directly. JSObject* prototype = asObject(m_prototype); while(1) { if (!prototype->structure()->typeInfo().hasDefaultGetPropertyNames()) { prototype->getPropertyNames(exec, propertyNames); break; } prototype->getOwnPropertyNames(exec, propertyNames); JSValue nextProto = prototype->prototype(); if (!nextProto.isObject()) break; prototype = asObject(nextProto); } } if (shouldCache) { StructureChain* protoChain = prototypeChain(exec); m_cachedPropertyNameArrayData = propertyNames.data(); if (!protoChain->isCacheable()) return; m_cachedPropertyNameArrayData->setCachedPrototypeChain(protoChain); m_cachedPropertyNameArrayData->setCachedStructure(this); } }