void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor) { Structure* thisObject = jsCast<Structure*>(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); JSCell::visitChildren(thisObject, visitor); if (thisObject->m_globalObject) visitor.append(&thisObject->m_globalObject); if (!thisObject->isObject()) thisObject->m_cachedPrototypeChain.clear(); else { if (thisObject->m_prototype) visitor.append(&thisObject->m_prototype); if (thisObject->m_cachedPrototypeChain) visitor.append(&thisObject->m_cachedPrototypeChain); } if (thisObject->m_previous) visitor.append(&thisObject->m_previous); if (thisObject->m_specificValueInPrevious) visitor.append(&thisObject->m_specificValueInPrevious); if (thisObject->m_enumerationCache) visitor.append(&thisObject->m_enumerationCache); if (thisObject->m_propertyTable) { PropertyTable::iterator end = thisObject->m_propertyTable->end(); for (PropertyTable::iterator ptr = thisObject->m_propertyTable->begin(); ptr != end; ++ptr) { if (ptr->specificValue) visitor.append(&ptr->specificValue); } } }
std::unique_ptr<PolyProtoAccessChain> PolyProtoAccessChain::create(JSGlobalObject* globalObject, JSCell* base, JSObject* target, bool& usesPolyProto) { JSCell* current = base; VM& vm = *base->vm(); bool found = false; usesPolyProto = false; std::unique_ptr<PolyProtoAccessChain> result(new PolyProtoAccessChain()); for (unsigned iterationNumber = 0; true; ++iterationNumber) { Structure* structure = current->structure(vm); if (!structure->propertyAccessesAreCacheable()) return nullptr; if (structure->isProxy()) return nullptr; if (structure->isDictionary()) { ASSERT(structure->isObject()); if (structure->hasBeenFlattenedBefore()) return nullptr; structure->flattenDictionaryStructure(vm, asObject(current)); } // To save memory, we don't include the base in the chain. We let // AccessCase provide the base to us as needed. if (iterationNumber) result->m_chain.append(structure); else RELEASE_ASSERT(current == base); if (current == target) { found = true; break; } // We only have poly proto if we need to access our prototype via // the poly proto protocol. If the slot base is the only poly proto // thing in the chain, and we have a cache hit on it, then we're not // poly proto. usesPolyProto |= structure->hasPolyProto(); JSValue prototype = structure->prototypeForLookup(globalObject, current); if (prototype.isNull()) break; current = asObject(prototype); } if (!found && !!target) return nullptr; return result; }
void Structure::visitChildren(JSCell* cell, SlotVisitor& visitor) { Structure* thisObject = jsCast<Structure*>(cell); ASSERT_GC_OBJECT_INHERITS(thisObject, &s_info); ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren()); JSCell::visitChildren(thisObject, visitor); visitor.append(&thisObject->m_globalObject); if (!thisObject->isObject()) thisObject->m_cachedPrototypeChain.clear(); else { visitor.append(&thisObject->m_prototype); visitor.append(&thisObject->m_cachedPrototypeChain); } visitor.append(&thisObject->m_previousOrRareData); visitor.append(&thisObject->m_specificValueInPrevious); if (thisObject->m_isPinnedPropertyTable) { ASSERT(thisObject->m_propertyTableUnsafe); visitor.append(&thisObject->m_propertyTableUnsafe); } else if (thisObject->m_propertyTableUnsafe) thisObject->m_propertyTableUnsafe.clear(); }