LLIntPrototypeLoadAdaptiveStructureWatchpoint::LLIntPrototypeLoadAdaptiveStructureWatchpoint(const ObjectPropertyCondition& key, Instruction* getByIdInstruction) : m_key(key) , m_getByIdInstruction(getByIdInstruction) { RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint()); RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint()); }
ObjectToStringAdaptiveStructureWatchpoint::ObjectToStringAdaptiveStructureWatchpoint(const ObjectPropertyCondition& key, StructureRareData* structureRareData) : m_key(key) , m_structureRareData(structureRareData) { RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint()); RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint()); }
void StructureRareData::setObjectToStringValue(ExecState* exec, VM& vm, Structure* ownStructure, JSString* value, PropertySlot toStringTagSymbolSlot) { if (m_giveUpOnObjectToStringValueCache) return; ObjectPropertyConditionSet conditionSet; if (toStringTagSymbolSlot.isValue()) { // We don't handle the own property case of Symbol.toStringTag because we would never know if a new // object transitioning to the same structure had the same value stored in Symbol.toStringTag. // Additionally, this is a super unlikely case anyway. if (!toStringTagSymbolSlot.isCacheable() || toStringTagSymbolSlot.slotBase()->structure(vm) == ownStructure) return; // This will not create a condition for the current structure but that is good because we know the Symbol.toStringTag // is not on the ownStructure so we will transisition if one is added and this cache will no longer be used. conditionSet = generateConditionsForPrototypePropertyHit(vm, this, exec, ownStructure, toStringTagSymbolSlot.slotBase(), vm.propertyNames->toStringTagSymbol.impl()); ASSERT(!conditionSet.isValid() || conditionSet.hasOneSlotBaseCondition()); } else if (toStringTagSymbolSlot.isUnset()) conditionSet = generateConditionsForPropertyMiss(vm, this, exec, ownStructure, vm.propertyNames->toStringTagSymbol.impl()); else return; if (!conditionSet.isValid()) { m_giveUpOnObjectToStringValueCache = true; return; } ObjectPropertyCondition equivCondition; for (const ObjectPropertyCondition& condition : conditionSet) { if (condition.condition().kind() == PropertyCondition::Presence) { ASSERT(isValidOffset(condition.offset())); condition.object()->structure(vm)->startWatchingPropertyForReplacements(vm, condition.offset()); equivCondition = condition.attemptToMakeEquivalenceWithoutBarrier(); // The equivalence condition won't be watchable if we have already seen a replacement. if (!equivCondition.isWatchable()) { m_giveUpOnObjectToStringValueCache = true; return; } } else if (!condition.isWatchable()) { m_giveUpOnObjectToStringValueCache = true; return; } } ASSERT(conditionSet.structuresEnsureValidity()); for (ObjectPropertyCondition condition : conditionSet) { if (condition.condition().kind() == PropertyCondition::Presence) { m_objectToStringAdaptiveInferredValueWatchpoint = std::make_unique<ObjectToStringAdaptiveInferredPropertyValueWatchpoint>(equivCondition, this); m_objectToStringAdaptiveInferredValueWatchpoint->install(); } else m_objectToStringAdaptiveWatchpointSet.add(condition, this)->install(); } m_objectToStringValue.set(vm, this, value); }
AdaptiveStructureWatchpoint::AdaptiveStructureWatchpoint( const ObjectPropertyCondition& key, CodeBlock* codeBlock) : m_key(key) , m_codeBlock(codeBlock) { RELEASE_ASSERT(key.watchingRequiresStructureTransitionWatchpoint()); RELEASE_ASSERT(!key.watchingRequiresReplacementWatchpoint()); }
AdaptiveInferredPropertyValueWatchpoint::AdaptiveInferredPropertyValueWatchpoint( const ObjectPropertyCondition& key, CodeBlock* codeBlock) : m_key(key) , m_codeBlock(codeBlock) { RELEASE_ASSERT(key.kind() == PropertyCondition::Equivalence); }
void AdaptiveStructureWatchpointAdaptor::add( CodeBlock* codeBlock, const ObjectPropertyCondition& key, CommonData& common) { switch (key.kind()) { case PropertyCondition::Equivalence: common.adaptiveInferredPropertyValueWatchpoints.add(key, codeBlock)->install(); break; default: common.adaptiveStructureWatchpoints.add(key, codeBlock)->install(); break; } }
void ObjectToStringAdaptiveStructureWatchpoint::fireInternal(const FireDetail& detail) { if (m_key.isWatchable(PropertyCondition::EnsureWatchability)) { install(); return; } StringPrintStream out; out.print("ObjectToStringValue Adaptation of ", m_key, " failed: ", detail); StringFireDetail stringDetail(out.toCString().data()); m_structureRareData->clearObjectToStringValue(); }
void ObjectToStringAdaptiveStructureWatchpoint::install() { RELEASE_ASSERT(m_key.isWatchable()); m_key.object()->structure()->addTransitionWatchpoint(this); }