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);
}
示例#6
0
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);
}