ObjectPropertyConditionSet generateConditionsForInstanceOf( VM& vm, JSCell* owner, ExecState* exec, Structure* headStructure, JSObject* prototype, bool shouldHit) { bool didHit = false; if (ObjectPropertyConditionSetInternal::verbose) dataLog("Searching for prototype ", JSValue(prototype), " starting with structure ", RawPointer(headStructure), " with shouldHit = ", shouldHit, "\n"); ObjectPropertyConditionSet result = generateConditions( vm, exec->lexicalGlobalObject(), headStructure, shouldHit ? prototype : nullptr, [&] (Vector<ObjectPropertyCondition>& conditions, JSObject* object) -> bool { if (ObjectPropertyConditionSetInternal::verbose) dataLog("Encountered object: ", RawPointer(object), "\n"); if (object == prototype) { RELEASE_ASSERT(shouldHit); didHit = true; return true; } Structure* structure = object->structure(vm); if (structure->hasPolyProto()) return false; conditions.append( ObjectPropertyCondition::hasPrototype( vm, owner, object, structure->storedPrototypeObject())); return true; }); if (result.isValid()) { if (ObjectPropertyConditionSetInternal::verbose) dataLog("didHit = ", didHit, ", shouldHit = ", shouldHit, "\n"); RELEASE_ASSERT(didHit == shouldHit); } return result; }
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; }