Ignore:
Timestamp:
Mar 8, 2013, 6:51:06 PM (12 years ago)
Author:
[email protected]
Message:

DFG overflow check elimination is too smart for its own good
https://bugs.webkit.org/show_bug.cgi?id=111832

Source/JavaScriptCore:

Reviewed by Oliver Hunt and Gavin Barraclough.

This improves overflow check elimination in three ways:

1) It reduces the amount of time the compiler will spend doing it.

2) It fixes bugs where overflow check elimination was overzealous. Precisely, for a binary operation

over @a and @b where both @a and @b will type check that their inputs (@a->children, @b->children)
are int32's and then perform a possibly-overflowing operation, we must be careful not to assume
that @a's non-int32 parts don't matter if at the point that @a runs we have as yet not proved that
@b->children are int32's and that hence @b might produce a large enough result that doubles would
start chopping low bits. The specific implication of this is that for a binary operation to not
propagate that it cares about non-int32 parts (NodeUsedAsNumber), we must prove that at least one
of the inputs is guaranteed to produce a result within 232 and that there won't be a tower of such
operations large enough to ultimately produce a double greater than 2
52 (roughly). We achieve the
latter by disabling this optimization for very large basic blocks. It's noteworthy that blocks that
large won't even make it into the DFG currently.


3) It makes the overflow check elimination more precise for cases where the inputs to an Add or Sub

are the outputs of a bit-op. For example in (@a + (@b | 0)) | 0, we don't need to propagate
NodeUsedAsNumber to either @a or @b.


This is neutral on V8v7 and a slight speed-up on compile time benchmarks.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • Target.pri:
  • dfg/DFGArrayMode.cpp:

(JSC::DFG::ArrayMode::refine):

  • dfg/DFGBackwardsPropagationPhase.cpp: Added.

(DFG):
(BackwardsPropagationPhase):
(JSC::DFG::BackwardsPropagationPhase::BackwardsPropagationPhase):
(JSC::DFG::BackwardsPropagationPhase::run):
(JSC::DFG::BackwardsPropagationPhase::isNotNegZero):
(JSC::DFG::BackwardsPropagationPhase::isNotZero):
(JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwoForConstant):
(JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwoNonRecursive):
(JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwo):
(JSC::DFG::BackwardsPropagationPhase::mergeDefaultFlags):
(JSC::DFG::BackwardsPropagationPhase::propagate):
(JSC::DFG::performBackwardsPropagation):

  • dfg/DFGBackwardsPropagationPhase.h: Added.

(DFG):

  • dfg/DFGCPSRethreadingPhase.cpp:

(JSC::DFG::CPSRethreadingPhase::run):
(JSC::DFG::CPSRethreadingPhase::clearIsLoadedFrom):
(CPSRethreadingPhase):
(JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
(JSC::DFG::CPSRethreadingPhase::canonicalizeFlushOrPhantomLocalFor):

  • dfg/DFGDriver.cpp:

(JSC::DFG::compile):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::dump):

  • dfg/DFGNodeFlags.cpp:

(JSC::DFG::dumpNodeFlags):
(DFG):

  • dfg/DFGNodeFlags.h:

(DFG):

  • dfg/DFGPredictionPropagationPhase.cpp:

(PredictionPropagationPhase):
(JSC::DFG::PredictionPropagationPhase::propagate):

  • dfg/DFGUnificationPhase.cpp:

(JSC::DFG::UnificationPhase::run):

  • dfg/DFGVariableAccessData.h:

(JSC::DFG::VariableAccessData::VariableAccessData):
(JSC::DFG::VariableAccessData::mergeIsLoadedFrom):
(VariableAccessData):
(JSC::DFG::VariableAccessData::setIsLoadedFrom):
(JSC::DFG::VariableAccessData::isLoadedFrom):

LayoutTests:

Reviewed by Oliver Hunt and Gavin Barraclough.

  • fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int-expected.txt: Added.
  • fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.html: Added.
  • fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers-expected.txt: Added.
  • fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.html: Added.
  • fast/js/jsc-test-list:
  • fast/js/script-tests/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.js: Added.

(foo):
(bar):

  • fast/js/script-tests/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.js: Added.

(foo):
(bar):

File:
1 edited

Legend:

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

    r144862 r145299  
    4848            return false;
    4949       
     50        clearIsLoadedFrom();
    5051        freeUnnecessaryNodes();
    5152        canonicalizeLocalsInBlocks();
     
    5859
    5960private:
     61   
     62    void clearIsLoadedFrom()
     63    {
     64        for (unsigned i = 0; i < m_graph.m_variableAccessData.size(); ++i)
     65            m_graph.m_variableAccessData[i].setIsLoadedFrom(false);
     66    }
    6067   
    6168    void freeUnnecessaryNodes()
     
    171178           
    172179            if (otherNode->op() == SetArgument) {
     180                variable->setIsLoadedFrom(true);
    173181                node->children.setChild1(Edge(otherNode));
    174182                m_block->variablesAtTail.atFor<operandKind>(idx) = node;
     
    177185           
    178186            if (variable->isCaptured()) {
     187                variable->setIsLoadedFrom(true);
    179188                if (otherNode->op() == GetLocal)
    180189                    otherNode = otherNode->child1().node();
     
    201210        }
    202211       
     212        variable->setIsLoadedFrom(true);
    203213        Node* phi = addPhi<operandKind>(node->codeOrigin, variable, idx);
    204214        node->children.setChild1(Edge(phi));
     
    257267            }
    258268           
     269            variable->setIsLoadedFrom(true);
    259270            // There is nothing wrong with having redundant Flush's. It just needs to
    260271            // be linked appropriately. Note that if there had already been a previous
     
    267278        }
    268279       
     280        variable->setIsLoadedFrom(true);
    269281        node->children.setChild1(Edge(addPhi<operandKind>(node->codeOrigin, variable, idx)));
    270282        m_block->variablesAtHead.atFor<operandKind>(idx) = node;
Note: See TracChangeset for help on using the changeset viewer.