Ignore:
Timestamp:
Jan 3, 2020, 1:20:48 AM (5 years ago)
Author:
[email protected]
Message:

AI rule for PutById can only observe transitions when it watches the condition
https://bugs.webkit.org/show_bug.cgi?id=205697
<rdar://problem/56814254>

Reviewed by Yusuke Suzuki.

JSTests:

  • stress/only-transition-structures-for-put-by-id-in-AI-if-watchable.js: Added.

Source/JavaScriptCore:

There was a bug in AI where we were capturing a PutByIdStatus and
emitting a structure transition in AI state based on the variants inside this
PutByIdStatus. This, in principal, is a valid static analysis to perform.
However, we can only do this if we ensure that the snapshot we have in the
PutByIdStatus holds at runtime. We can do this by watching the property conditions
for the various variants. AI forgot to watch these conditions. This patch fixes that.
In practice, this also means we need to be slightly more strict about stating to
AI when we transition since some object property conditions aren't watchable, and need
to be verified at runtime via structure checks. This is ok in practice, since
we'll emit the code to do that inside constant folding (constant folding was
already doing this), which will continue to report the precise transition in
the abstract state.

  • dfg/DFGAbstractInterpreter.h:
  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r253896 r253991  
    607607                AbstractValue valueValue = m_state.forNode(node->child2());
    608608
    609                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
    610                 alreadyHandled = true; // Don't allow the default constant folder to do things to this.
    611 
    612609                if (!baseValue.m_structure.isFinite())
    613610                    break;
    614                
     611
    615612                PutByIdStatus status = PutByIdStatus::computeFor(
    616613                    m_graph.globalObjectFor(origin.semantic),
     
    618615                    m_graph.identifiers()[identifierNumber],
    619616                    node->op() == PutByIdDirect);
    620                
     617
    621618                if (!status.isSimple())
    622619                    break;
     
    630627
    631628                bool allGood = true;
     629                RegisteredStructureSet newSet;
     630                TransitionVector transitions;
    632631                for (const PutByIdVariant& variant : status.variants()) {
    633                     if (!allGood)
    634                         break;
    635632                    for (const ObjectPropertyCondition& condition : variant.conditionSet()) {
    636633                        if (m_graph.watchCondition(condition))
     
    649646                                indexInBlock, node->origin, condition.object(), KnownCellUse));
    650647                    }
     648
     649                    if (!allGood)
     650                        break;
     651
     652                    if (variant.kind() == PutByIdVariant::Transition) {
     653                        RegisteredStructure newStructure = m_graph.registerStructure(variant.newStructure());
     654                        transitions.append(
     655                            Transition(
     656                                m_graph.registerStructure(variant.oldStructureForTransition()), newStructure));
     657                        newSet.add(newStructure);
     658                    } else {
     659                        ASSERT(variant.kind() == PutByIdVariant::Replace);
     660                        newSet.merge(*m_graph.addStructureSet(variant.oldStructure()));
     661                    }
    651662                }
    652663
    653664                if (!allGood)
    654665                    break;
     666
     667                // Push CFA over this node after we get the state before.
     668                m_interpreter.didFoldClobberWorld();
     669                m_interpreter.observeTransitions(indexInBlock, transitions);
     670                if (m_state.forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
     671                    m_state.setIsValid(false);
     672
     673                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
    655674               
    656675                m_insertionSet.insertNode(
Note: See TracChangeset for help on using the changeset viewer.