Ignore:
Timestamp:
Sep 15, 2012, 7:36:22 PM (13 years ago)
Author:
[email protected]
Message:

Structure check hoisting fails to consider the possibility of conflicting checks on the source of the first assignment to the hoisted variable
https://bugs.webkit.org/show_bug.cgi?id=96872

Reviewed by Oliver Hunt.

This does a few related things:

  • It turns off the use of ForceOSRExit for sure-to-fail CheckStructures, because I noticed that this would sometimes happen for a ForwardCheckStructure. The problem is that ForceOSRExit exits backwards, not forwards. Since the code that led to those ForceOSRExit's being inserted was written out of paranoia rather than need, I removed it. Specifically, I removed the m_isValid = false code for CheckStructure/StructureTransitionWatchpoint in AbstractState.


  • If a structure check causes a structure set to go empty, we don't want a PutStructure to revive the set. It should instead be smart enough to realize that an empty set implies that the code can't execute. This was the only "bug" that the use of m_isValid = false was preventing.


  • Finally, the main change: structure check hoisting looks at the source of the SetLocals on structure-check-hoistable variables and ensures that the source is not checked with a conflicting structure. This is O(n2) but it does not show up at all in performance tests.


The first two parts of this change were auxiliary bugs that were revealed by
the structure check hoister doing bad things.

  • dfg/DFGAbstractState.cpp:

(JSC::DFG::AbstractState::initialize):
(JSC::DFG::AbstractState::execute):

  • dfg/DFGStructureCheckHoistingPhase.cpp:

(JSC::DFG::StructureCheckHoistingPhase::run):

File:
1 edited

Legend:

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

    r128400 r128699  
    6868                    continue;
    6969                switch (node.op()) {
    70                 case CheckStructure: {
     70                case CheckStructure:
     71                case StructureTransitionWatchpoint: {
    7172                    Node& child = m_graph[node.child1()];
    7273                    if (child.op() != GetLocal)
     
    9293                case PutByOffset:
    9394                case PutStructure:
    94                 case StructureTransitionWatchpoint:
    9595                case AllocatePropertyStorage:
    9696                case ReallocatePropertyStorage:
     
    105105                    // Don't count these uses.
    106106                    break;
     107                   
     108                case SetLocal: {
     109                    // Find all uses of the source of the SetLocal. If any of them are a
     110                    // kind of CheckStructure, then we should notice them to ensure that
     111                    // we're not hoisting a check that would contravene checks that are
     112                    // already being performed.
     113                    VariableAccessData* variable = node.variableAccessData();
     114                    if (variable->isCaptured() || variable->structureCheckHoistingFailed())
     115                        break;
     116                    if (!isCellSpeculation(variable->prediction()))
     117                        break;
     118                    NodeIndex source = node.child1().index();
     119                    for (unsigned subIndexInBlock = 0; subIndexInBlock < block->size(); ++subIndexInBlock) {
     120                        NodeIndex subNodeIndex = block->at(subIndexInBlock);
     121                        Node& subNode = m_graph[subNodeIndex];
     122                        if (!subNode.shouldGenerate())
     123                            continue;
     124                        switch (subNode.op()) {
     125                        case CheckStructure:
     126                        case StructureTransitionWatchpoint: {
     127                            if (subNode.child1().index() != source)
     128                                break;
     129                           
     130                            noticeStructureCheck(variable, subNode.structureSet());
     131                            break;
     132                        }
     133                        default:
     134                            break;
     135                        }
     136                    }
     137                   
     138                    m_graph.vote(node, VoteOther);
     139                    break;
     140                }
    107141                   
    108142                default:
Note: See TracChangeset for help on using the changeset viewer.