Changeset 96375 in webkit


Ignore:
Timestamp:
Sep 29, 2011 4:17:19 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG JIT should infer which uses of a variable are not aliased
https://bugs.webkit.org/show_bug.cgi?id=68593

Reviewed by Oliver Hunt.

This separates how a variable is stored (i.e. its virtual register)
from how it's predicted. Each variable now takes a
VariableAccessData as its operand, instead of the virtual register.
The VariableAccessData stores the operand and the prediction. If
multiple uses of a variable are aliased, their VariableAccessDatas
are unified.

This also adds tracking of which argument values are used. It
correctly observes that an argument value is not used, if the
argument is assigned to inside the function before being used.

This also adds tracking of which variables are live at the head of
a basic block, and separates that from a variable being live at the
tail.

Finally, this communicates to both OSR entry and OSR exit code how
a variable is predicted at a particular point in the code, rather
than just communicating how it was predicted in the entire code
block (since with this patch there is no longer the notion of a
variable having just one prediction for a code block).

(JSC::actionablePredictionFromPredictedType):
(JSC::valueObeysPrediction):
(JSC::actionablePredictionToString):
(JSC::ActionablePredictions::ActionablePredictions):
(JSC::ActionablePredictions::setArgument):
(JSC::ActionablePredictions::argument):
(JSC::ActionablePredictions::setVariable):
(JSC::ActionablePredictions::variable):
(JSC::ActionablePredictions::argumentUpperBound):
(JSC::ActionablePredictions::variableUpperBound):
(JSC::ActionablePredictions::pack):
(JSC::ActionablePredictions::packVector):

  • bytecode/CodeBlock.h:
  • bytecode/PredictionTracker.h:
  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::newVariableAccessData):
(JSC::DFG::ByteCodeParser::getLocal):
(JSC::DFG::ByteCodeParser::setLocal):
(JSC::DFG::ByteCodeParser::getArgument):
(JSC::DFG::ByteCodeParser::setArgument):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::processPhiStack):
(JSC::DFG::ByteCodeParser::parse):

  • dfg/DFGDriver.cpp:

(JSC::DFG::compile):

  • dfg/DFGGraph.cpp:

(JSC::DFG::Graph::nameOfVariableAccessData):
(JSC::DFG::Graph::dump):
(JSC::DFG::Graph::predictArgumentTypes):

  • dfg/DFGGraph.h:

(JSC::DFG::operandIsArgument):
(JSC::DFG::VariableRecord::setFirstTime):
(JSC::DFG::BasicBlock::BasicBlock):
(JSC::DFG::Graph::predict):
(JSC::DFG::Graph::getPrediction):

  • dfg/DFGJITCompiler.h:

(JSC::DFG::JITCompiler::noticeOSREntry):

  • dfg/DFGNode.h:

(JSC::DFG::Node::hasVariableAccessData):
(JSC::DFG::Node::hasLocal):
(JSC::DFG::Node::variableAccessData):
(JSC::DFG::Node::local):

  • dfg/DFGOSREntry.cpp:

(JSC::DFG::prepareOSREntry):

  • dfg/DFGOSREntry.h:
  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::propagateNodePredictions):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::ValueSource::dump):
(JSC::DFG::OSRExit::OSRExit):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::ValueSource::ValueSource):
(JSC::DFG::ValueSource::forPrediction):
(JSC::DFG::ValueSource::isSet):
(JSC::DFG::ValueSource::kind):
(JSC::DFG::ValueSource::nodeIndex):
(JSC::DFG::ValueSource::nodeIndexFromKind):
(JSC::DFG::ValueSource::kindFromNodeIndex):
(JSC::DFG::SpeculativeJIT::isKnownArray):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
(JSC::DFG::SpeculativeJIT::SpeculativeJIT):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::OSRExit::OSRExit):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::checkArgumentTypes):
(JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):

  • wtf/PackedIntVector.h: Added.

(WTF::PackedIntVector::PackedIntVector):
(WTF::PackedIntVector::operator=):
(WTF::PackedIntVector::size):
(WTF::PackedIntVector::ensureSize):
(WTF::PackedIntVector::resize):
(WTF::PackedIntVector::clearAll):
(WTF::PackedIntVector::get):
(WTF::PackedIntVector::set):
(WTF::PackedIntVector::mask):

  • wtf/Platform.h:
  • wtf/UnionFind.h: Added.

(WTF::UnionFind::UnionFind):
(WTF::UnionFind::find):
(WTF::UnionFind::unify):

Location:
trunk/Source/JavaScriptCore
Files:
3 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r96373 r96375  
     12011-09-28  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG JIT should infer which uses of a variable are not aliased
     4        https://bugs.webkit.org/show_bug.cgi?id=68593
     5
     6        Reviewed by Oliver Hunt.
     7       
     8        This separates how a variable is stored (i.e. its virtual register)
     9        from how it's predicted. Each variable now takes a
     10        VariableAccessData as its operand, instead of the virtual register.
     11        The VariableAccessData stores the operand and the prediction. If
     12        multiple uses of a variable are aliased, their VariableAccessDatas
     13        are unified.
     14       
     15        This also adds tracking of which argument values are used. It
     16        correctly observes that an argument value is not used, if the
     17        argument is assigned to inside the function before being used.
     18       
     19        This also adds tracking of which variables are live at the head of
     20        a basic block, and separates that from a variable being live at the
     21        tail.
     22       
     23        Finally, this communicates to both OSR entry and OSR exit code how
     24        a variable is predicted at a particular point in the code, rather
     25        than just communicating how it was predicted in the entire code
     26        block (since with this patch there is no longer the notion of a
     27        variable having just one prediction for a code block).
     28
     29        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
     30        * JavaScriptCore.vcproj/WTF/WTF.vcproj:
     31        * JavaScriptCore.xcodeproj/project.pbxproj:
     32        * bytecode/ActionablePrediction.h: Added.
     33        (JSC::actionablePredictionFromPredictedType):
     34        (JSC::valueObeysPrediction):
     35        (JSC::actionablePredictionToString):
     36        (JSC::ActionablePredictions::ActionablePredictions):
     37        (JSC::ActionablePredictions::setArgument):
     38        (JSC::ActionablePredictions::argument):
     39        (JSC::ActionablePredictions::setVariable):
     40        (JSC::ActionablePredictions::variable):
     41        (JSC::ActionablePredictions::argumentUpperBound):
     42        (JSC::ActionablePredictions::variableUpperBound):
     43        (JSC::ActionablePredictions::pack):
     44        (JSC::ActionablePredictions::packVector):
     45        * bytecode/CodeBlock.h:
     46        * bytecode/PredictionTracker.h:
     47        * dfg/DFGByteCodeParser.cpp:
     48        (JSC::DFG::ByteCodeParser::newVariableAccessData):
     49        (JSC::DFG::ByteCodeParser::getLocal):
     50        (JSC::DFG::ByteCodeParser::setLocal):
     51        (JSC::DFG::ByteCodeParser::getArgument):
     52        (JSC::DFG::ByteCodeParser::setArgument):
     53        (JSC::DFG::ByteCodeParser::parseBlock):
     54        (JSC::DFG::ByteCodeParser::processPhiStack):
     55        (JSC::DFG::ByteCodeParser::parse):
     56        * dfg/DFGDriver.cpp:
     57        (JSC::DFG::compile):
     58        * dfg/DFGGraph.cpp:
     59        (JSC::DFG::Graph::nameOfVariableAccessData):
     60        (JSC::DFG::Graph::dump):
     61        (JSC::DFG::Graph::predictArgumentTypes):
     62        * dfg/DFGGraph.h:
     63        (JSC::DFG::operandIsArgument):
     64        (JSC::DFG::VariableRecord::setFirstTime):
     65        (JSC::DFG::BasicBlock::BasicBlock):
     66        (JSC::DFG::Graph::predict):
     67        (JSC::DFG::Graph::getPrediction):
     68        * dfg/DFGJITCompiler.h:
     69        (JSC::DFG::JITCompiler::noticeOSREntry):
     70        * dfg/DFGNode.h:
     71        (JSC::DFG::Node::hasVariableAccessData):
     72        (JSC::DFG::Node::hasLocal):
     73        (JSC::DFG::Node::variableAccessData):
     74        (JSC::DFG::Node::local):
     75        * dfg/DFGOSREntry.cpp:
     76        (JSC::DFG::prepareOSREntry):
     77        * dfg/DFGOSREntry.h:
     78        * dfg/DFGPropagator.cpp:
     79        (JSC::DFG::Propagator::propagateNodePredictions):
     80        * dfg/DFGSpeculativeJIT.cpp:
     81        (JSC::DFG::ValueSource::dump):
     82        (JSC::DFG::OSRExit::OSRExit):
     83        (JSC::DFG::SpeculativeJIT::compile):
     84        (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
     85        (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
     86        * dfg/DFGSpeculativeJIT.h:
     87        (JSC::DFG::ValueSource::ValueSource):
     88        (JSC::DFG::ValueSource::forPrediction):
     89        (JSC::DFG::ValueSource::isSet):
     90        (JSC::DFG::ValueSource::kind):
     91        (JSC::DFG::ValueSource::nodeIndex):
     92        (JSC::DFG::ValueSource::nodeIndexFromKind):
     93        (JSC::DFG::ValueSource::kindFromNodeIndex):
     94        (JSC::DFG::SpeculativeJIT::isKnownArray):
     95        (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
     96        (JSC::DFG::SpeculativeJIT::SpeculativeJIT):
     97        * dfg/DFGSpeculativeJIT32_64.cpp:
     98        (JSC::DFG::OSRExit::OSRExit):
     99        (JSC::DFG::SpeculativeJIT::compile):
     100        (JSC::DFG::SpeculativeJIT::checkArgumentTypes):
     101        (JSC::DFG::SpeculativeJIT::computeValueRecoveryFor):
     102        * wtf/PackedIntVector.h: Added.
     103        (WTF::PackedIntVector::PackedIntVector):
     104        (WTF::PackedIntVector::operator=):
     105        (WTF::PackedIntVector::size):
     106        (WTF::PackedIntVector::ensureSize):
     107        (WTF::PackedIntVector::resize):
     108        (WTF::PackedIntVector::clearAll):
     109        (WTF::PackedIntVector::get):
     110        (WTF::PackedIntVector::set):
     111        (WTF::PackedIntVector::mask):
     112        * wtf/Platform.h:
     113        * wtf/UnionFind.h: Added.
     114        (WTF::UnionFind::UnionFind):
     115        (WTF::UnionFind::find):
     116        (WTF::UnionFind::unify):
     117
    11182011-09-29  Oliver Hunt  <oliver@apple.com>
    2119
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r95751 r96375  
    14311431                        >
    14321432                        <File
     1433                                RelativePath="..\..\bytecode\ActionablePrediction.h"
     1434                                >
     1435                        </File>
     1436                        <File
    14331437                                RelativePath="..\..\bytecode\CodeBlock.cpp"
    14341438                                >
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/WTF/WTF.vcproj

    r95895 r96375  
    942942                </File>
    943943                <File
     944                        RelativePath="..\..\wtf\PackedIntVector.h"
     945                        >
     946                </File>
     947                <File
    944948                        RelativePath="..\..\wtf\PageAllocation.h"
    945949                        >
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r96347 r96375  
    5050                0BDFFAE10FC6193100D69EF4 /* OwnFastMallocPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BDFFAD10FC616EC00D69EF4 /* OwnFastMallocPtr.h */; settings = {ATTRIBUTES = (Private, ); }; };
    5151                0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0BF28A2811A33DC300638F84 /* SizeLimits.cpp */; };
     52                0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; };
    5253                0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; };
    53                 0F604E8B142D696D009CEB92 /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F604E8A142D6969009CEB92 /* BitVector.cpp */; };
     54                0F636DA0142D27D700B2E66A /* PackedIntVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F636D9F142D27D200B2E66A /* PackedIntVector.h */; };
     55                0F636DA2142D27F000B2E66A /* ActionablePrediction.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F636DA1142D27ED00B2E66A /* ActionablePrediction.h */; };
    5456                0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; };
    5557                0F963B2713F753BB0002D9B2 /* RedBlackTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2613F753990002D9B2 /* RedBlackTree.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    6668                0FD3C82714115D4F00FD81CB /* DFGPropagator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3C82414115D2200FD81CB /* DFGPropagator.h */; };
    6769                0FD3C82814115D4F00FD81CB /* DFGDriver.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD3C82214115D0E00FD81CB /* DFGDriver.h */; };
     70                0FD52AAE143035A00026DC9F /* UnionFind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD52AAC1430359D0026DC9F /* UnionFind.h */; settings = {ATTRIBUTES = (Private, ); }; };
    6871                0FD82E2114172CE300179C94 /* DFGCapabilities.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */; };
    6972                0FD82E39141AB14D00179C94 /* CompactJITCodeMap.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E37141AB14200179C94 /* CompactJITCodeMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    798801                0BDFFAD40FC6171000D69EF4 /* CrossThreadRefCounted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrossThreadRefCounted.h; sourceTree = "<group>"; };
    799802                0BF28A2811A33DC300638F84 /* SizeLimits.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SizeLimits.cpp; sourceTree = "<group>"; };
     803                0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; };
    800804                0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; };
    801                 0F604E8A142D6969009CEB92 /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; };
     805                0F636D9F142D27D200B2E66A /* PackedIntVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PackedIntVector.h; sourceTree = "<group>"; };
     806                0F636DA1142D27ED00B2E66A /* ActionablePrediction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionablePrediction.h; sourceTree = "<group>"; };
    802807                0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; };
    803808                0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; };
     
    815820                0FD3C82314115D1A00FD81CB /* DFGPropagator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPropagator.cpp; path = dfg/DFGPropagator.cpp; sourceTree = "<group>"; };
    816821                0FD3C82414115D2200FD81CB /* DFGPropagator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPropagator.h; path = dfg/DFGPropagator.h; sourceTree = "<group>"; };
     822                0FD52AAC1430359D0026DC9F /* UnionFind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UnionFind.h; sourceTree = "<group>"; };
    817823                0FD82E1E14172C2F00179C94 /* DFGCapabilities.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGCapabilities.cpp; path = dfg/DFGCapabilities.cpp; sourceTree = "<group>"; };
    818824                0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCapabilities.h; path = dfg/DFGCapabilities.h; sourceTree = "<group>"; };
     
    18251831                        isa = PBXGroup;
    18261832                        children = (
    1827                                 0F604E8A142D6969009CEB92 /* BitVector.cpp */,
     1833                                0FD52AAC1430359D0026DC9F /* UnionFind.h */,
     1834                                0F636D9F142D27D200B2E66A /* PackedIntVector.h */,
     1835                                0F16D724142C39A200CF784A /* BitVector.cpp */,
    18281836                                0FD82F491428069200179C94 /* BitVector.h */,
    18291837                                C22C524813FAF6EF00B7DC0D /* dtoa */,
     
    23562364                        isa = PBXGroup;
    23572365                        children = (
     2366                                0F636DA1142D27ED00B2E66A /* ActionablePrediction.h */,
    23582367                                0FD82E8E14207A5100179C94 /* ValueProfile.cpp */,
    23592368                                0FD82E84141F3FDA00179C94 /* PredictedType.cpp */,
     
    28392848                                A70456B01427FB910037DA68 /* AllocationSpace.h in Headers */,
    28402849                                86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */,
     2850                                0F636DA0142D27D700B2E66A /* PackedIntVector.h in Headers */,
     2851                                0F636DA2142D27F000B2E66A /* ActionablePrediction.h in Headers */,
    28412852                                A7521E131429169A003C8D0C /* CardSet.h in Headers */,
     2853                                0FD52AAE143035A00026DC9F /* UnionFind.h in Headers */,
    28422854                                86880F1E14328BB900B08D42 /* DFGJITCompilerInlineMethods.h in Headers */,
    28432855                        );
     
    31543166                        buildActionMask = 2147483647;
    31553167                        files = (
     3168                                0F16D726142C39C000CF784A /* BitVector.cpp in Sources */,
    31563169                                0FD82F2C1426CA7400179C94 /* JettisonedCodeBlocks.cpp in Sources */,
    31573170                                0FD82E9014207A5F00179C94 /* ValueProfile.cpp in Sources */,
     
    33653378                                A70456B11427FB950037DA68 /* AllocationSpace.cpp in Sources */,
    33663379                                86FA9E91142BBB2E001773B7 /* JSBoundFunction.cpp in Sources */,
    3367                                 0F604E8B142D696D009CEB92 /* BitVector.cpp in Sources */,
    33683380                                86880F1C14328BB900B08D42 /* DFGJITCodeGenerator32_64.cpp in Sources */,
    33693381                                86880F1D14328BB900B08D42 /* DFGJITCompiler32_64.cpp in Sources */,
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r95930 r96375  
    241241        PassOwnPtr<CodeBlock> releaseAlternative() { return m_alternative.release(); }
    242242       
    243         void setPredictions(PassOwnPtr<PredictionTracker> predictions) { m_predictions = predictions; }
    244         PredictionTracker* predictions() const { return m_predictions.get(); }
    245 
    246243        void visitAggregate(SlotVisitor&);
    247244        void visitWeakReferences(SlotVisitor&);
     
    976973        OwnPtr<CodeBlock> m_alternative;
    977974       
    978         OwnPtr<PredictionTracker> m_predictions;
    979 
    980975        int32_t m_executeCounter;
    981976        uint32_t m_speculativeSuccessCounter;
  • trunk/Source/JavaScriptCore/bytecode/PredictionTracker.h

    r95930 r96375  
    2929#include "PredictedType.h"
    3030#include <wtf/HashMap.h>
    31 #include <wtf/Vector.h>
    3231
    3332namespace JSC {
    34 
    35 // helper function to distinguish vars & temporaries from arguments.
    36 inline bool operandIsArgument(int operand) { return operand < 0; }
    3733
    3834struct PredictionSlot {
     
    5147    }
    5248   
    53     PredictionTracker(unsigned numArguments, unsigned numVariables)
    54         : m_arguments(numArguments)
    55         , m_variables(numVariables)
    56     {
    57     }
    58    
    59     void initializeSimilarTo(const PredictionTracker& other)
    60     {
    61         m_arguments.resize(other.numberOfArguments());
    62         m_variables.resize(other.numberOfVariables());
    63     }
    64    
    65     void copyLocalsFrom(const PredictionTracker& other)
    66     {
    67         m_arguments = other.m_arguments;
    68         m_variables = other.m_variables;
    69     }
    70    
    71     size_t numberOfArguments() const { return m_arguments.size(); }
    72     size_t numberOfVariables() const { return m_variables.size(); }
    73    
    74     unsigned argumentIndexForOperand(int operand) const { return operand + m_arguments.size() + RegisterFile::CallFrameHeaderSize; }
    75 
    76     bool predictArgument(unsigned argument, PredictedType prediction)
    77     {
    78         return mergePrediction(m_arguments[argument].m_value, prediction);
    79     }
    80    
    81     bool predict(int operand, PredictedType prediction)
    82     {
    83         if (operandIsArgument(operand))
    84             return predictArgument(argumentIndexForOperand(operand), prediction);
    85         if ((unsigned)operand >= m_variables.size()) {
    86             ASSERT(operand >= 0);
    87             m_variables.resize(operand + 1);
    88         }
    89        
    90         return mergePrediction(m_variables[operand].m_value, prediction);
    91     }
    92    
    9349    bool predictGlobalVar(unsigned varNumber, PredictedType prediction)
    9450    {
     
    10359    }
    10460   
    105     PredictedType getArgumentPrediction(unsigned argument)
    106     {
    107         return m_arguments[argument].m_value;
    108     }
    109 
    110     PredictedType getPrediction(int operand)
    111     {
    112         if (operandIsArgument(operand))
    113             return getArgumentPrediction(argumentIndexForOperand(operand));
    114         if ((unsigned)operand < m_variables.size())
    115             return m_variables[operand].m_value;
    116         return PredictNone;
    117     }
    118    
    11961    PredictedType getGlobalVarPrediction(unsigned varNumber)
    12062    {
     
    12668   
    12769private:
    128     Vector<PredictionSlot, 16> m_arguments;
    129     Vector<PredictionSlot, 16> m_variables;
    13070    HashMap<unsigned, PredictionSlot> m_globalVars;
    13171};
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r96189 r96375  
    8484    // Add spill locations to nodes.
    8585    void allocateVirtualRegisters();
    86 
     86   
     87    VariableAccessData* newVariableAccessData(int operand)
     88    {
     89        ASSERT(operand < FirstConstantRegisterIndex);
     90       
     91        m_graph.m_variableAccessData.append(VariableAccessData(static_cast<VirtualRegister>(operand)));
     92        return &m_graph.m_variableAccessData.last();
     93    }
     94   
    8795    // Get/Set the operands/result of a bytecode instruction.
    8896    NodeIndex get(int operand)
     
    117125    NodeIndex getLocal(unsigned operand)
    118126    {
    119         NodeIndex nodeIndex = m_currentBlock->m_locals[operand].value;
     127        NodeIndex nodeIndex = m_currentBlock->m_localsAtTail[operand].value;
    120128
    121129        if (nodeIndex != NoNode) {
     
    130138        // expand m_preservedVars to cover these.
    131139        m_preservedVars = std::max(m_preservedVars, operand + 1);
    132 
    133         NodeIndex phi = addToGraph(Phi);
     140       
     141        VariableAccessData* variableAccessData = newVariableAccessData(operand);
     142       
     143        NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
    134144        m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, operand));
    135         nodeIndex = addToGraph(GetLocal, OpInfo(operand), phi);
    136         m_currentBlock->m_locals[operand].value = nodeIndex;
     145        nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), phi);
     146        m_currentBlock->m_localsAtTail[operand].value = nodeIndex;
     147       
     148        m_currentBlock->m_localsAtHead[operand].setFirstTime(nodeIndex);
     149       
    137150        return nodeIndex;
    138151    }
    139152    void setLocal(unsigned operand, NodeIndex value)
    140153    {
    141         m_currentBlock->m_locals[operand].value = addToGraph(SetLocal, OpInfo(operand), value);
     154        m_currentBlock->m_localsAtTail[operand].value = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value);
    142155    }
    143156
     
    148161        ASSERT(argument < m_numArguments);
    149162
    150         NodeIndex nodeIndex = m_currentBlock->m_arguments[argument].value;
     163        NodeIndex nodeIndex = m_currentBlock->m_argumentsAtTail[argument].value;
    151164
    152165        if (nodeIndex != NoNode) {
    153166            Node& node = m_graph[nodeIndex];
     167            if (node.op == SetArgument) {
     168                // We're getting an argument in the first basic block; link
     169                // the GetLocal to the SetArgument.
     170                ASSERT(node.local() == static_cast<VirtualRegister>(operand));
     171                nodeIndex = addToGraph(GetLocal, OpInfo(node.variableAccessData()), nodeIndex);
     172                m_currentBlock->m_argumentsAtTail[argument].value = nodeIndex;
     173                return nodeIndex;
     174            }
     175           
    154176            if (node.op == GetLocal)
    155177                return nodeIndex;
     178           
    156179            ASSERT(node.op == SetLocal);
    157180            return node.child1();
    158181        }
    159 
    160         NodeIndex phi = addToGraph(Phi);
     182       
     183        VariableAccessData* variableAccessData = newVariableAccessData(operand);
     184
     185        NodeIndex phi = addToGraph(Phi, OpInfo(variableAccessData));
    161186        m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, argument));
    162         nodeIndex = addToGraph(GetLocal, OpInfo(operand), phi);
    163         m_currentBlock->m_arguments[argument].value = nodeIndex;
     187        nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), phi);
     188        m_currentBlock->m_argumentsAtTail[argument].value = nodeIndex;
     189       
     190        m_currentBlock->m_argumentsAtHead[argument].setFirstTime(nodeIndex);
     191       
    164192        return nodeIndex;
    165193    }
     
    169197        ASSERT(argument < m_numArguments);
    170198
    171         m_currentBlock->m_arguments[argument].value = addToGraph(SetLocal, OpInfo(operand), value);
     199        m_currentBlock->m_argumentsAtTail[argument].value = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value);
    172200    }
    173201
     
    688716        for (unsigned i = 0; i < m_constants.size(); ++i)
    689717            m_constants[i] = ConstantRecord();
     718    }
     719   
     720    // If we are the first basic block, introduce markers for arguments. This allows
     721    // us to track if a use of an argument may use the actual argument passed, as
     722    // opposed to using a value we set explicitly.
     723    if (!m_currentIndex) {
     724        m_graph.m_arguments.resize(m_numArguments);
     725        for (unsigned argument = 0; argument < m_numArguments; ++argument) {
     726            NodeIndex setArgument = addToGraph(SetArgument, OpInfo(newVariableAccessData(argument - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize)));
     727            m_graph.m_arguments[argument] = setArgument;
     728            m_currentBlock->m_argumentsAtHead[argument].setFirstTime(setArgument);
     729            m_currentBlock->m_argumentsAtTail[argument].setFirstTime(setArgument);
     730        }
    690731    }
    691732
     
    14491490        PredecessorList& predecessors = entry.m_block->m_predecessors;
    14501491        unsigned varNo = entry.m_varNo;
     1492        VariableAccessData* dataForPhi = m_graph[entry.m_phi].variableAccessData();
    14511493
    14521494        for (size_t i = 0; i < predecessors.size(); ++i) {
    14531495            BasicBlock* predecessorBlock = m_graph.m_blocks[predecessors[i]].get();
    14541496
    1455             VariableRecord& var = (stackType == ArgumentPhiStack) ? predecessorBlock->m_arguments[varNo] : predecessorBlock->m_locals[varNo];
     1497            VariableRecord& var = (stackType == ArgumentPhiStack) ? predecessorBlock->m_argumentsAtTail[varNo] : predecessorBlock->m_localsAtTail[varNo];
    14561498
    14571499            NodeIndex valueInPredecessor = var.value;
    14581500            if (valueInPredecessor == NoNode) {
    1459                 valueInPredecessor = addToGraph(Phi);
    1460                 var.value = valueInPredecessor;
     1501                valueInPredecessor = addToGraph(Phi, OpInfo(newVariableAccessData(stackType == ArgumentPhiStack ? varNo - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize : varNo)));
     1502                var.setFirstTime(valueInPredecessor);
     1503                if (stackType == ArgumentPhiStack)
     1504                    predecessorBlock->m_argumentsAtHead[varNo].setFirstTime(valueInPredecessor);
     1505                else
     1506                    predecessorBlock->m_localsAtHead[varNo].setFirstTime(valueInPredecessor);
    14611507                phiStack.append(PhiStackEntry(predecessorBlock, valueInPredecessor, varNo));
    1462             } else if (m_graph[valueInPredecessor].op == GetLocal)
     1508            } else if (m_graph[valueInPredecessor].op == GetLocal) {
     1509                // We want to ensure that the VariableAccessDatas are identical between the
     1510                // GetLocal and its block-local Phi. Strictly speaking we only need the two
     1511                // to be unified. But for efficiency, we want the code that creates GetLocals
     1512                // and Phis to try to reuse VariableAccessDatas as much as possible.
     1513                ASSERT(m_graph[valueInPredecessor].variableAccessData() == m_graph[m_graph[valueInPredecessor].child1()].variableAccessData());
     1514               
    14631515                valueInPredecessor = m_graph[valueInPredecessor].child1();
    1464             ASSERT(m_graph[valueInPredecessor].op == SetLocal || m_graph[valueInPredecessor].op == Phi);
     1516            }
     1517            ASSERT(m_graph[valueInPredecessor].op == SetLocal || m_graph[valueInPredecessor].op == Phi || (m_graph[valueInPredecessor].op == SetArgument && stackType == ArgumentPhiStack));
     1518           
     1519            VariableAccessData* dataForPredecessor = m_graph[valueInPredecessor].variableAccessData();
     1520           
     1521            dataForPredecessor->unify(dataForPhi);
    14651522
    14661523            Node* phiNode = &m_graph[entry.m_phi];
     
    14801537                continue;
    14811538            }
    1482 
    1483             NodeIndex newPhi = addToGraph(Phi);
     1539           
     1540            NodeIndex newPhi = addToGraph(Phi, OpInfo(dataForPhi));
    14841541           
    14851542            phiNode = &m_graph[entry.m_phi]; // reload after vector resize
     
    15491606   
    15501607    m_graph.m_preservedVars = m_preservedVars;
     1608    m_graph.m_localVars = m_numLocals;
    15511609    m_graph.m_parameterSlots = m_parameterSlots;
    15521610
  • trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp

    r95901 r96375  
    3939{
    4040    JSGlobalData* globalData = &exec->globalData();
    41     Graph dfg(codeBlock->m_numParameters, codeBlock->m_numVars);
     41    Graph dfg;
    4242    if (!parse(dfg, globalData, codeBlock))
    4343        return false;
     
    4747   
    4848    propagate(dfg, globalData, codeBlock);
    49    
    50     // Save the predictions we've made, so that OSR entry can verify them. Predictions
    51     // are saved in the CodeBlock from which we will be doing OSR entry, since the
    52     // CodeBlock to which we are OSRing may be replaced at any time.
    53     OwnPtr<PredictionTracker> predictions = adoptPtr(new PredictionTracker());
    54     *predictions = dfg.predictions();
    55     ASSERT(codeBlock->alternative());
    56     ASSERT(codeBlock->alternative()->getJITType() == JITCode::BaselineJIT);
    57     codeBlock->alternative()->setPredictions(predictions.release());
    5849   
    5950    JITCompiler dataFlowJIT(globalData, dfg, codeBlock);
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r95930 r96375  
    4545{
    4646    return dfgOpNames[op & NodeIdMask];
     47}
     48
     49const char* Graph::nameOfVariableAccessData(VariableAccessData* variableAccessData)
     50{
     51    // Variables are already numbered. For readability of IR dumps, this returns
     52    // an alphabetic name for the variable access data, so that you don't have to
     53    // reason about two numbers (variable number and live range number), but instead
     54    // a number and a letter.
     55   
     56    unsigned index = std::numeric_limits<unsigned>::max();
     57    for (unsigned i = 0; i < m_variableAccessData.size(); ++i) {
     58        if (&m_variableAccessData[i] == variableAccessData) {
     59            index = i;
     60            break;
     61        }
     62    }
     63   
     64    ASSERT(index != std::numeric_limits<unsigned>::max());
     65   
     66    if (!index)
     67        return "A";
     68
     69    static char buf[10];
     70    BoundsCheckedPointer<char> ptr(buf, sizeof(buf));
     71   
     72    while (index) {
     73        *ptr++ = 'A' + (index % 26);
     74        index /= 26;
     75    }
     76   
     77    *ptr++ = 0;
     78   
     79    return buf;
    4780}
    4881
     
    117150        hasPrinted = true;
    118151    }
    119     if (node.hasLocal()) {
    120         int local = node.local();
    121         if (operandIsArgument(local))
    122             printf("%sarg%u", hasPrinted ? ", " : "", local - codeBlock->thisRegister());
     152    ASSERT(node.hasVariableAccessData() == node.hasLocal());
     153    if (node.hasVariableAccessData()) {
     154        VariableAccessData* variableAccessData = node.variableAccessData();
     155        int operand = variableAccessData->operand();
     156        if (operandIsArgument(operand))
     157            printf("%sarg%u(%s)", hasPrinted ? ", " : "", operand - codeBlock->thisRegister(), nameOfVariableAccessData(variableAccessData));
    123158        else
    124             printf("%sr%u", hasPrinted ? ", " : "", local);
     159            printf("%sr%u(%s)", hasPrinted ? ", " : "", operand, nameOfVariableAccessData(variableAccessData));
    125160        hasPrinted = true;
    126161    }
     
    146181
    147182    if (!skipped) {
    148         if (node.hasLocal())
    149             printf("  predicting %s", predictionToString(getPrediction(node.local())));
     183        if (node.hasVariableAccessData())
     184            printf("  predicting %s", predictionToString(node.variableAccessData()->prediction()));
    150185        else if (node.hasVarNumber())
    151186            printf("  predicting %s", predictionToString(getGlobalVarPrediction(node.varNumber())));
     
    205240{
    206241    if (exec) {
    207         size_t numberOfArguments = std::min(exec->argumentCountIncludingThis(), m_predictions.numberOfArguments());
     242        size_t numberOfArguments = std::min(exec->argumentCountIncludingThis(), m_arguments.size());
    208243       
    209244        for (size_t arg = 1; arg < numberOfArguments; ++arg)
    210             m_predictions.predictArgument(arg, predictionFromValue(exec->argument(arg - 1)));
     245            at(m_arguments[arg]).variableAccessData()->predict(predictionFromValue(exec->argument(arg - 1)));
    211246    }
    212247   
     
    221256            continue;
    222257       
    223         m_predictions.predictArgument(arg, profile->computeUpdatedPrediction());
     258        at(m_arguments[arg]).variableAccessData()->predict(profile->computeUpdatedPrediction());
    224259       
    225260#if ENABLE(DFG_DEBUG_VERBOSE)
    226         printf("Argument [%lu] prediction: %s\n", arg, predictionToString(m_predictions.getArgumentPrediction(arg)));
     261        printf("Argument [%lu] prediction: %s\n", arg, predictionToString(at(m_arguments[arg]).variableAccessData()->prediction()));
    227262#endif
    228263    }
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r95930 r96375  
    4444namespace DFG {
    4545
     46// helper function to distinguish vars & temporaries from arguments.
     47inline bool operandIsArgument(int operand) { return operand < 0; }
     48
    4649typedef uint32_t BlockIndex;
    4750
     
    5356        : value(NoNode)
    5457    {
     58    }
     59   
     60    void setFirstTime(NodeIndex nodeIndex)
     61    {
     62        ASSERT(value == NoNode);
     63        value = nodeIndex;
    5564    }
    5665
     
    111120        , end(NoNode)
    112121        , isOSRTarget(false)
    113         , m_arguments(numArguments)
    114         , m_locals(numLocals)
     122        , m_argumentsAtHead(numArguments)
     123        , m_localsAtHead(numLocals)
     124        , m_argumentsAtTail(numArguments)
     125        , m_localsAtTail(numLocals)
    115126    {
    116127    }
     
    127138
    128139    PredecessorList m_predecessors;
    129     Vector <VariableRecord, 8> m_arguments;
    130     Vector <VariableRecord, 16> m_locals;
     140   
     141    Vector<VariableRecord, 8> m_argumentsAtHead;
     142    Vector<VariableRecord, 16> m_localsAtHead;
     143   
     144    Vector<VariableRecord, 8> m_argumentsAtTail;
     145    Vector<VariableRecord, 16> m_localsAtTail;
    131146};
    132147
     
    139154class Graph : public Vector<Node, 64> {
    140155public:
    141     Graph(unsigned numArguments, unsigned numVariables)
    142         : m_predictions(numArguments, numVariables)
    143     {
    144     }
    145 
    146156    // Mark a node as being referenced.
    147157    void ref(NodeIndex nodeIndex)
     
    172182    }
    173183   
    174     PredictionTracker& predictions()
    175     {
    176         return m_predictions;
    177     }
    178    
    179     bool predict(int operand, PredictedType prediction)
    180     {
    181         return m_predictions.predict(operand, prediction);
    182     }
    183    
    184184    bool predictGlobalVar(unsigned varNumber, PredictedType prediction)
    185185    {
     
    191191        switch (node.op) {
    192192        case GetLocal:
    193             return predict(node.local(), prediction);
    194             break;
     193        case SetLocal:
     194        case Phi:
     195        case SetArgument:
     196            return node.variableAccessData()->predict(prediction);
    195197        case GetGlobalVar:
    196198            return predictGlobalVar(node.varNumber(), prediction);
    197             break;
    198199        case GetById:
    199200        case GetMethod:
     
    213214    }
    214215
    215     PredictedType getPrediction(int operand)
    216     {
    217         return m_predictions.getPrediction(operand);
    218     }
    219    
    220216    PredictedType getGlobalVarPrediction(unsigned varNumber)
    221217    {
     
    245241        switch (nodePtr->op) {
    246242        case GetLocal:
    247             return getPrediction(nodePtr->local());
     243        case SetLocal:
     244        case SetArgument:
     245        case Phi:
     246            return nodePtr->variableAccessData()->prediction();
    248247        case GetGlobalVar:
    249248            return getGlobalVarPrediction(nodePtr->varNumber());
     
    325324#ifndef NDEBUG
    326325    static const char *opName(NodeType);
     326   
     327    // This is O(n), and should only be used for verbose dumps.
     328    const char* nameOfVariableAccessData(VariableAccessData*);
    327329#endif
    328330
     
    334336    Vector<StorageAccessData> m_storageAccessData;
    335337    Vector<ResolveGlobalData> m_resolveGlobalData;
     338    Vector<NodeIndex, 8> m_arguments;
     339    SegmentedVector<VariableAccessData, 16> m_variableAccessData;
    336340    unsigned m_preservedVars;
     341    unsigned m_localVars;
    337342    unsigned m_parameterSlots;
    338343private:
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.cpp

    r95933 r96375  
    577577    // Link the code, populate data in CodeBlock data structures.
    578578#if ENABLE(DFG_DEBUG_VERBOSE)
    579     fprintf(stderr, "JIT code for %p start at [%p, %p)\n", m_codeBlock, linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize());
     579    fprintf(stderr, "JIT code for %p start at [%p, %p). Size = %lu.\n", m_codeBlock, linkBuffer.debugAddress(), static_cast<char*>(linkBuffer.debugAddress()) + linkBuffer.debugSize(), linkBuffer.debugSize());
    580580#endif
    581581
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r96171 r96375  
    394394        OSREntryData* entry = codeBlock()->appendDFGOSREntryData(basicBlock.bytecodeBegin, differenceBetween(m_startOfCode, label()));
    395395       
    396         unsigned lastLiveArgument = 0;
    397         unsigned lastLiveLocal = 0;
     396        ActionablePredictions actionablePredictions(basicBlock.m_argumentsAtHead.size(), basicBlock.m_localsAtHead.size());
     397
     398        for (unsigned i = 0; i < basicBlock.m_argumentsAtHead.size(); ++i) {
     399            NodeIndex nodeIndex = basicBlock.m_argumentsAtHead[i].value;
     400            if (nodeIndex != NoNode)
     401                actionablePredictions.setArgument(i, actionablePredictionFromPredictedType(m_graph[nodeIndex].variableAccessData()->prediction()));
     402        }
    398403       
    399         for (unsigned i = 0; i < basicBlock.m_arguments.size(); ++i) {
    400             if (basicBlock.m_arguments[i].value != NoNode)
    401                 lastLiveArgument = i;
     404        for (unsigned i = 0; i < basicBlock.m_localsAtHead.size(); ++i) {
     405            NodeIndex nodeIndex = basicBlock.m_localsAtHead[i].value;
     406            if (nodeIndex != NoNode)
     407                actionablePredictions.setVariable(i, actionablePredictionFromPredictedType(m_graph[nodeIndex].variableAccessData()->prediction()));
    402408        }
    403409       
    404         for (unsigned i = 0; i < basicBlock.m_locals.size(); ++i) {
    405             if (basicBlock.m_locals[i].value != NoNode)
    406                 lastLiveLocal = i;
    407         }
     410        actionablePredictions.pack();
    408411       
    409         if (lastLiveArgument) {
    410             entry->m_liveArguments.resize(lastLiveArgument + 1);
    411             entry->m_liveArguments.clearAll();
    412            
    413             for (unsigned i = 0; i <= lastLiveArgument; ++i) {
    414                 if (basicBlock.m_arguments[i].value != NoNode)
    415                     entry->m_liveArguments.set(i);
    416             }
    417         } else
    418             entry->m_liveArguments.clearAll();
    419        
    420         if (lastLiveLocal) {
    421             entry->m_liveVariables.resize(lastLiveLocal + 1);
    422             entry->m_liveVariables.clearAll();
    423            
    424             for (unsigned i = 0; i <= lastLiveLocal; ++i) {
    425                 if (basicBlock.m_locals[i].value != NoNode)
    426                     entry->m_liveVariables.set(i);
    427             }
    428         } else
    429             entry->m_liveVariables.clearAll();
     412        entry->m_predictions = actionablePredictions;
    430413#else
    431414        UNUSED_PARAM(basicBlock);
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r96309 r96375  
    2929#include <wtf/BoundsCheckedPointer.h>
    3030#include <wtf/Platform.h>
     31#include <wtf/UnionFind.h>
    3132
    3233// Emit various logging information for debugging, including dumping the dataflow graphs.
     
    109110};
    110111
     112class VariableAccessData: public UnionFind<VariableAccessData> {
     113public:
     114    VariableAccessData()
     115        : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))
     116        , m_prediction(PredictNone)
     117    {
     118    }
     119   
     120    VariableAccessData(VirtualRegister local)
     121        : m_local(local)
     122        , m_prediction(PredictNone)
     123    {
     124    }
     125   
     126    VirtualRegister local()
     127    {
     128        ASSERT(m_local == find()->m_local);
     129        return m_local;
     130    }
     131   
     132    int operand()
     133    {
     134        return static_cast<int>(local());
     135    }
     136   
     137    bool predict(PredictedType prediction)
     138    {
     139        return mergePrediction(find()->m_prediction, prediction);
     140    }
     141   
     142    PredictedType prediction()
     143    {
     144        return find()->m_prediction;
     145    }
     146   
     147private:
     148    // This is slightly space-inefficient, since anything we're unified with
     149    // will have the same operand and should have the same prediction. But
     150    // putting them here simplifies the code, and we don't expect DFG space
     151    // usage for variable access nodes do be significant.
     152
     153    VirtualRegister m_local;
     154    PredictedType m_prediction;
     155};
     156
    111157typedef unsigned ArithNodeFlags;
    112158#define NodeUseBottom      0x00
     
    223269    macro(Phantom, NodeMustGenerate) \
    224270    macro(Phi, 0) \
     271    \
     272    /* Marker for arguments being set. */\
     273    macro(SetArgument, 0) \
    225274    \
    226275    /* Nodes for bitwise operations. */\
     
    465514    }
    466515   
     516    bool hasVariableAccessData()
     517    {
     518        switch (op) {
     519        case GetLocal:
     520        case SetLocal:
     521        case Phi:
     522        case SetArgument:
     523            return true;
     524        default:
     525            return false;
     526        }
     527    }
     528   
    467529    bool hasLocal()
    468530    {
    469         return op == GetLocal || op == SetLocal;
    470     }
    471 
     531        return hasVariableAccessData();
     532    }
     533   
     534    VariableAccessData* variableAccessData()
     535    {
     536        return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
     537    }
     538   
    472539    VirtualRegister local()
    473540    {
    474         ASSERT(hasLocal());
    475         return (VirtualRegister)m_opInfo;
     541        return variableAccessData()->local();
    476542    }
    477543
  • trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp

    r95901 r96375  
    3636namespace JSC { namespace DFG {
    3737
    38 inline bool predictionIsValid(JSGlobalData* globalData, JSValue value, PredictedType type)
    39 {
    40     // this takes into account only local variable predictions that get enforced
    41     // on SetLocal.
    42    
    43     if (isInt32Prediction(type))
    44         return value.isInt32();
    45    
    46     if (isArrayPrediction(type))
    47         return isJSArray(globalData, value);
    48    
    49     if (isBooleanPrediction(type))
    50         return value.isBoolean();
    51    
    52     return true;
    53 }
    54 
    5538void* prepareOSREntry(ExecState* exec, CodeBlock* codeBlock, unsigned bytecodeIndex)
    5639{
     
    6750   
    6851    JSGlobalData* globalData = &exec->globalData();
    69     CodeBlock* baselineCodeBlock = codeBlock->alternative();
    7052    OSREntryData* entry = codeBlock->dfgOSREntryDataForBytecodeIndex(bytecodeIndex);
    7153   
     
    9678    //    OSR at this time.
    9779   
    98     PredictionTracker* predictions = baselineCodeBlock->predictions();
    99    
    100     if (predictions->numberOfArguments() > exec->argumentCountIncludingThis())
    101         return 0;
    102    
    103     for (unsigned i = 1; i < predictions->numberOfArguments(); ++i) {
    104         if (i < entry->m_liveArguments.size() && entry->m_liveArguments.get(i)
    105             && !predictionIsValid(globalData, exec->argument(i - 1), predictions->getArgumentPrediction(i))) {
     80    for (unsigned i = 1; i < entry->m_predictions.argumentUpperBound(); ++i) {
     81        ActionablePrediction prediction = entry->m_predictions.argument(i);
     82        if (prediction == NoActionablePrediction)
     83            continue;
     84
     85        if (i >= exec->argumentCountIncludingThis()) {
    10686#if ENABLE(JIT_VERBOSE_OSR)
    107             printf("    OSR failed because argument %u is %s, expected %s.\n", i, exec->argument(i - 1).description(), predictionToString(predictions->getArgumentPrediction(i)));
     87            printf("    OSR failed because argument %u was not passed, expected %s.\n", i, actionablePredictionToString(prediction));
     88#endif
     89            return 0;
     90        }
     91       
     92        if (!valueObeysPrediction(globalData, exec->argument(i - 1), prediction)) {
     93#if ENABLE(JIT_VERBOSE_OSR)
     94            printf("    OSR failed because argument %u is %s, expected %s.\n", i, exec->argument(i - 1).description(), actionablePredictionToString(prediction));
    10895#endif
    10996            return 0;
     
    11198    }
    11299   
    113     for (unsigned i = 0; i < predictions->numberOfVariables(); ++i) {
    114         if (i < entry->m_liveVariables.size() && entry->m_liveVariables.get(i)
    115             && !predictionIsValid(globalData, exec->registers()[i].jsValue(), predictions->getPrediction(i))) {
     100    for (unsigned i = 0; i < entry->m_predictions.variableUpperBound(); ++i) {
     101        ActionablePrediction prediction = entry->m_predictions.variable(i);
     102        if (prediction == NoActionablePrediction)
     103            continue;
     104       
     105        if (!valueObeysPrediction(globalData, exec->registers()[i].jsValue(), prediction)) {
    116106#if ENABLE(JIT_VERBOSE_OSR)
    117             printf("    OSR failed because variable %u is %s, expected %s.\n", i, exec->registers()[i].jsValue().description(), predictionToString(predictions->getPrediction(i)));
     107            printf("    OSR failed because variable %u is %s, expected %s.\n", i, exec->registers()[i].jsValue().description(), actionablePredictionToString(prediction));
    118108#endif
    119109            return 0;
     
    130120    if (!globalData->interpreter->registerFile().grow(&exec->registers()[codeBlock->m_numCalleeRegisters])) {
    131121#if ENABLE(JIT_VERBOSE_OSR)
    132         printf("    OSR failed because stack growth failed..\n");
     122        printf("    OSR failed because stack growth failed.\n");
    133123#endif
    134124        return 0;
  • trunk/Source/JavaScriptCore/dfg/DFGOSREntry.h

    r95901 r96375  
    2727#define DFGOSREntry_h
    2828
    29 #include <wtf/BitVector.h>
     29#include "ActionablePrediction.h"
    3030
    3131namespace JSC {
     
    4040    unsigned m_bytecodeIndex;
    4141    unsigned m_machineCodeOffset;
    42     BitVector m_liveArguments;
    43     BitVector m_liveVariables;
     42    ActionablePredictions m_predictions;
    4443};
    4544
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r96189 r96375  
    320320           
    321321        case GetLocal: {
    322             PredictedType prediction = m_graph.getPrediction(node.local());
     322            PredictedType prediction = node.variableAccessData()->prediction();
    323323            if (prediction)
    324324                changed |= mergePrediction(prediction);
     
    327327           
    328328        case SetLocal: {
    329             changed |= m_graph.predict(node.local(), m_predictions[node.child1()]);
     329            changed |= node.variableAccessData()->predict(m_predictions[node.child1()]);
    330330            break;
    331331        }
     
    473473           
    474474        case ConvertThis: {
    475             changed |= setPrediction(PredictObjectUnknown);
     475            PredictedType prediction = m_predictions[node.child1()];
     476            if (prediction) {
     477                if (prediction & ~PredictObjectMask) {
     478                    prediction &= ~PredictObjectMask;
     479                    prediction |= PredictObjectUnknown;
     480                }
     481                changed |= mergePrediction(prediction);
     482            }
    476483            break;
    477484        }
     
    572579        case ThrowReferenceError:
    573580        case ForceOSRExit:
    574             break;
    575            
    576         // This gets ignored because it doesn't do anything.
    577         case Phantom:
     581        case SetArgument:
    578582        case PutByVal:
    579583        case PutByValAlias:
    580584        case PutById:
    581585        case PutByIdDirect:
     586            break;
     587           
     588        // This gets ignored because it doesn't do anything.
     589        case Phantom:
    582590            break;
    583591#else
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r96306 r96375  
    156156void ValueSource::dump(FILE* out) const
    157157{
    158     fprintf(out, "Node(%d)", m_nodeIndex);
     158    switch (kind()) {
     159    case SourceNotSet:
     160        fprintf(out, "NotSet");
     161        break;
     162    case ValueInRegisterFile:
     163        fprintf(out, "InRegFile");
     164        break;
     165    case Int32InRegisterFile:
     166        fprintf(out, "Int32");
     167        break;
     168    case HaveNode:
     169        fprintf(out, "Node(%d)", m_nodeIndex);
     170        break;
     171    }
    159172}
    160173
     
    204217    ASSERT(m_bytecodeIndex != std::numeric_limits<uint32_t>::max());
    205218    for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
    206         m_arguments[argument] = jit->computeValueRecoveryFor(operandForArgument(argument), jit->m_arguments[argument]);
     219        m_arguments[argument] = jit->computeValueRecoveryFor(jit->m_arguments[argument]);
    207220    for (unsigned variable = 0; variable < m_variables.size(); ++variable)
    208         m_variables[variable] = jit->computeValueRecoveryFor(variable, jit->m_variables[variable]);
     221        m_variables[variable] = jit->computeValueRecoveryFor(jit->m_variables[variable]);
    209222}
    210223
     
    723736
    724737    case GetLocal: {
    725         PredictedType prediction = m_jit.graph().getPrediction(node.local());
     738        PredictedType prediction = node.variableAccessData()->prediction();
    726739
    727740        // If we have no prediction for this local, then don't attempt to compile.
     
    798811        m_bytecodeIndexForOSR = nextNode.codeOrigin.bytecodeIndex();
    799812       
    800         PredictedType predictedType = m_jit.graph().getPrediction(node.local());
     813        PredictedType predictedType = node.variableAccessData()->prediction();
    801814        if (isInt32Prediction(predictedType)) {
    802815            SpeculateIntegerOperand value(this, node.child1());
     
    821834        // Indicate that it's no longer necessary to retrieve the value of
    822835        // this bytecode variable from registers or other locations in the register file.
    823         valueSourceReferenceForOperand(node.local()) = ValueSource();
    824         break;
    825     }
     836        valueSourceReferenceForOperand(node.local()) = ValueSource::forPrediction(predictedType);
     837        break;
     838    }
     839       
     840    case SetArgument:
     841        // This is a no-op; it just marks the fact that the argument is being used.
     842        // But it may be profitable to use this as a hook to run speculation checks
     843        // on arguments, thereby allowing us to trivially eliminate such checks if
     844        // the argument is not used.
     845        break;
    826846
    827847    case BitAnd:
     
    22022222#endif
    22032223   
    2204     for (size_t i = 0; i < m_arguments.size(); ++i)
    2205         m_arguments[i] = ValueSource();
    2206     for (size_t i = 0; i < m_variables.size(); ++i)
    2207         m_variables[i] = ValueSource();
     2224    ASSERT(m_arguments.size() == block.m_argumentsAtHead.size());
     2225    for (size_t i = 0; i < m_arguments.size(); ++i) {
     2226        NodeIndex nodeIndex = block.m_argumentsAtHead[i].value;
     2227        if (nodeIndex == NoNode)
     2228            m_arguments[i] = ValueSource(ValueInRegisterFile);
     2229        else
     2230            m_arguments[i] = ValueSource::forPrediction(m_jit.graph()[nodeIndex].variableAccessData()->prediction());
     2231    }
     2232   
     2233    ASSERT(m_variables.size() == block.m_localsAtHead.size());
     2234    for (size_t i = 0; i < m_variables.size(); ++i) {
     2235        NodeIndex nodeIndex = block.m_localsAtHead[i].value;
     2236        if (nodeIndex == NoNode)
     2237            m_variables[i] = ValueSource(ValueInRegisterFile);
     2238        else
     2239            m_variables[i] = ValueSource::forPrediction(m_jit.graph()[nodeIndex].variableAccessData()->prediction());
     2240    }
     2241   
    22082242    m_lastSetOperand = std::numeric_limits<int>::max();
    22092243    m_bytecodeIndexForOSR = std::numeric_limits<uint32_t>::max();
     
    22762310    ASSERT(!m_compileIndex);
    22772311    m_bytecodeIndexForOSR = 0;
     2312
     2313    for (size_t i = 0; i < m_arguments.size(); ++i)
     2314        m_arguments[i] = ValueSource(ValueInRegisterFile);
     2315    for (size_t i = 0; i < m_variables.size(); ++i)
     2316        m_variables[i] = ValueSource(ValueInRegisterFile);
     2317   
    22782318    for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
    22792319        VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
    2280         PredictedType predictedType = m_jit.graph().getPrediction(virtualRegister);
     2320        PredictedType predictedType = m_jit.graph()[m_jit.graph().m_arguments[i]].variableAccessData()->prediction();
    22812321        if (isInt32Prediction(predictedType))
    22822322            speculationCheck(m_jit.branchPtr(MacroAssembler::Below, JITCompiler::addressFor(virtualRegister), GPRInfo::tagTypeNumberRegister));
     
    23062346}
    23072347
    2308 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(int operand, const ValueSource& valueSource)
     2348ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
    23092349{
    2310     if (!valueSource.isSet()) {
    2311         if (m_bytecodeIndexForOSR && isInt32Prediction(m_jit.graph().getPrediction(operand)))
    2312             return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
     2350    switch (valueSource.kind()) {
     2351    case ValueInRegisterFile:
    23132352        return ValueRecovery::alreadyInRegisterFile();
    2314     }
    2315 
    2316     if (m_jit.isConstant(valueSource.nodeIndex()))
    2317         return ValueRecovery::constant(m_jit.valueOfJSConstant(valueSource.nodeIndex()));
    2318    
    2319     Node* nodePtr = &m_jit.graph()[valueSource.nodeIndex()];
    2320     if (!nodePtr->shouldGenerate()) {
    2321         // It's legitimately dead. As in, nobody will ever use this node, or operand,
    2322         // ever. Set it to Undefined to make the GC happy after the OSR.
    2323         return ValueRecovery::constant(jsUndefined());
    2324     }
    2325    
    2326     GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2327     if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
    2328         // Try to see if there is an alternate node that would contain the value we want.
    2329         // There are four possibilities:
    2330         //
    2331         // ValueToNumber: If the only live version of the value is a ValueToNumber node
    2332         //    then it means that all remaining uses of the value would have performed a
    2333         //    ValueToNumber conversion anyway. Thus, we can substitute ValueToNumber.
    2334         //
    2335         // ValueToInt32: Likewise, if the only remaining live version of the value is
    2336         //    ValueToInt32, then we can use it. But if there is both a ValueToInt32
    2337         //    and a ValueToNumber, then we better go with ValueToNumber because it
    2338         //    means that some remaining uses would have converted to number while
    2339         //    others would have converted to Int32.
    2340         //
    2341         // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
    2342         //    then the only remaining uses are ones that want a properly formed number
    2343         //    rather than a UInt32 intermediate.
    2344         //
    2345         // The reverse of the above: This node could be a UInt32ToNumber, but its
    2346         //    alternative is still alive. This means that the only remaining uses of
    2347         //    the number would be fine with a UInt32 intermediate.
    2348        
    2349         bool found = false;
    2350        
    2351         if (nodePtr->op == UInt32ToNumber) {
    2352             NodeIndex nodeIndex = nodePtr->child1();
    2353             nodePtr = &m_jit.graph()[nodeIndex];
    2354             infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2355             if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
    2356                 found = true;
    2357         }
    2358        
    2359         if (!found) {
    2360             NodeIndex valueToNumberIndex = NoNode;
    2361             NodeIndex valueToInt32Index = NoNode;
    2362             NodeIndex uint32ToNumberIndex = NoNode;
    2363            
    2364             for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
    2365                 GenerationInfo& info = m_generationInfo[virtualRegister];
    2366                 if (!info.alive())
    2367                     continue;
    2368                 if (info.nodeIndex() == NoNode)
    2369                     continue;
    2370                 Node& node = m_jit.graph()[info.nodeIndex()];
    2371                 if (node.child1Unchecked() != valueSource.nodeIndex())
    2372                     continue;
    2373                 switch (node.op) {
    2374                 case ValueToNumber:
    2375                 case ValueToDouble:
    2376                     valueToNumberIndex = info.nodeIndex();
    2377                     break;
    2378                 case ValueToInt32:
    2379                     valueToInt32Index = info.nodeIndex();
    2380                     break;
    2381                 case UInt32ToNumber:
    2382                     uint32ToNumberIndex = info.nodeIndex();
    2383                     break;
    2384                 default:
    2385                     break;
     2353       
     2354    case Int32InRegisterFile:
     2355        return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
     2356       
     2357    case HaveNode: {
     2358        if (m_jit.isConstant(valueSource.nodeIndex()))
     2359            return ValueRecovery::constant(m_jit.valueOfJSConstant(valueSource.nodeIndex()));
     2360   
     2361        Node* nodePtr = &m_jit.graph()[valueSource.nodeIndex()];
     2362        if (!nodePtr->shouldGenerate()) {
     2363            // It's legitimately dead. As in, nobody will ever use this node, or operand,
     2364            // ever. Set it to Undefined to make the GC happy after the OSR.
     2365            return ValueRecovery::constant(jsUndefined());
     2366        }
     2367   
     2368        GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
     2369        if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
     2370            // Try to see if there is an alternate node that would contain the value we want.
     2371            // There are four possibilities:
     2372            //
     2373            // ValueToNumber: If the only live version of the value is a ValueToNumber node
     2374            //    then it means that all remaining uses of the value would have performed a
     2375            //    ValueToNumber conversion anyway. Thus, we can substitute ValueToNumber.
     2376            //
     2377            // ValueToInt32: Likewise, if the only remaining live version of the value is
     2378            //    ValueToInt32, then we can use it. But if there is both a ValueToInt32
     2379            //    and a ValueToNumber, then we better go with ValueToNumber because it
     2380            //    means that some remaining uses would have converted to number while
     2381            //    others would have converted to Int32.
     2382            //
     2383            // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
     2384            //    then the only remaining uses are ones that want a properly formed number
     2385            //    rather than a UInt32 intermediate.
     2386            //
     2387            // The reverse of the above: This node could be a UInt32ToNumber, but its
     2388            //    alternative is still alive. This means that the only remaining uses of
     2389            //    the number would be fine with a UInt32 intermediate.
     2390       
     2391            bool found = false;
     2392       
     2393            if (nodePtr->op == UInt32ToNumber) {
     2394                NodeIndex nodeIndex = nodePtr->child1();
     2395                nodePtr = &m_jit.graph()[nodeIndex];
     2396                infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
     2397                if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
     2398                    found = true;
     2399            }
     2400       
     2401            if (!found) {
     2402                NodeIndex valueToNumberIndex = NoNode;
     2403                NodeIndex valueToInt32Index = NoNode;
     2404                NodeIndex uint32ToNumberIndex = NoNode;
     2405           
     2406                for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
     2407                    GenerationInfo& info = m_generationInfo[virtualRegister];
     2408                    if (!info.alive())
     2409                        continue;
     2410                    if (info.nodeIndex() == NoNode)
     2411                        continue;
     2412                    Node& node = m_jit.graph()[info.nodeIndex()];
     2413                    if (node.child1Unchecked() != valueSource.nodeIndex())
     2414                        continue;
     2415                    switch (node.op) {
     2416                    case ValueToNumber:
     2417                    case ValueToDouble:
     2418                        valueToNumberIndex = info.nodeIndex();
     2419                        break;
     2420                    case ValueToInt32:
     2421                        valueToInt32Index = info.nodeIndex();
     2422                        break;
     2423                    case UInt32ToNumber:
     2424                        uint32ToNumberIndex = info.nodeIndex();
     2425                        break;
     2426                    default:
     2427                        break;
     2428                    }
     2429                }
     2430           
     2431                NodeIndex nodeIndexToUse;
     2432                if (valueToNumberIndex != NoNode)
     2433                    nodeIndexToUse = valueToNumberIndex;
     2434                else if (valueToInt32Index != NoNode)
     2435                    nodeIndexToUse = valueToInt32Index;
     2436                else if (uint32ToNumberIndex != NoNode)
     2437                    nodeIndexToUse = uint32ToNumberIndex;
     2438                else
     2439                    nodeIndexToUse = NoNode;
     2440           
     2441                if (nodeIndexToUse != NoNode) {
     2442                    nodePtr = &m_jit.graph()[nodeIndexToUse];
     2443                    infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
     2444                    ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
     2445                    found = true;
    23862446                }
    23872447            }
    2388            
    2389             NodeIndex nodeIndexToUse;
    2390             if (valueToNumberIndex != NoNode)
    2391                 nodeIndexToUse = valueToNumberIndex;
    2392             else if (valueToInt32Index != NoNode)
    2393                 nodeIndexToUse = valueToInt32Index;
    2394             else if (uint32ToNumberIndex != NoNode)
    2395                 nodeIndexToUse = uint32ToNumberIndex;
    2396             else
    2397                 nodeIndexToUse = NoNode;
    2398            
    2399             if (nodeIndexToUse != NoNode) {
    2400                 nodePtr = &m_jit.graph()[nodeIndexToUse];
    2401                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2402                 ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
    2403                 found = true;
    2404             }
    2405         }
    2406        
    2407         if (!found)
    2408             return ValueRecovery::constant(jsUndefined());
    2409     }
    2410    
    2411     ASSERT(infoPtr->alive());
    2412 
    2413     if (infoPtr->registerFormat() != DataFormatNone) {
    2414         if (infoPtr->registerFormat() == DataFormatDouble)
    2415             return ValueRecovery::inFPR(infoPtr->fpr());
    2416         return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
    2417     }
    2418     if (infoPtr->spillFormat() != DataFormatNone)
    2419         return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()));
    2420    
    2421     ASSERT_NOT_REACHED();
    2422     return ValueRecovery();
     2448       
     2449            if (!found)
     2450                return ValueRecovery::constant(jsUndefined());
     2451        }
     2452   
     2453        ASSERT(infoPtr->alive());
     2454
     2455        if (infoPtr->registerFormat() != DataFormatNone) {
     2456            if (infoPtr->registerFormat() == DataFormatDouble)
     2457                return ValueRecovery::inFPR(infoPtr->fpr());
     2458            return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
     2459        }
     2460        if (infoPtr->spillFormat() != DataFormatNone)
     2461            return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()));
     2462   
     2463        ASSERT_NOT_REACHED();
     2464        return ValueRecovery();
     2465    }
     2466       
     2467    default:
     2468        ASSERT_NOT_REACHED();
     2469        return ValueRecovery();
     2470    }
    24232471}
    24242472
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r96189 r96375  
    6767};
    6868
     69enum ValueSourceKind {
     70    SourceNotSet,
     71    ValueInRegisterFile,
     72    Int32InRegisterFile,
     73    HaveNode
     74};
     75
    6976class ValueSource {
    7077public:
    7178    ValueSource()
    72         : m_nodeIndex(NoNode)
    73     {
     79        : m_nodeIndex(nodeIndexFromKind(SourceNotSet))
     80    {
     81    }
     82   
     83    explicit ValueSource(ValueSourceKind valueSourceKind)
     84        : m_nodeIndex(nodeIndexFromKind(valueSourceKind))
     85    {
     86        ASSERT(kind() != SourceNotSet);
     87        ASSERT(kind() != HaveNode);
    7488    }
    7589   
     
    7791        : m_nodeIndex(nodeIndex)
    7892    {
     93        ASSERT(kind() == HaveNode);
     94    }
     95   
     96    static ValueSource forPrediction(PredictedType prediction)
     97    {
     98        if (isInt32Prediction(prediction))
     99            return ValueSource(Int32InRegisterFile);
     100        return ValueSource(ValueInRegisterFile);
    79101    }
    80102   
    81103    bool isSet() const
    82104    {
    83         return m_nodeIndex != NoNode;
     105        return kindFromNodeIndex(m_nodeIndex) != SourceNotSet;
     106    }
     107   
     108    ValueSourceKind kind() const
     109    {
     110        return kindFromNodeIndex(m_nodeIndex);
    84111    }
    85112   
    86113    NodeIndex nodeIndex() const
    87114    {
    88         ASSERT(isSet());
     115        ASSERT(kind() == HaveNode);
    89116        return m_nodeIndex;
    90117    }
     
    95122   
    96123private:
     124    static NodeIndex nodeIndexFromKind(ValueSourceKind kind)
     125    {
     126        ASSERT(kind >= SourceNotSet && kind < HaveNode);
     127        return NoNode - kind;
     128    }
     129   
     130    static ValueSourceKind kindFromNodeIndex(NodeIndex nodeIndex)
     131    {
     132        unsigned kind = static_cast<unsigned>(NoNode - nodeIndex);
     133        if (kind >= static_cast<unsigned>(HaveNode))
     134            return HaveNode;
     135        return static_cast<ValueSourceKind>(kind);
     136    }
     137   
    97138    NodeIndex m_nodeIndex;
    98139};
     
    518559        switch (node.op) {
    519560        case GetLocal:
    520             return isArrayPrediction(m_jit.graph().getPrediction(node.local()));
     561            return isArrayPrediction(node.variableAccessData()->prediction());
    521562           
    522563        case NewArray:
     
    591632    // Tracking for which nodes are currently holding the values of arguments and bytecode
    592633    // operand-indexed variables.
    593 
     634   
    594635    ValueSource valueSourceForOperand(int operand)
    595636    {
     
    624665    uint32_t m_bytecodeIndexForOSR;
    625666   
    626     ValueRecovery computeValueRecoveryFor(int operand, const ValueSource&);
     667    ValueRecovery computeValueRecoveryFor(const ValueSource&);
    627668
    628669    ValueRecovery computeValueRecoveryFor(int operand)
    629670    {
    630         return computeValueRecoveryFor(operand, valueSourceForOperand(operand));
     671        return computeValueRecoveryFor(valueSourceForOperand(operand));
    631672    }
    632673};
     
    853894    , m_compileOkay(true)
    854895    , m_arguments(jit.codeBlock()->m_numParameters)
    855     , m_variables(jit.codeBlock()->m_numVars)
     896    , m_variables(jit.graph().m_localVars)
    856897    , m_lastSetOperand(std::numeric_limits<int>::max())
    857898    , m_bytecodeIndexForOSR(std::numeric_limits<uint32_t>::max())
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r96344 r96375  
    118118void ValueSource::dump(FILE* out) const
    119119{
    120     fprintf(out, "Node(%d)", m_nodeIndex);
     120    switch (kind()) {
     121    case SourceNotSet:
     122        fprintf(out, "NotSet");
     123        break;
     124    case ValueInRegisterFile:
     125        fprintf(out, "InRegFile");
     126        break;
     127    case Int32InRegisterFile:
     128        fprintf(out, "Int32");
     129        break;
     130    case HaveNode:
     131        fprintf(out, "Node(%d)", m_nodeIndex);
     132        break;
     133    }
    121134}
    122135
     
    171184    ASSERT(m_bytecodeIndex != std::numeric_limits<uint32_t>::max());
    172185    for (unsigned argument = 0; argument < m_arguments.size(); ++argument)
    173         m_arguments[argument] = jit->computeValueRecoveryFor(operandForArgument(argument), jit->m_arguments[argument]);
     186        m_arguments[argument] = jit->computeValueRecoveryFor(jit->m_arguments[argument]);
    174187    for (unsigned variable = 0; variable < m_variables.size(); ++variable)
    175         m_variables[variable] = jit->computeValueRecoveryFor(variable, jit->m_variables[variable]);
     188        m_variables[variable] = jit->computeValueRecoveryFor(jit->m_variables[variable]);
    176189}
    177190
     
    632645
    633646    case GetLocal: {
    634         PredictedType prediction = m_jit.graph().getPrediction(node.local());
     647        PredictedType prediction = node.variableAccessData()->prediction();
    635648
    636649        // If we have no prediction for this local, then don't attempt to compile.
     
    706719        m_bytecodeIndexForOSR = nextNode.codeOrigin.bytecodeIndex();
    707720       
    708         PredictedType predictedType = m_jit.graph().getPrediction(node.local());
     721        PredictedType predictedType = node.variableAccessData()->prediction();
    709722        if (isInt32Prediction(predictedType)) {
    710723            SpeculateIntegerOperand value(this, node.child1());
     
    726739        // Indicate that it's no longer necessary to retrieve the value of
    727740        // this bytecode variable from registers or other locations in the register file.
    728         valueSourceReferenceForOperand(node.local()) = ValueSource();
    729         break;
    730     }
     741        valueSourceReferenceForOperand(node.local()) = ValueSource::forPrediction(predictedType);
     742        break;
     743    }
     744
     745    case SetArgument:
     746        // This is a no-op; it just marks the fact that the argument is being used.
     747        // But it may be profitable to use this as a hook to run speculation checks
     748        // on arguments, thereby allowing us to trivially eliminate such checks if
     749        // the argument is not used.
     750        break;
    731751
    732752    case BitAnd:
     
    21352155#endif
    21362156
    2137     for (size_t i = 0; i < m_arguments.size(); ++i)
    2138         m_arguments[i] = ValueSource();
    2139     for (size_t i = 0; i < m_variables.size(); ++i)
    2140         m_variables[i] = ValueSource();
     2157    ASSERT(m_arguments.size() == block.m_argumentsAtHead.size());
     2158    for (size_t i = 0; i < m_arguments.size(); ++i) {
     2159        NodeIndex nodeIndex = block.m_argumentsAtHead[i].value;
     2160        if (nodeIndex == NoNode)
     2161            m_arguments[i] = ValueSource(ValueInRegisterFile);
     2162        else
     2163            m_arguments[i] = ValueSource::forPrediction(m_jit.graph()[nodeIndex].variableAccessData()->prediction());
     2164    }
     2165   
     2166    ASSERT(m_variables.size() == block.m_localsAtHead.size());
     2167    for (size_t i = 0; i < m_variables.size(); ++i) {
     2168        NodeIndex nodeIndex = block.m_localsAtHead[i].value;
     2169        if (nodeIndex == NoNode)
     2170            m_variables[i] = ValueSource(ValueInRegisterFile);
     2171        else
     2172            m_variables[i] = ValueSource::forPrediction(m_jit.graph()[nodeIndex].variableAccessData()->prediction());
     2173    }
     2174   
    21412175    m_lastSetOperand = std::numeric_limits<int>::max();
    21422176    m_bytecodeIndexForOSR = std::numeric_limits<uint32_t>::max();
     
    22112245    ASSERT(!m_compileIndex);
    22122246    m_bytecodeIndexForOSR = 0;
     2247
     2248    for (size_t i = 0; i < m_arguments.size(); ++i)
     2249        m_arguments[i] = ValueSource(ValueInRegisterFile);
     2250    for (size_t i = 0; i < m_variables.size(); ++i)
     2251        m_variables[i] = ValueSource(ValueInRegisterFile);
     2252   
    22132253    for (int i = 0; i < m_jit.codeBlock()->m_numParameters; ++i) {
    22142254        VirtualRegister virtualRegister = (VirtualRegister)(m_jit.codeBlock()->thisRegister() + i);
    2215         PredictedType predictedType = m_jit.graph().getPrediction(virtualRegister);
     2255        PredictedType predictedType = m_jit.graph()[m_jit.graph().m_arguments[i]].variableAccessData()->prediction();
    22162256        if (isInt32Prediction(predictedType))
    22172257            speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, JITCompiler::tagFor(virtualRegister), TrustedImm32(JSValue::Int32Tag)));
     
    22372277}
    22382278
    2239 ValueRecovery SpeculativeJIT::computeValueRecoveryFor(int operand, const ValueSource& valueSource)
     2279ValueRecovery SpeculativeJIT::computeValueRecoveryFor(const ValueSource& valueSource)
    22402280{
    2241     if (!valueSource.isSet()) {
    2242         if (m_bytecodeIndexForOSR && isInt32Prediction(m_jit.graph().getPrediction(operand)))
    2243             return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
     2281    switch (valueSource.kind()) {
     2282    case ValueInRegisterFile:
    22442283        return ValueRecovery::alreadyInRegisterFile();
    2245     }
    2246 
    2247     if (m_jit.isConstant(valueSource.nodeIndex()))
    2248         return ValueRecovery::constant(m_jit.valueOfJSConstant(valueSource.nodeIndex()));
    2249    
    2250     Node* nodePtr = &m_jit.graph()[valueSource.nodeIndex()];
    2251     if (!nodePtr->shouldGenerate()) {
    2252         // It's legitimately dead. As in, nobody will ever use this node, or operand,
    2253         // ever. Set it to Undefined to make the GC happy after the OSR.
    2254         return ValueRecovery::constant(jsUndefined());
    2255     }
    2256    
    2257     GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2258     if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
    2259         // Try to see if there is an alternate node that would contain the value we want.
    2260         // There are four possibilities:
    2261         //
    2262         // ValueToNumber: If the only live version of the value is a ValueToNumber node
    2263         //    then it means that all remaining uses of the value would have performed a
    2264         //    ValueToNumber conversion anyway. Thus, we can substitute ValueToNumber.
    2265         //
    2266         // ValueToInt32: Likewise, if the only remaining live version of the value is
    2267         //    ValueToInt32, then we can use it. But if there is both a ValueToInt32
    2268         //    and a ValueToNumber, then we better go with ValueToNumber because it
    2269         //    means that some remaining uses would have converted to number while
    2270         //    others would have converted to Int32.
    2271         //
    2272         // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
    2273         //    then the only remaining uses are ones that want a properly formed number
    2274         //    rather than a UInt32 intermediate.
    2275         //
    2276         // The reverse of the above: This node could be a UInt32ToNumber, but its
    2277         //    alternative is still alive. This means that the only remaining uses of
    2278         //    the number would be fine with a UInt32 intermediate.
    2279        
    2280         bool found = false;
    2281        
    2282         if (nodePtr->op == UInt32ToNumber) {
    2283             NodeIndex nodeIndex = nodePtr->child1();
    2284             nodePtr = &m_jit.graph()[nodeIndex];
    2285             infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2286             if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
    2287                 found = true;
    2288         }
    2289        
    2290         if (!found) {
    2291             NodeIndex valueToNumberIndex = NoNode;
    2292             NodeIndex valueToInt32Index = NoNode;
    2293             NodeIndex uint32ToNumberIndex = NoNode;
    2294            
    2295             for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
    2296                 GenerationInfo& info = m_generationInfo[virtualRegister];
    2297                 if (!info.alive())
    2298                     continue;
    2299                 if (info.nodeIndex() == NoNode)
    2300                     continue;
    2301                 Node& node = m_jit.graph()[info.nodeIndex()];
    2302                 if (node.child1Unchecked() != valueSource.nodeIndex())
    2303                     continue;
    2304                 switch (node.op) {
    2305                 case ValueToNumber:
    2306                 case ValueToDouble:
    2307                     valueToNumberIndex = info.nodeIndex();
    2308                     break;
    2309                 case ValueToInt32:
    2310                     valueToInt32Index = info.nodeIndex();
    2311                     break;
    2312                 case UInt32ToNumber:
    2313                     uint32ToNumberIndex = info.nodeIndex();
    2314                     break;
    2315                 default:
    2316                     break;
     2284       
     2285    case Int32InRegisterFile:
     2286        return ValueRecovery::alreadyInRegisterFileAsUnboxedInt32();
     2287
     2288    case HaveNode: {
     2289        if (m_jit.isConstant(valueSource.nodeIndex()))
     2290            return ValueRecovery::constant(m_jit.valueOfJSConstant(valueSource.nodeIndex()));
     2291   
     2292        Node* nodePtr = &m_jit.graph()[valueSource.nodeIndex()];
     2293        if (!nodePtr->shouldGenerate()) {
     2294            // It's legitimately dead. As in, nobody will ever use this node, or operand,
     2295            // ever. Set it to Undefined to make the GC happy after the OSR.
     2296            return ValueRecovery::constant(jsUndefined());
     2297        }
     2298   
     2299        GenerationInfo* infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
     2300        if (!infoPtr->alive() || infoPtr->nodeIndex() != valueSource.nodeIndex()) {
     2301            // Try to see if there is an alternate node that would contain the value we want.
     2302            // There are four possibilities:
     2303            //
     2304            // ValueToNumber: If the only live version of the value is a ValueToNumber node
     2305            //    then it means that all remaining uses of the value would have performed a
     2306            //    ValueToNumber conversion anyway. Thus, we can substitute ValueToNumber.
     2307            //
     2308            // ValueToInt32: Likewise, if the only remaining live version of the value is
     2309            //    ValueToInt32, then we can use it. But if there is both a ValueToInt32
     2310            //    and a ValueToNumber, then we better go with ValueToNumber because it
     2311            //    means that some remaining uses would have converted to number while
     2312            //    others would have converted to Int32.
     2313            //
     2314            // UInt32ToNumber: If the only live version of the value is a UInt32ToNumber
     2315            //    then the only remaining uses are ones that want a properly formed number
     2316            //    rather than a UInt32 intermediate.
     2317            //
     2318            // The reverse of the above: This node could be a UInt32ToNumber, but its
     2319            //    alternative is still alive. This means that the only remaining uses of
     2320            //    the number would be fine with a UInt32 intermediate.
     2321       
     2322            bool found = false;
     2323       
     2324            if (nodePtr->op == UInt32ToNumber) {
     2325                NodeIndex nodeIndex = nodePtr->child1();
     2326                nodePtr = &m_jit.graph()[nodeIndex];
     2327                infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
     2328                if (infoPtr->alive() && infoPtr->nodeIndex() == nodeIndex)
     2329                    found = true;
     2330            }
     2331       
     2332            if (!found) {
     2333                NodeIndex valueToNumberIndex = NoNode;
     2334                NodeIndex valueToInt32Index = NoNode;
     2335                NodeIndex uint32ToNumberIndex = NoNode;
     2336           
     2337                for (unsigned virtualRegister = 0; virtualRegister < m_generationInfo.size(); ++virtualRegister) {
     2338                    GenerationInfo& info = m_generationInfo[virtualRegister];
     2339                    if (!info.alive())
     2340                        continue;
     2341                    if (info.nodeIndex() == NoNode)
     2342                        continue;
     2343                    Node& node = m_jit.graph()[info.nodeIndex()];
     2344                    if (node.child1Unchecked() != valueSource.nodeIndex())
     2345                        continue;
     2346                    switch (node.op) {
     2347                    case ValueToNumber:
     2348                    case ValueToDouble:
     2349                        valueToNumberIndex = info.nodeIndex();
     2350                        break;
     2351                    case ValueToInt32:
     2352                        valueToInt32Index = info.nodeIndex();
     2353                        break;
     2354                    case UInt32ToNumber:
     2355                        uint32ToNumberIndex = info.nodeIndex();
     2356                        break;
     2357                    default:
     2358                        break;
     2359                    }
     2360                }
     2361           
     2362                NodeIndex nodeIndexToUse;
     2363                if (valueToNumberIndex != NoNode)
     2364                    nodeIndexToUse = valueToNumberIndex;
     2365                else if (valueToInt32Index != NoNode)
     2366                    nodeIndexToUse = valueToInt32Index;
     2367                else if (uint32ToNumberIndex != NoNode)
     2368                    nodeIndexToUse = uint32ToNumberIndex;
     2369                else
     2370                    nodeIndexToUse = NoNode;
     2371           
     2372                if (nodeIndexToUse != NoNode) {
     2373                    nodePtr = &m_jit.graph()[nodeIndexToUse];
     2374                    infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
     2375                    ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
     2376                    found = true;
    23172377                }
    23182378            }
    2319            
    2320             NodeIndex nodeIndexToUse;
    2321             if (valueToNumberIndex != NoNode)
    2322                 nodeIndexToUse = valueToNumberIndex;
    2323             else if (valueToInt32Index != NoNode)
    2324                 nodeIndexToUse = valueToInt32Index;
    2325             else if (uint32ToNumberIndex != NoNode)
    2326                 nodeIndexToUse = uint32ToNumberIndex;
    2327             else
    2328                 nodeIndexToUse = NoNode;
    2329            
    2330             if (nodeIndexToUse != NoNode) {
    2331                 nodePtr = &m_jit.graph()[nodeIndexToUse];
    2332                 infoPtr = &m_generationInfo[nodePtr->virtualRegister()];
    2333                 ASSERT(infoPtr->alive() && infoPtr->nodeIndex() == nodeIndexToUse);
    2334                 found = true;
    2335             }
    2336         }
    2337        
    2338         if (!found)
    2339             return ValueRecovery::constant(jsUndefined());
    2340     }
    2341    
    2342     ASSERT(infoPtr->alive());
    2343 
    2344     if (infoPtr->registerFormat() != DataFormatNone) {
    2345         if (infoPtr->registerFormat() == DataFormatDouble)
    2346             return ValueRecovery::inFPR(infoPtr->fpr());
    2347         if (infoPtr->registerFormat() & DataFormatJS)
    2348             return ValueRecovery::inPair(infoPtr->tagGPR(), infoPtr->payloadGPR());
    2349         return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
    2350     }
    2351     if (infoPtr->spillFormat() != DataFormatNone)
    2352         return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()));
    2353    
    2354     ASSERT_NOT_REACHED();
    2355     return ValueRecovery();
     2379       
     2380            if (!found)
     2381                return ValueRecovery::constant(jsUndefined());
     2382        }
     2383   
     2384        ASSERT(infoPtr->alive());
     2385
     2386        if (infoPtr->registerFormat() != DataFormatNone) {
     2387            if (infoPtr->registerFormat() == DataFormatDouble)
     2388                return ValueRecovery::inFPR(infoPtr->fpr());
     2389            if (infoPtr->registerFormat() & DataFormatJS)
     2390                return ValueRecovery::inPair(infoPtr->tagGPR(), infoPtr->payloadGPR());
     2391            return ValueRecovery::inGPR(infoPtr->gpr(), infoPtr->registerFormat());
     2392        }
     2393        if (infoPtr->spillFormat() != DataFormatNone)
     2394            return ValueRecovery::displacedInRegisterFile(static_cast<VirtualRegister>(nodePtr->virtualRegister()));
     2395   
     2396        ASSERT_NOT_REACHED();
     2397        return ValueRecovery();
     2398    }
     2399       
     2400    default:
     2401        ASSERT_NOT_REACHED();
     2402        return ValueRecovery();
     2403    }
    23562404}
    23572405
Note: See TracChangeset for help on using the changeset viewer.