Changeset 145299 in webkit


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):

Location:
trunk
Files:
8 added
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r145298 r145299  
     12013-03-08  Filip Pizlo  <[email protected]>
     2
     3        DFG overflow check elimination is too smart for its own good
     4        https://bugs.webkit.org/show_bug.cgi?id=111832
     5
     6        Reviewed by Oliver Hunt and Gavin Barraclough.
     7
     8        * fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int-expected.txt: Added.
     9        * fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.html: Added.
     10        * fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers-expected.txt: Added.
     11        * fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.html: Added.
     12        * fast/js/jsc-test-list:
     13        * fast/js/script-tests/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int.js: Added.
     14        (foo):
     15        (bar):
     16        * fast/js/script-tests/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers.js: Added.
     17        (foo):
     18        (bar):
     19
    1202013-03-08  James Robinson  <[email protected]>
    221
  • trunk/LayoutTests/fast/js/jsc-test-list

    r145145 r145299  
    8383fast/js/dfg-arguments-out-of-bounds
    8484fast/js/dfg-arguments-unexpected-escape
     85fast/js/dfg-arith-add-overflow-check-elimination-tower-of-large-numbers
     86fast/js/dfg-arith-add-overflow-check-elimination-predicted-but-not-proven-int
    8587fast/js/dfg-arrayify-elimination
    8688fast/js/dfg-arrayify-when-late-prevent-extensions
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r145119 r145299  
    7979    dfg/DFGArrayMode.cpp
    8080    dfg/DFGAssemblyHelpers.cpp
     81    dfg/DFGBackwardsPropagationPhase.cpp
    8182    dfg/DFGByteCodeParser.cpp
    8283    dfg/DFGCapabilities.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r145247 r145299  
     12013-03-08  Filip Pizlo  <[email protected]>
     2
     3        DFG overflow check elimination is too smart for its own good
     4        https://bugs.webkit.org/show_bug.cgi?id=111832
     5
     6        Reviewed by Oliver Hunt and Gavin Barraclough.
     7       
     8        This improves overflow check elimination in three ways:
     9       
     10        1) It reduces the amount of time the compiler will spend doing it.
     11       
     12        2) It fixes bugs where overflow check elimination was overzealous. Precisely, for a binary operation
     13           over @a and @b where both @a and @b will type check that their inputs (@a->children, @b->children)
     14           are int32's and then perform a possibly-overflowing operation, we must be careful not to assume
     15           that @a's non-int32 parts don't matter if at the point that @a runs we have as yet not proved that
     16           @b->children are int32's and that hence @b might produce a large enough result that doubles would
     17           start chopping low bits. The specific implication of this is that for a binary operation to not
     18           propagate that it cares about non-int32 parts (NodeUsedAsNumber), we must prove that at least one
     19           of the inputs is guaranteed to produce a result within 2^32 and that there won't be a tower of such
     20           operations large enough to ultimately produce a double greater than 2^52 (roughly). We achieve the
     21           latter by disabling this optimization for very large basic blocks. It's noteworthy that blocks that
     22           large won't even make it into the DFG currently.
     23       
     24        3) It makes the overflow check elimination more precise for cases where the inputs to an Add or Sub
     25           are the outputs of a bit-op. For example in (@a + (@b | 0)) | 0, we don't need to propagate
     26           NodeUsedAsNumber to either @a or @b.
     27       
     28        This is neutral on V8v7 and a slight speed-up on compile time benchmarks.
     29
     30        * CMakeLists.txt:
     31        * GNUmakefile.list.am:
     32        * JavaScriptCore.xcodeproj/project.pbxproj:
     33        * Target.pri:
     34        * dfg/DFGArrayMode.cpp:
     35        (JSC::DFG::ArrayMode::refine):
     36        * dfg/DFGBackwardsPropagationPhase.cpp: Added.
     37        (DFG):
     38        (BackwardsPropagationPhase):
     39        (JSC::DFG::BackwardsPropagationPhase::BackwardsPropagationPhase):
     40        (JSC::DFG::BackwardsPropagationPhase::run):
     41        (JSC::DFG::BackwardsPropagationPhase::isNotNegZero):
     42        (JSC::DFG::BackwardsPropagationPhase::isNotZero):
     43        (JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwoForConstant):
     44        (JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwoNonRecursive):
     45        (JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwo):
     46        (JSC::DFG::BackwardsPropagationPhase::mergeDefaultFlags):
     47        (JSC::DFG::BackwardsPropagationPhase::propagate):
     48        (JSC::DFG::performBackwardsPropagation):
     49        * dfg/DFGBackwardsPropagationPhase.h: Added.
     50        (DFG):
     51        * dfg/DFGCPSRethreadingPhase.cpp:
     52        (JSC::DFG::CPSRethreadingPhase::run):
     53        (JSC::DFG::CPSRethreadingPhase::clearIsLoadedFrom):
     54        (CPSRethreadingPhase):
     55        (JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
     56        (JSC::DFG::CPSRethreadingPhase::canonicalizeFlushOrPhantomLocalFor):
     57        * dfg/DFGDriver.cpp:
     58        (JSC::DFG::compile):
     59        * dfg/DFGGraph.cpp:
     60        (JSC::DFG::Graph::dump):
     61        * dfg/DFGNodeFlags.cpp:
     62        (JSC::DFG::dumpNodeFlags):
     63        (DFG):
     64        * dfg/DFGNodeFlags.h:
     65        (DFG):
     66        * dfg/DFGPredictionPropagationPhase.cpp:
     67        (PredictionPropagationPhase):
     68        (JSC::DFG::PredictionPropagationPhase::propagate):
     69        * dfg/DFGUnificationPhase.cpp:
     70        (JSC::DFG::UnificationPhase::run):
     71        * dfg/DFGVariableAccessData.h:
     72        (JSC::DFG::VariableAccessData::VariableAccessData):
     73        (JSC::DFG::VariableAccessData::mergeIsLoadedFrom):
     74        (VariableAccessData):
     75        (JSC::DFG::VariableAccessData::setIsLoadedFrom):
     76        (JSC::DFG::VariableAccessData::isLoadedFrom):
     77
    1782013-03-08  Roger Fong  <[email protected]>
    279
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r145119 r145299  
    185185        Source/JavaScriptCore/dfg/DFGAssemblyHelpers.cpp \
    186186        Source/JavaScriptCore/dfg/DFGAssemblyHelpers.h \
     187        Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp \
     188        Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.h \
    187189        Source/JavaScriptCore/dfg/DFGBasicBlock.h \
    188190        Source/JavaScriptCore/dfg/DFGBasicBlockInlines.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r145119 r145299  
    164164                0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */; settings = {ATTRIBUTES = (Private, ); }; };
    165165                0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
     166                0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */; };
     167                0F714CA516EA92F200F3EBEB /* DFGBackwardsPropagationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
    166168                0F73D7AE165A142D00ACAB71 /* ClosureCallStubRoutine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F73D7AB165A142A00ACAB71 /* ClosureCallStubRoutine.cpp */; };
    167169                0F73D7AF165A143000ACAB71 /* ClosureCallStubRoutine.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F73D7AC165A142A00ACAB71 /* ClosureCallStubRoutine.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    10641066                0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdjacencyList.h; path = dfg/DFGAdjacencyList.h; sourceTree = "<group>"; };
    10651067                0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdge.h; path = dfg/DFGEdge.h; sourceTree = "<group>"; };
     1068                0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBackwardsPropagationPhase.cpp; path = dfg/DFGBackwardsPropagationPhase.cpp; sourceTree = "<group>"; };
     1069                0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBackwardsPropagationPhase.h; path = dfg/DFGBackwardsPropagationPhase.h; sourceTree = "<group>"; };
    10661070                0F73D7AB165A142A00ACAB71 /* ClosureCallStubRoutine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ClosureCallStubRoutine.cpp; sourceTree = "<group>"; };
    10671071                0F73D7AC165A142A00ACAB71 /* ClosureCallStubRoutine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClosureCallStubRoutine.h; sourceTree = "<group>"; };
     
    26372641                                0FC0976B1468AB4A00CF2442 /* DFGAssemblyHelpers.cpp */,
    26382642                                0FC0976C1468AB4A00CF2442 /* DFGAssemblyHelpers.h */,
     2643                                0F714CA116EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.cpp */,
     2644                                0F714CA216EA92ED00F3EBEB /* DFGBackwardsPropagationPhase.h */,
    26392645                                0F620170143FCD2F0068B77C /* DFGBasicBlock.h */,
    26402646                                0FD5652216AB780A00197653 /* DFGBasicBlockInlines.h */,
     
    34093415                                0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */,
    34103416                                0FCCAE4516D0CF7400D0C65B /* ParserError.h in Headers */,
     3417                                0F714CA516EA92F200F3EBEB /* DFGBackwardsPropagationPhase.h in Headers */,
    34113418                        );
    34123419                        runOnlyForDeploymentPostprocessing = 0;
     
    40524059                                0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */,
    40534060                                ADE39FFF16DD144B0003CD4A /* PropertyTable.cpp in Sources */,
     4061                                0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */,
    40544062                        );
    40554063                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/JavaScriptCore/Target.pri

    r145119 r145299  
    115115    dfg/DFGArrayMode.cpp \
    116116    dfg/DFGAssemblyHelpers.cpp \
     117    dfg/DFGBackwardsPropagationPhase.cpp \
    117118    dfg/DFGByteCodeParser.cpp \
    118119    dfg/DFGCapabilities.cpp \
  • trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp

    r141069 r145299  
    168168       
    169169    case Array::Double:
    170         if (flags & NodeUsedAsIntLocally)
     170        if (flags & NodeUsedAsInt)
    171171            return withTypeAndConversion(Array::Contiguous, Array::RageConvert);
    172172        if (!value || isNumberSpeculation(value))
     
    175175       
    176176    case Array::Contiguous:
    177         if (doesConversion() && (flags & NodeUsedAsIntLocally))
     177        if (doesConversion() && (flags & NodeUsedAsInt))
    178178            return withConversion(Array::RageConvert);
    179179        return *this;
  • 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;
  • trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp

    r145143 r145299  
    3434
    3535#include "DFGArgumentsSimplificationPhase.h"
     36#include "DFGBackwardsPropagationPhase.h"
    3637#include "DFGByteCodeParser.h"
    3738#include "DFGCFAPhase.h"
     
    123124        validate(dfg);
    124125   
     126    performBackwardsPropagation(dfg);
    125127    performPredictionPropagation(dfg);
    126128    performFixup(dfg);
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r144862 r145299  
    180180    }
    181181
    182     if (strlen(nodeFlagsAsString(node->flags())))
    183         out.print(comma, nodeFlagsAsString(node->flags()));
     182    if (toCString(NodeFlagsDump(node->flags())) != "<empty>")
     183        out.print(comma, NodeFlagsDump(node->flags()));
    184184    if (node->hasArrayMode())
    185185        out.print(comma, node->arrayMode());
  • 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
  • trunk/Source/JavaScriptCore/dfg/DFGNodeFlags.h

    r144362 r145299  
    3131#if ENABLE(DFG_JIT)
    3232
     33#include <wtf/PrintStream.h>
    3334#include <wtf/StdLibExtras.h>
    3435
     
    6061#define NodeUsedAsValue          (NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther)
    6162#define NodeUsedAsInt            0x1000 // The result of this computation is known to be used in a context that prefers, but does not require, integer values.
    62 #define NodeUsedAsIntLocally     0x2000 // Same as NodeUsedAsInt, but within the same basic block.
    6363
    6464#define NodeArithFlagsMask       (NodeBehaviorMask | NodeBackPropMask)
    6565
    66 #define NodeDoesNotExit          0x4000 // This flag is negated to make it natural for the default to be that a node does exit.
     66#define NodeDoesNotExit          0x2000 // This flag is negated to make it natural for the default to be that a node does exit.
    6767
    68 #define NodeRelevantToOSR        0x8000
     68#define NodeRelevantToOSR        0x4000
    6969
    70 #define NodeExitsForward        0x10000
     70#define NodeExitsForward         0x8000
    7171
    7272typedef uint32_t NodeFlags;
     
    103103}
    104104
    105 const char* nodeFlagsAsString(NodeFlags);
     105void dumpNodeFlags(PrintStream&, NodeFlags);
     106MAKE_PRINT_ADAPTOR(NodeFlagsDump, NodeFlags, dumpNodeFlags);
    106107
    107108} } // namespace JSC::DFG
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r144939 r145299  
    107107    }
    108108   
    109     bool isNotNegZero(Node* node)
    110     {
    111         if (!m_graph.isNumberConstant(node))
    112             return false;
    113         double value = m_graph.valueOfNumberConstant(node);
    114         return !value && 1.0 / value < 0.0;
    115     }
    116    
    117     bool isNotZero(Node* node)
    118     {
    119         if (!m_graph.isNumberConstant(node))
    120             return false;
    121         return !!m_graph.valueOfNumberConstant(node);
    122     }
    123    
    124     bool isWithinPowerOfTwoForConstant(Node* node, int power)
    125     {
    126         JSValue immediateValue = node->valueOfJSConstant(codeBlock());
    127         if (!immediateValue.isInt32())
    128             return false;
    129         int32_t intImmediate = immediateValue.asInt32();
    130         return intImmediate > -(1 << power) && intImmediate < (1 << power);
    131     }
    132    
    133     bool isWithinPowerOfTwoNonRecursive(Node* node, int power)
    134     {
    135         if (node->op() != JSConstant)
    136             return false;
    137         return isWithinPowerOfTwoForConstant(node, power);
    138     }
    139    
    140     bool isWithinPowerOfTwo(Node* node, int power)
    141     {
    142         switch (node->op()) {
    143         case JSConstant: {
    144             return isWithinPowerOfTwoForConstant(node, power);
    145         }
    146            
    147         case BitAnd: {
    148             return isWithinPowerOfTwoNonRecursive(node->child1().node(), power)
    149                 || isWithinPowerOfTwoNonRecursive(node->child2().node(), power);
    150         }
    151            
    152         case BitRShift:
    153         case BitURShift: {
    154             Node* shiftAmount = node->child2().node();
    155             if (shiftAmount->op() != JSConstant)
    156                 return false;
    157             JSValue immediateValue = shiftAmount->valueOfJSConstant(codeBlock());
    158             if (!immediateValue.isInt32())
    159                 return false;
    160             return immediateValue > 32 - power;
    161         }
    162            
    163         default:
    164             return false;
    165         }
    166     }
    167 
    168109    SpeculatedType speculatedDoubleTypeForPrediction(SpeculatedType value)
    169110    {
     
    183124    {
    184125        NodeType op = node->op();
    185         NodeFlags flags = node->flags() & NodeBackPropMask;
    186126
    187127#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
    188         dataLog("   ", Graph::opName(op), " ", m_currentNode, ": ", nodeFlagsAsString(flags), " ");
     128        dataLog("   ", Graph::opName(op), " ", m_currentNode, ": ", NodeFlagsDump(node->flags()), " ");
    189129#endif
    190130       
     
    203143            if (prediction)
    204144                changed |= mergePrediction(prediction);
    205            
    206             // Assume conservatively that a SetLocal implies that the value may flow through a loop,
    207             // and so we would have overflow leading to the program "observing" numbers even if all
    208             // users of the value are doing toInt32. It might be worthwhile to revisit this at some
    209             // point and actually check if the data flow involves loops, but right now I don't think
    210             // we have evidence that this would be beneficial for benchmarks.
    211            
    212             changed |= variableAccessData->mergeFlags((flags & ~NodeUsedAsIntLocally) | NodeUsedAsNumber);
    213145            break;
    214146        }
     
    217149            VariableAccessData* variableAccessData = node->variableAccessData();
    218150            changed |= variableAccessData->predict(node->child1()->prediction());
    219 
    220             changed |= node->child1()->mergeFlags(variableAccessData->flags());
    221             break;
    222         }
    223            
    224         case Flush: {
    225             // Make sure that the analysis knows that flushed locals escape.
    226             VariableAccessData* variableAccessData = node->variableAccessData();
    227             changed |= variableAccessData->mergeFlags(NodeUsedAsValue);
    228151            break;
    229152        }
     
    236159        case BitURShift: {
    237160            changed |= setPrediction(SpecInt32);
    238             flags |= NodeUsedAsInt | NodeUsedAsIntLocally;
    239             flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
    240             changed |= node->child1()->mergeFlags(flags);
    241             changed |= node->child2()->mergeFlags(flags);
    242161            break;
    243162        }
     
    245164        case ValueToInt32: {
    246165            changed |= setPrediction(SpecInt32);
    247             flags |= NodeUsedAsInt | NodeUsedAsIntLocally;
    248             flags &= ~(NodeUsedAsNumber | NodeNeedsNegZero | NodeUsedAsOther);
    249             changed |= node->child1()->mergeFlags(flags);
    250             break;
    251         }
    252            
    253         case ArrayPop: {
    254             changed |= mergePrediction(node->getHeapPrediction());
    255             changed |= mergeDefaultFlags(node);
    256             break;
    257         }
    258 
    259         case ArrayPush: {
    260             changed |= mergePrediction(node->getHeapPrediction());
    261             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    262             changed |= node->child2()->mergeFlags(NodeUsedAsValue);
    263             break;
    264         }
    265 
     166            break;
     167        }
     168           
     169        case ArrayPop:
     170        case ArrayPush:
    266171        case RegExpExec:
    267         case RegExpTest: {
    268             changed |= mergePrediction(node->getHeapPrediction());
    269             changed |= mergeDefaultFlags(node);
     172        case RegExpTest:
     173        case GetById:
     174        case GetByIdFlush:
     175        case GetMyArgumentByValSafe:
     176        case GetByOffset:
     177        case Call:
     178        case Construct:
     179        case GetGlobalVar:
     180        case GetScopedVar:
     181        case Resolve:
     182        case ResolveBase:
     183        case ResolveBaseStrictPut:
     184        case ResolveGlobal: {
     185            changed |= setPrediction(node->getHeapPrediction());
    270186            break;
    271187        }
    272188
    273189        case StringCharCodeAt: {
    274             changed |= mergePrediction(SpecInt32);
    275             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    276             changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
     190            changed |= setPrediction(SpecInt32);
    277191            break;
    278192        }
     
    283197            else
    284198                changed |= mergePrediction(SpecNumber);
    285            
    286             changed |= node->child1()->mergeFlags(flags);
    287199            break;
    288200        }
     
    291203            SpeculatedType left = node->child1()->prediction();
    292204            SpeculatedType right = node->child2()->prediction();
    293            
    294             AddSpeculationMode mode = DontSpeculateInteger;
    295205           
    296206            if (left && right) {
    297207                if (isNumberSpeculationExpectingDefined(left) && isNumberSpeculationExpectingDefined(right)) {
    298                     if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
     208                    if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
    299209                        changed |= mergePrediction(SpecInt32);
    300210                    else
     
    306216                    changed |= mergePrediction(SpecString | SpecInt32 | SpecDouble);
    307217            }
    308            
    309             if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node()))
    310                 flags &= ~NodeNeedsNegZero;
    311             if (node->child1()->hasNumberResult() || node->child2()->hasNumberResult())
    312                 flags &= ~NodeUsedAsOther;
    313            
    314             if (mode != SpeculateInteger)
    315                 flags |= NodeUsedAsNumber;
    316            
    317             changed |= node->child1()->mergeFlags(flags);
    318             changed |= node->child2()->mergeFlags(flags);
    319218            break;
    320219        }
     
    324223            SpeculatedType right = node->child2()->prediction();
    325224           
    326             AddSpeculationMode mode = DontSpeculateInteger;
    327            
    328225            if (left && right) {
    329                 if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
     226                if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
    330227                    changed |= mergePrediction(SpecInt32);
    331228                else
    332229                    changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
    333230            }
    334            
    335             if (isNotNegZero(node->child1().node()) || isNotNegZero(node->child2().node()))
    336                 flags &= ~NodeNeedsNegZero;
    337             flags &= ~NodeUsedAsOther;
    338            
    339             if (mode != SpeculateInteger)
    340                 flags |= NodeUsedAsNumber;
    341            
    342             changed |= node->child1()->mergeFlags(flags);
    343             changed |= node->child2()->mergeFlags(flags);
    344231            break;
    345232        }
     
    349236            SpeculatedType right = node->child2()->prediction();
    350237           
    351             AddSpeculationMode mode = DontSpeculateInteger;
    352            
    353238            if (left && right) {
    354                 if ((mode = m_graph.addSpeculationMode(node)) != DontSpeculateInteger)
     239                if (m_graph.addSpeculationMode(node) != DontSpeculateInteger)
    355240                    changed |= mergePrediction(SpecInt32);
    356241                else
    357242                    changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
    358243            }
    359 
    360             if (isNotZero(node->child1().node()) || isNotZero(node->child2().node()))
    361                 flags &= ~NodeNeedsNegZero;
    362             flags &= ~NodeUsedAsOther;
    363            
    364             if (mode != SpeculateInteger)
    365                 flags |= NodeUsedAsNumber;
    366            
    367             changed |= node->child1()->mergeFlags(flags);
    368             changed |= node->child2()->mergeFlags(flags);
    369244            break;
    370245        }
     
    377252                    changed |= mergePrediction(speculatedDoubleTypeForPrediction(node->child1()->prediction()));
    378253            }
    379 
    380             flags &= ~NodeUsedAsOther;
    381 
    382             changed |= node->child1()->mergeFlags(flags);
    383254            break;
    384255           
     
    395266                    changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
    396267            }
    397 
    398             flags |= NodeUsedAsNumber;
    399             flags &= ~NodeUsedAsOther;
    400 
    401             changed |= node->child1()->mergeFlags(flags);
    402             changed |= node->child2()->mergeFlags(flags);
    403268            break;
    404269        }
     
    414279                    changed |= mergePrediction(speculatedDoubleTypeForPredictions(left, right));
    415280            }
    416 
    417             // As soon as a multiply happens, we can easily end up in the part
    418             // of the double domain where the point at which you do truncation
    419             // can change the outcome. So, ArithMul always forces its inputs to
    420             // check for overflow. Additionally, it will have to check for overflow
    421             // itself unless we can prove that there is no way for the values
    422             // produced to cause double rounding.
    423            
    424             if (!isWithinPowerOfTwo(node->child1().node(), 22)
    425                 && !isWithinPowerOfTwo(node->child2().node(), 22))
    426                 flags |= NodeUsedAsNumber;
    427            
    428             changed |= node->mergeFlags(flags);
    429            
    430             flags |= NodeUsedAsNumber | NodeNeedsNegZero;
    431             flags &= ~NodeUsedAsOther;
    432 
    433             changed |= node->child1()->mergeFlags(flags);
    434             changed |= node->child2()->mergeFlags(flags);
    435281            break;
    436282        }
     
    447293                    changed |= mergePrediction(SpecDouble);
    448294            }
    449 
    450             // As soon as a multiply happens, we can easily end up in the part
    451             // of the double domain where the point at which you do truncation
    452             // can change the outcome. So, ArithDiv always checks for overflow
    453             // no matter what, and always forces its inputs to check as well.
    454            
    455             flags |= NodeUsedAsNumber | NodeNeedsNegZero;
    456             flags &= ~NodeUsedAsOther;
    457 
    458             changed |= node->child1()->mergeFlags(flags);
    459             changed |= node->child2()->mergeFlags(flags);
    460295            break;
    461296        }
     
    472307                    changed |= mergePrediction(SpecDouble);
    473308            }
    474            
    475             flags |= NodeUsedAsNumber | NodeNeedsNegZero;
    476             flags &= ~NodeUsedAsOther;
    477 
    478             changed |= node->child1()->mergeFlags(flags);
    479             changed |= node->child2()->mergeFlags(flags);
    480309            break;
    481310        }
     
    483312        case ArithSqrt: {
    484313            changed |= setPrediction(SpecDouble);
    485             flags |= NodeUsedAsNumber | NodeNeedsNegZero;
    486             flags &= ~NodeUsedAsOther;
    487             changed |= node->child1()->mergeFlags(flags);
    488314            break;
    489315        }
     
    496322            else
    497323                changed |= mergePrediction(speculatedDoubleTypeForPrediction(child));
    498 
    499             changed |= node->child1()->mergeFlags(flags);
    500324            break;
    501325        }
     
    518342        case IsFunction: {
    519343            changed |= setPrediction(SpecBoolean);
    520             changed |= mergeDefaultFlags(node);
    521344            break;
    522345        }
     
    524347        case TypeOf: {
    525348            changed |= setPrediction(SpecString);
    526             changed |= mergeDefaultFlags(node);
    527             break;
    528         }
    529 
    530         case GetById: {
    531             changed |= mergePrediction(node->getHeapPrediction());
    532             changed |= mergeDefaultFlags(node);
    533             break;
    534         }
    535            
    536         case GetByIdFlush:
    537             changed |= mergePrediction(node->getHeapPrediction());
    538             changed |= mergeDefaultFlags(node);
    539             break;
    540            
     349            break;
     350        }
     351
    541352        case GetByVal: {
    542353            if (node->child1()->shouldSpeculateFloat32Array()
     
    545356            else
    546357                changed |= mergePrediction(node->getHeapPrediction());
    547 
    548             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    549             changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
    550             break;
    551         }
    552            
    553         case GetMyArgumentByValSafe: {
    554             changed |= mergePrediction(node->getHeapPrediction());
    555             changed |= node->child1()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
    556358            break;
    557359        }
     
    568370        case ReallocatePropertyStorage: {
    569371            changed |= setPrediction(SpecOther);
    570             changed |= mergeDefaultFlags(node);
    571             break;
    572         }
    573 
    574         case GetByOffset: {
    575             changed |= mergePrediction(node->getHeapPrediction());
    576             changed |= mergeDefaultFlags(node);
    577             break;
    578         }
    579            
    580         case Call:
    581         case Construct: {
    582             changed |= mergePrediction(node->getHeapPrediction());
    583             for (unsigned childIdx = node->firstChild();
    584                 childIdx < node->firstChild() + node->numChildren();
    585                 ++childIdx)
    586                 changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);
    587             break;
    588         }
    589            
     372            break;
     373        }
     374
    590375        case ConvertThis: {
    591376            SpeculatedType prediction = node->child1()->prediction();
     
    597382                changed |= mergePrediction(prediction);
    598383            }
    599             changed |= mergeDefaultFlags(node);
    600             break;
    601         }
    602            
    603         case GetGlobalVar: {
    604             changed |= mergePrediction(node->getHeapPrediction());
    605             break;
    606         }
    607            
    608         case PutGlobalVar:
    609         case PutGlobalVarCheck: {
    610             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    611             break;
    612         }
    613            
    614         case GetScopedVar:
    615         case Resolve:
    616         case ResolveBase:
    617         case ResolveBaseStrictPut:
    618         case ResolveGlobal: {
    619             SpeculatedType prediction = node->getHeapPrediction();
    620             changed |= mergePrediction(prediction);
    621384            break;
    622385        }
     
    637400        case NewObject: {
    638401            changed |= setPrediction(SpecFinalObject);
    639             changed |= mergeDefaultFlags(node);
    640             break;
    641         }
    642            
    643         case NewArray: {
    644             changed |= setPrediction(SpecArray);
    645             for (unsigned childIdx = node->firstChild();
    646                 childIdx < node->firstChild() + node->numChildren();
    647                 ++childIdx)
    648                 changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);
    649             break;
    650         }
    651            
    652         case NewArrayWithSize: {
    653             changed |= setPrediction(SpecArray);
    654             changed |= node->child1()->mergeFlags(NodeUsedAsValue | NodeUsedAsInt | NodeUsedAsIntLocally);
    655             break;
    656         }
    657            
     402            break;
     403        }
     404           
     405        case NewArray:
     406        case NewArrayWithSize:
    658407        case NewArrayBuffer: {
    659408            changed |= setPrediction(SpecArray);
     
    661410        }
    662411           
    663         case NewRegexp: {
     412        case NewRegexp:
     413        case CreateActivation: {
    664414            changed |= setPrediction(SpecObjectOther);
    665415            break;
    666416        }
    667417       
    668         case StringCharAt: {
    669             changed |= setPrediction(SpecString);
    670             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    671             changed |= node->child2()->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
    672             break;
    673         }
    674            
     418        case StringCharAt:
    675419        case StrCat: {
    676420            changed |= setPrediction(SpecString);
    677             for (unsigned childIdx = node->firstChild();
    678                 childIdx < node->firstChild() + node->numChildren();
    679                 ++childIdx)
    680                 changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther);
    681421            break;
    682422        }
     
    700440                    changed |= mergePrediction(child);
    701441            }
    702             changed |= node->child1()->mergeFlags(flags);
    703             break;
    704         }
    705            
    706         case CreateActivation: {
    707             changed |= setPrediction(SpecObjectOther);
    708442            break;
    709443        }
     
    744478        }
    745479       
    746         case PutByVal:
    747             changed |= m_graph.varArgChild(node, 0)->mergeFlags(NodeUsedAsValue);
    748             changed |= m_graph.varArgChild(node, 1)->mergeFlags(NodeUsedAsNumber | NodeUsedAsOther | NodeUsedAsInt | NodeUsedAsIntLocally);
    749             changed |= m_graph.varArgChild(node, 2)->mergeFlags(NodeUsedAsValue);
    750             break;
    751 
    752         case PutScopedVar:
    753             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    754             changed |= node->child3()->mergeFlags(NodeUsedAsValue);
    755             break;
    756            
    757         case Return:
    758         case Throw:
    759             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    760             break;
    761 
    762         case PutById:
    763         case PutByIdDirect:
    764             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    765             changed |= node->child2()->mergeFlags(NodeUsedAsValue);
    766             break;
    767 
    768         case PutByOffset:
    769             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    770             changed |= node->child3()->mergeFlags(NodeUsedAsValue);
    771             break;
    772            
    773480        case Phi:
    774481            // Phis should not be visible here since we're iterating the all-but-Phi's
     
    777484            break;
    778485
     486        case GetScope:
     487            changed |= setPrediction(SpecCellOther);
     488            break;
     489
     490#ifndef NDEBUG
     491        // These get ignored because they don't return anything.
     492        case PutByVal:
     493        case PutScopedVar:
     494        case Return:
     495        case Throw:
     496        case PutById:
     497        case PutByIdDirect:
     498        case PutByOffset:
    779499        case SetCallee:
    780500        case SetMyScope:
    781             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    782             break;
    783            
    784         case GetScope:
    785             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    786             changed |= setPrediction(SpecCellOther);
    787             break;
    788 
    789 #ifndef NDEBUG
    790         // These get ignored because they don't return anything.
    791501        case DFG::Jump:
    792502        case Branch:
     
    810520        case AllocationProfileWatchpoint:
    811521        case Phantom:
    812             changed |= mergeDefaultFlags(node);
     522        case PutGlobalVar:
     523        case PutGlobalVarCheck:
    813524            break;
    814525           
     
    818529        case CountExecution:
    819530        case PhantomLocal:
     531        case Flush:
    820532            break;
    821533           
     
    825537#else
    826538        default:
    827             changed |= mergeDefaultFlags(node);
    828539            break;
    829540#endif
     
    837548    }
    838549       
    839     bool mergeDefaultFlags(Node* node)
    840     {
    841         bool changed = false;
    842         if (node->flags() & NodeHasVarArgs) {
    843             for (unsigned childIdx = node->firstChild();
    844                 childIdx < node->firstChild() + node->numChildren();
    845                 childIdx++) {
    846                 if (!!m_graph.m_varArgChildren[childIdx])
    847                     changed |= m_graph.m_varArgChildren[childIdx]->mergeFlags(NodeUsedAsValue);
    848             }
    849         } else {
    850             if (!node->child1())
    851                 return changed;
    852             changed |= node->child1()->mergeFlags(NodeUsedAsValue);
    853             if (!node->child2())
    854                 return changed;
    855             changed |= node->child2()->mergeFlags(NodeUsedAsValue);
    856             if (!node->child3())
    857                 return changed;
    858             changed |= node->child3()->mergeFlags(NodeUsedAsValue);
    859         }
    860         return changed;
    861     }
    862    
    863550    void propagateForward()
    864551    {
  • trunk/Source/JavaScriptCore/dfg/DFGUnificationPhase.cpp

    r143955 r145299  
    7474            data->find()->mergeStructureCheckHoistingFailed(data->structureCheckHoistingFailed());
    7575            data->find()->mergeShouldNeverUnbox(data->shouldNeverUnbox());
     76            data->find()->mergeIsLoadedFrom(data->isLoadedFrom());
    7677        }
    7778       
  • trunk/Source/JavaScriptCore/dfg/DFGVariableAccessData.h

    r144131 r145299  
    5252        , m_structureCheckHoistingFailed(false)
    5353        , m_isProfitableToUnbox(false)
     54        , m_isLoadedFrom(false)
    5455        , m_doubleFormatState(EmptyDoubleFormatState)
    5556    {
     
    150151    }
    151152   
     153    bool mergeIsLoadedFrom(bool isLoadedFrom)
     154    {
     155        return checkAndSet(m_isLoadedFrom, m_isLoadedFrom | isLoadedFrom);
     156    }
     157   
     158    void setIsLoadedFrom(bool isLoadedFrom)
     159    {
     160        m_isLoadedFrom = isLoadedFrom;
     161    }
     162   
     163    bool isLoadedFrom()
     164    {
     165        return m_isLoadedFrom;
     166    }
     167   
    152168    bool predict(SpeculatedType prediction)
    153169    {
     
    307323    bool m_structureCheckHoistingFailed;
    308324    bool m_isProfitableToUnbox;
     325    bool m_isLoadedFrom;
    309326
    310327    float m_votes[2]; // Used primarily for double voting but may be reused for other purposes.
Note: See TracChangeset for help on using the changeset viewer.