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/DFGNodeFlags.cpp

    r144362 r145299  
    2929#if ENABLE(DFG_JIT)
    3030
    31 #include <wtf/BoundsCheckedPointer.h>
     31#include <wtf/CommaPrinter.h>
    3232
    3333namespace JSC { namespace DFG {
    3434
    35 const char* nodeFlagsAsString(NodeFlags flags)
     35void dumpNodeFlags(PrintStream& out, NodeFlags flags)
    3636{
    37     if (!(flags ^ NodeDoesNotExit))
    38         return "<empty>";
     37    if (!(flags ^ NodeDoesNotExit)) {
     38        out.print("<empty>");
     39        return;
     40    }
    3941
    40     static const int size = 128;
    41     static char description[size];
    42     BoundsCheckedPointer<char> ptr(description, size);
    43    
    44     bool hasPrinted = false;
     42    CommaPrinter comma("|");
    4543   
    4644    if (flags & NodeResultMask) {
    4745        switch (flags & NodeResultMask) {
    4846        case NodeResultJS:
    49             ptr.strcat("JS");
     47            out.print(comma, "JS");
    5048            break;
    5149        case NodeResultNumber:
    52             ptr.strcat("Number");
     50            out.print(comma, "Number");
    5351            break;
    5452        case NodeResultInt32:
    55             ptr.strcat("Int32");
     53            out.print(comma, "Int32");
    5654            break;
    5755        case NodeResultBoolean:
    58             ptr.strcat("Boolean");
     56            out.print(comma, "Boolean");
    5957            break;
    6058        case NodeResultStorage:
    61             ptr.strcat("Storage");
     59            out.print(comma, "Storage");
    6260            break;
    6361        default:
     
    6563            break;
    6664        }
    67         hasPrinted = true;
    6865    }
    6966   
    70     if (flags & NodeMustGenerate) {
    71         if (hasPrinted)
    72             ptr.strcat("|");
    73         ptr.strcat("MustGen");
    74         hasPrinted = true;
     67    if (flags & NodeMustGenerate)
     68        out.print(comma, "MustGen");
     69   
     70    if (flags & NodeHasVarArgs)
     71        out.print(comma, "VarArgs");
     72   
     73    if (flags & NodeClobbersWorld)
     74        out.print(comma, "Clobbers");
     75   
     76    if (flags & NodeMightClobber)
     77        out.print(comma, "MightClobber");
     78   
     79    if (flags & NodeResultMask) {
     80        if (!(flags & NodeUsedAsNumber) && !(flags & NodeNeedsNegZero))
     81            out.print(comma, "PureInt");
     82        else if (!(flags & NodeUsedAsNumber))
     83            out.print(comma, "PureInt(w/ neg zero)");
     84        else if (!(flags & NodeNeedsNegZero))
     85            out.print(comma, "PureNum");
     86        if (flags & NodeUsedAsOther)
     87            out.print(comma, "UseAsOther");
    7588    }
    7689   
    77     if (flags & NodeHasVarArgs) {
    78         if (hasPrinted)
    79             ptr.strcat("|");
    80         ptr.strcat("VarArgs");
    81         hasPrinted = true;
    82     }
     90    if (flags & NodeMayOverflow)
     91        out.print(comma, "MayOverflow");
    8392   
    84     if (flags & NodeClobbersWorld) {
    85         if (hasPrinted)
    86             ptr.strcat("|");
    87         ptr.strcat("Clobbers");
    88         hasPrinted = true;
    89     }
     93    if (flags & NodeMayNegZero)
     94        out.print(comma, "MayNegZero");
    9095   
    91     if (flags & NodeMightClobber) {
    92         if (hasPrinted)
    93             ptr.strcat("|");
    94         ptr.strcat("MightClobber");
    95         hasPrinted = true;
    96     }
     96    if (flags & NodeUsedAsInt)
     97        out.print(comma, "UseAsInt");
    9798   
    98     if (flags & NodeResultMask) {
    99         if (!(flags & NodeUsedAsNumber) && !(flags & NodeNeedsNegZero)) {
    100             if (hasPrinted)
    101                 ptr.strcat("|");
    102             ptr.strcat("PureInt");
    103             hasPrinted = true;
    104         } else if (!(flags & NodeUsedAsNumber)) {
    105             if (hasPrinted)
    106                 ptr.strcat("|");
    107             ptr.strcat("PureInt(w/ neg zero)");
    108             hasPrinted = true;
    109         } else if (!(flags & NodeNeedsNegZero)) {
    110             if (hasPrinted)
    111                 ptr.strcat("|");
    112             ptr.strcat("PureNum");
    113             hasPrinted = true;
    114         }
    115         if (flags & NodeUsedAsOther) {
    116             if (hasPrinted)
    117                 ptr.strcat("|");
    118             ptr.strcat("UseAsOther");
    119             hasPrinted = true;
    120         }
    121     }
     99    if (!(flags & NodeDoesNotExit))
     100        out.print(comma, "CanExit");
    122101   
    123     if (flags & NodeMayOverflow) {
    124         if (hasPrinted)
    125             ptr.strcat("|");
    126         ptr.strcat("MayOverflow");
    127         hasPrinted = true;
    128     }
    129    
    130     if (flags & NodeMayNegZero) {
    131         if (hasPrinted)
    132             ptr.strcat("|");
    133         ptr.strcat("MayNegZero");
    134         hasPrinted = true;
    135     }
    136    
    137     if (flags & NodeUsedAsInt) {
    138         if (hasPrinted)
    139             ptr.strcat("|");
    140         ptr.strcat("UseAsInt");
    141         hasPrinted = true;
    142     }
    143    
    144     if (!(flags & NodeDoesNotExit)) {
    145         if (hasPrinted)
    146             ptr.strcat("|");
    147         ptr.strcat("CanExit");
    148         hasPrinted = true;
    149     }
    150    
    151     if (flags & NodeExitsForward) {
    152         if (hasPrinted)
    153             ptr.strcat("|");
    154         ptr.strcat("NodeExitsForward");
    155         hasPrinted = true;
    156     }
    157    
    158     *ptr++ = 0;
    159    
    160     return description;
     102    if (flags & NodeExitsForward)
     103        out.print(comma, "NodeExitsForward");
    161104}
    162 
    163105
    164106} } // namespace JSC::DFG
Note: See TracChangeset for help on using the changeset viewer.