Changeset 97218 in webkit


Ignore:
Timestamp:
Oct 11, 2011 7:05:53 PM (13 years ago)
Author:
fpizlo@apple.com
Message:

DFG does not have flow-sensitive intraprocedural control flow analysis
https://bugs.webkit.org/show_bug.cgi?id=69690

Reviewed by Gavin Barraclough.

Implemented a control flow analysis (CFA). It currently propagates type
proofs only. For example, if all predecessors to a basic block have
checks that variable X is a JSFinalObject with structure 0xabcdef, then
this basic block will now know this fact and will know that it does not
have to emit either JSFinalObject checks or any structure checks since
the structure is precisely known. The CFA takes heap side-effects into
account (though somewhat conservatively), so that if the object pointed
to by variable X could have possibly undergone a structure transition
then this is reflected: the analysis may simply say that X's structure
is unknown.

This also propagates a wealth of other type information which is
currently not being used. For example, we now know when a variable can
only hold doubles. Even if a variable may hold other types at different
points in its live range, we can still prove exactly when it will only
be double.

There's a bunch of stuff that the CFA could do that it still does not
do, like precise handling of PutStructure (i.e. structure transitions),
precise handling of CheckFunction and CheckMethod, etc. So this is
very much intended to be a starting point rather than an end unto
itself.

This is a 1% win on V8 (mostly due to a 3% win on richards and deltablue)
and a 1% win on Kraken (mostly due to a 6% win on imaging-desaturate).
Neutral on SunSpider.

  • GNUmakefile.list.am:
  • JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/ActionablePrediction.h: Removed.
  • bytecode/PredictedType.cpp:

(JSC::predictionToString):

  • bytecode/PredictedType.h:
  • dfg/DFGAbstractState.cpp: Added.

(JSC::DFG::AbstractState::AbstractState):
(JSC::DFG::AbstractState::~AbstractState):
(JSC::DFG::AbstractState::beginBasicBlock):
(JSC::DFG::AbstractState::initialize):
(JSC::DFG::AbstractState::endBasicBlock):
(JSC::DFG::AbstractState::reset):
(JSC::DFG::AbstractState::execute):
(JSC::DFG::AbstractState::clobberStructures):
(JSC::DFG::AbstractState::mergeStateAtTail):
(JSC::DFG::AbstractState::merge):
(JSC::DFG::AbstractState::mergeToSuccessors):
(JSC::DFG::AbstractState::mergeVariableBetweenBlocks):
(JSC::DFG::AbstractState::dump):

  • dfg/DFGAbstractState.h: Added.

(JSC::DFG::AbstractState::forNode):
(JSC::DFG::AbstractState::isValid):

  • dfg/DFGAbstractValue.h: Added.

(JSC::DFG::StructureAbstractValue::StructureAbstractValue):
(JSC::DFG::StructureAbstractValue::clear):
(JSC::DFG::StructureAbstractValue::makeTop):
(JSC::DFG::StructureAbstractValue::top):
(JSC::DFG::StructureAbstractValue::add):
(JSC::DFG::StructureAbstractValue::addAll):
(JSC::DFG::StructureAbstractValue::contains):
(JSC::DFG::StructureAbstractValue::isSubsetOf):
(JSC::DFG::StructureAbstractValue::doesNotContainAnyOtherThan):
(JSC::DFG::StructureAbstractValue::isSupersetOf):
(JSC::DFG::StructureAbstractValue::filter):
(JSC::DFG::StructureAbstractValue::isClear):
(JSC::DFG::StructureAbstractValue::isTop):
(JSC::DFG::StructureAbstractValue::size):
(JSC::DFG::StructureAbstractValue::at):
(JSC::DFG::StructureAbstractValue::operator[]):
(JSC::DFG::StructureAbstractValue::last):
(JSC::DFG::StructureAbstractValue::predictionFromStructures):
(JSC::DFG::StructureAbstractValue::operator==):
(JSC::DFG::StructureAbstractValue::dump):
(JSC::DFG::AbstractValue::AbstractValue):
(JSC::DFG::AbstractValue::clear):
(JSC::DFG::AbstractValue::isClear):
(JSC::DFG::AbstractValue::makeTop):
(JSC::DFG::AbstractValue::clobberStructures):
(JSC::DFG::AbstractValue::isTop):
(JSC::DFG::AbstractValue::top):
(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::operator==):
(JSC::DFG::AbstractValue::merge):
(JSC::DFG::AbstractValue::filter):
(JSC::DFG::AbstractValue::validate):
(JSC::DFG::AbstractValue::dump):

  • dfg/DFGBasicBlock.h: Added.

(JSC::DFG::BasicBlock::BasicBlock):
(JSC::DFG::BasicBlock::getBytecodeBegin):

  • dfg/DFGByteCodeParser.cpp:

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

  • dfg/DFGGraph.cpp:

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

  • dfg/DFGGraph.h:
  • dfg/DFGJITCodeGenerator.h:

(JSC::DFG::block):

  • dfg/DFGJITCodeGenerator32_64.cpp:

(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranchNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranch):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq):

  • dfg/DFGJITCodeGenerator64.cpp:

(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranchNull):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranch):
(JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq):

  • dfg/DFGJITCompiler.h:

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

  • dfg/DFGNode.h:

(JSC::DFG::NodeIndexTraits::defaultValue):
(JSC::DFG::Node::variableAccessData):
(JSC::DFG::Node::takenBytecodeOffsetDuringParsing):
(JSC::DFG::Node::notTakenBytecodeOffsetDuringParsing):
(JSC::DFG::Node::setTakenBlockIndex):
(JSC::DFG::Node::setNotTakenBlockIndex):
(JSC::DFG::Node::takenBlockIndex):
(JSC::DFG::Node::notTakenBlockIndex):

  • dfg/DFGOSREntry.cpp:

(JSC::DFG::prepareOSREntry):

  • dfg/DFGOSREntry.h:
  • dfg/DFGOperands.h: Added.

(JSC::DFG::operandIsArgument):
(JSC::DFG::OperandValueTraits::defaultValue):
(JSC::DFG::Operands::Operands):
(JSC::DFG::Operands::numberOfArguments):
(JSC::DFG::Operands::numberOfLocals):
(JSC::DFG::Operands::argument):
(JSC::DFG::Operands::local):
(JSC::DFG::Operands::setLocal):
(JSC::DFG::Operands::setArgumentFirstTime):
(JSC::DFG::Operands::setLocalFirstTime):
(JSC::DFG::Operands::operand):
(JSC::DFG::Operands::setOperand):
(JSC::DFG::Operands::clear):
(JSC::DFG::dumpOperands):

  • dfg/DFGPropagator.cpp:

(JSC::DFG::Propagator::fixpoint):
(JSC::DFG::Propagator::propagateArithNodeFlags):
(JSC::DFG::Propagator::propagateNodePredictions):
(JSC::DFG::Propagator::propagatePredictions):
(JSC::DFG::Propagator::performBlockCFA):
(JSC::DFG::Propagator::performForwardCFA):
(JSC::DFG::Propagator::globalCFA):

  • dfg/DFGSpeculativeJIT.cpp:

(JSC::DFG::SpeculativeJIT::compilePeepHoleDoubleBranch):
(JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch):
(JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
(JSC::DFG::SpeculativeJIT::compile):
(JSC::DFG::SpeculativeJIT::compileGetCharCodeAt):
(JSC::DFG::SpeculativeJIT::compileGetByValOnString):

  • dfg/DFGSpeculativeJIT.h:

(JSC::DFG::SpeculativeJIT::SpeculativeJIT):

  • dfg/DFGSpeculativeJIT32_64.cpp:

(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compare):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::emitBranch):
(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGSpeculativeJIT64.cpp:

(JSC::DFG::SpeculativeJIT::compileObjectEquality):
(JSC::DFG::SpeculativeJIT::compare):
(JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
(JSC::DFG::SpeculativeJIT::compileLogicalNot):
(JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
(JSC::DFG::SpeculativeJIT::emitBranch):
(JSC::DFG::SpeculativeJIT::compile):

  • dfg/DFGStructureSet.h:

(JSC::DFG::StructureSet::clear):
(JSC::DFG::StructureSet::predictionFromStructures):
(JSC::DFG::StructureSet::operator==):
(JSC::DFG::StructureSet::dump):

  • dfg/DFGVariableAccessData.h: Added.
Location:
trunk/Source/JavaScriptCore
Files:
6 added
1 deleted
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r97216 r97218  
     12011-10-08  Filip Pizlo  <fpizlo@apple.com>
     2
     3        DFG does not have flow-sensitive intraprocedural control flow analysis
     4        https://bugs.webkit.org/show_bug.cgi?id=69690
     5
     6        Reviewed by Gavin Barraclough.
     7
     8        Implemented a control flow analysis (CFA). It currently propagates type
     9        proofs only. For example, if all predecessors to a basic block have
     10        checks that variable X is a JSFinalObject with structure 0xabcdef, then
     11        this basic block will now know this fact and will know that it does not
     12        have to emit either JSFinalObject checks or any structure checks since
     13        the structure is precisely known. The CFA takes heap side-effects into
     14        account (though somewhat conservatively), so that if the object pointed
     15        to by variable X could have possibly undergone a structure transition
     16        then this is reflected: the analysis may simply say that X's structure
     17        is unknown.
     18       
     19        This also propagates a wealth of other type information which is
     20        currently not being used. For example, we now know when a variable can
     21        only hold doubles. Even if a variable may hold other types at different
     22        points in its live range, we can still prove exactly when it will only
     23        be double.
     24       
     25        There's a bunch of stuff that the CFA could do that it still does not
     26        do, like precise handling of PutStructure (i.e. structure transitions),
     27        precise handling of CheckFunction and CheckMethod, etc. So this is
     28        very much intended to be a starting point rather than an end unto
     29        itself.
     30       
     31        This is a 1% win on V8 (mostly due to a 3% win on richards and deltablue)
     32        and a 1% win on Kraken (mostly due to a 6% win on imaging-desaturate).
     33        Neutral on SunSpider.
     34
     35        * GNUmakefile.list.am:
     36        * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
     37        * JavaScriptCore.xcodeproj/project.pbxproj:
     38        * bytecode/ActionablePrediction.h: Removed.
     39        * bytecode/PredictedType.cpp:
     40        (JSC::predictionToString):
     41        * bytecode/PredictedType.h:
     42        * dfg/DFGAbstractState.cpp: Added.
     43        (JSC::DFG::AbstractState::AbstractState):
     44        (JSC::DFG::AbstractState::~AbstractState):
     45        (JSC::DFG::AbstractState::beginBasicBlock):
     46        (JSC::DFG::AbstractState::initialize):
     47        (JSC::DFG::AbstractState::endBasicBlock):
     48        (JSC::DFG::AbstractState::reset):
     49        (JSC::DFG::AbstractState::execute):
     50        (JSC::DFG::AbstractState::clobberStructures):
     51        (JSC::DFG::AbstractState::mergeStateAtTail):
     52        (JSC::DFG::AbstractState::merge):
     53        (JSC::DFG::AbstractState::mergeToSuccessors):
     54        (JSC::DFG::AbstractState::mergeVariableBetweenBlocks):
     55        (JSC::DFG::AbstractState::dump):
     56        * dfg/DFGAbstractState.h: Added.
     57        (JSC::DFG::AbstractState::forNode):
     58        (JSC::DFG::AbstractState::isValid):
     59        * dfg/DFGAbstractValue.h: Added.
     60        (JSC::DFG::StructureAbstractValue::StructureAbstractValue):
     61        (JSC::DFG::StructureAbstractValue::clear):
     62        (JSC::DFG::StructureAbstractValue::makeTop):
     63        (JSC::DFG::StructureAbstractValue::top):
     64        (JSC::DFG::StructureAbstractValue::add):
     65        (JSC::DFG::StructureAbstractValue::addAll):
     66        (JSC::DFG::StructureAbstractValue::contains):
     67        (JSC::DFG::StructureAbstractValue::isSubsetOf):
     68        (JSC::DFG::StructureAbstractValue::doesNotContainAnyOtherThan):
     69        (JSC::DFG::StructureAbstractValue::isSupersetOf):
     70        (JSC::DFG::StructureAbstractValue::filter):
     71        (JSC::DFG::StructureAbstractValue::isClear):
     72        (JSC::DFG::StructureAbstractValue::isTop):
     73        (JSC::DFG::StructureAbstractValue::size):
     74        (JSC::DFG::StructureAbstractValue::at):
     75        (JSC::DFG::StructureAbstractValue::operator[]):
     76        (JSC::DFG::StructureAbstractValue::last):
     77        (JSC::DFG::StructureAbstractValue::predictionFromStructures):
     78        (JSC::DFG::StructureAbstractValue::operator==):
     79        (JSC::DFG::StructureAbstractValue::dump):
     80        (JSC::DFG::AbstractValue::AbstractValue):
     81        (JSC::DFG::AbstractValue::clear):
     82        (JSC::DFG::AbstractValue::isClear):
     83        (JSC::DFG::AbstractValue::makeTop):
     84        (JSC::DFG::AbstractValue::clobberStructures):
     85        (JSC::DFG::AbstractValue::isTop):
     86        (JSC::DFG::AbstractValue::top):
     87        (JSC::DFG::AbstractValue::set):
     88        (JSC::DFG::AbstractValue::operator==):
     89        (JSC::DFG::AbstractValue::merge):
     90        (JSC::DFG::AbstractValue::filter):
     91        (JSC::DFG::AbstractValue::validate):
     92        (JSC::DFG::AbstractValue::dump):
     93        * dfg/DFGBasicBlock.h: Added.
     94        (JSC::DFG::BasicBlock::BasicBlock):
     95        (JSC::DFG::BasicBlock::getBytecodeBegin):
     96        * dfg/DFGByteCodeParser.cpp:
     97        (JSC::DFG::ByteCodeParser::getLocal):
     98        (JSC::DFG::ByteCodeParser::setLocal):
     99        (JSC::DFG::ByteCodeParser::getArgument):
     100        (JSC::DFG::ByteCodeParser::setArgument):
     101        (JSC::DFG::ByteCodeParser::parseBlock):
     102        (JSC::DFG::ByteCodeParser::processPhiStack):
     103        (JSC::DFG::ByteCodeParser::setupPredecessors):
     104        * dfg/DFGGraph.cpp:
     105        (JSC::DFG::Graph::dump):
     106        * dfg/DFGGraph.h:
     107        * dfg/DFGJITCodeGenerator.h:
     108        (JSC::DFG::block):
     109        * dfg/DFGJITCodeGenerator32_64.cpp:
     110        (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranchNull):
     111        (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranch):
     112        (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq):
     113        * dfg/DFGJITCodeGenerator64.cpp:
     114        (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranchNull):
     115        (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeBranch):
     116        (JSC::DFG::JITCodeGenerator::nonSpeculativePeepholeStrictEq):
     117        * dfg/DFGJITCompiler.h:
     118        (JSC::DFG::JITCompiler::noticeOSREntry):
     119        * dfg/DFGNode.h:
     120        (JSC::DFG::NodeIndexTraits::defaultValue):
     121        (JSC::DFG::Node::variableAccessData):
     122        (JSC::DFG::Node::takenBytecodeOffsetDuringParsing):
     123        (JSC::DFG::Node::notTakenBytecodeOffsetDuringParsing):
     124        (JSC::DFG::Node::setTakenBlockIndex):
     125        (JSC::DFG::Node::setNotTakenBlockIndex):
     126        (JSC::DFG::Node::takenBlockIndex):
     127        (JSC::DFG::Node::notTakenBlockIndex):
     128        * dfg/DFGOSREntry.cpp:
     129        (JSC::DFG::prepareOSREntry):
     130        * dfg/DFGOSREntry.h:
     131        * dfg/DFGOperands.h: Added.
     132        (JSC::DFG::operandIsArgument):
     133        (JSC::DFG::OperandValueTraits::defaultValue):
     134        (JSC::DFG::Operands::Operands):
     135        (JSC::DFG::Operands::numberOfArguments):
     136        (JSC::DFG::Operands::numberOfLocals):
     137        (JSC::DFG::Operands::argument):
     138        (JSC::DFG::Operands::local):
     139        (JSC::DFG::Operands::setLocal):
     140        (JSC::DFG::Operands::setArgumentFirstTime):
     141        (JSC::DFG::Operands::setLocalFirstTime):
     142        (JSC::DFG::Operands::operand):
     143        (JSC::DFG::Operands::setOperand):
     144        (JSC::DFG::Operands::clear):
     145        (JSC::DFG::dumpOperands):
     146        * dfg/DFGPropagator.cpp:
     147        (JSC::DFG::Propagator::fixpoint):
     148        (JSC::DFG::Propagator::propagateArithNodeFlags):
     149        (JSC::DFG::Propagator::propagateNodePredictions):
     150        (JSC::DFG::Propagator::propagatePredictions):
     151        (JSC::DFG::Propagator::performBlockCFA):
     152        (JSC::DFG::Propagator::performForwardCFA):
     153        (JSC::DFG::Propagator::globalCFA):
     154        * dfg/DFGSpeculativeJIT.cpp:
     155        (JSC::DFG::SpeculativeJIT::compilePeepHoleDoubleBranch):
     156        (JSC::DFG::SpeculativeJIT::compilePeepHoleObjectEquality):
     157        (JSC::DFG::SpeculativeJIT::compilePeepHoleIntegerBranch):
     158        (JSC::DFG::SpeculativeJIT::compilePeepHoleBranch):
     159        (JSC::DFG::SpeculativeJIT::compile):
     160        (JSC::DFG::SpeculativeJIT::compileGetCharCodeAt):
     161        (JSC::DFG::SpeculativeJIT::compileGetByValOnString):
     162        * dfg/DFGSpeculativeJIT.h:
     163        (JSC::DFG::SpeculativeJIT::SpeculativeJIT):
     164        * dfg/DFGSpeculativeJIT32_64.cpp:
     165        (JSC::DFG::SpeculativeJIT::compileObjectEquality):
     166        (JSC::DFG::SpeculativeJIT::compare):
     167        (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
     168        (JSC::DFG::SpeculativeJIT::compileLogicalNot):
     169        (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
     170        (JSC::DFG::SpeculativeJIT::emitBranch):
     171        (JSC::DFG::SpeculativeJIT::compile):
     172        * dfg/DFGSpeculativeJIT64.cpp:
     173        (JSC::DFG::SpeculativeJIT::compileObjectEquality):
     174        (JSC::DFG::SpeculativeJIT::compare):
     175        (JSC::DFG::SpeculativeJIT::compileObjectOrOtherLogicalNot):
     176        (JSC::DFG::SpeculativeJIT::compileLogicalNot):
     177        (JSC::DFG::SpeculativeJIT::emitObjectOrOtherBranch):
     178        (JSC::DFG::SpeculativeJIT::emitBranch):
     179        (JSC::DFG::SpeculativeJIT::compile):
     180        * dfg/DFGStructureSet.h:
     181        (JSC::DFG::StructureSet::clear):
     182        (JSC::DFG::StructureSet::predictionFromStructures):
     183        (JSC::DFG::StructureSet::operator==):
     184        (JSC::DFG::StructureSet::dump):
     185        * dfg/DFGVariableAccessData.h: Added.
     186
    11872011-10-11  Gavin Barraclough  <baraclough@apple.com>
    2188
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r96527 r97218  
    8282        Source/JavaScriptCore/assembler/SH4Assembler.h \
    8383        Source/JavaScriptCore/assembler/X86Assembler.h \
    84         Source/JavaScriptCore/bytecode/ActionablePrediction.h \
    8584        Source/JavaScriptCore/bytecode/CodeBlock.cpp \
    8685        Source/JavaScriptCore/bytecode/CodeBlock.h \
     
    106105        Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp \
    107106        Source/JavaScriptCore/bytecompiler/RegisterID.h \
     107        Source/JavaScriptCore/dfg/DFGAbstractState.cpp \
     108        Source/JavaScriptCore/dfg/DFGAbstractState.h \
     109        Source/JavaScriptCore/dfg/DFGAbstractValue.h \
     110        Source/JavaScriptCoer/dfg/DFGBasicBlock.h \
    108111        Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp \
    109112        Source/JavaScriptCore/dfg/DFGByteCodeParser.h \
     
    123126        Source/JavaScriptCore/dfg/DFGJITCompiler.h \
    124127        Source/JavaScriptCore/dfg/DFGNode.h \
     128        Source/JavaScriptCore/dfg/DFGOperands.h \
    125129        Source/JavaScriptCore/dfg/DFGOperations.cpp \
    126130        Source/JavaScriptCore/dfg/DFGOperations.h \
     
    136140        Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h \
    137141        Source/JavaScriptCore/dfg/DFGStructureSet.h \
     142        Source/JavaScriptCore/dfg/DFGVariableAccessData.h \
    138143        Source/JavaScriptCore/heap/AllocationSpace.cpp \
    139144        Source/JavaScriptCore/heap/AllocationSpace.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj

    r96465 r97218  
    14391439                        >
    14401440                        <File
    1441                                 RelativePath="..\..\bytecode\ActionablePrediction.h"
    1442                                 >
    1443                         </File>
    1444                         <File
    14451441                                RelativePath="..\..\bytecode\CodeBlock.cpp"
    14461442                                >
     
    15861582                                >
    15871583                        </File>
     1584                        <File
     1585                                RelativePath="..\..\dfg\DFGOSREntry.h"
     1586                                >
     1587                        </File>
    15881588                </Filter>
    15891589                <Filter
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r96881 r97218  
    5252                0F16D726142C39C000CF784A /* BitVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F16D724142C39A200CF784A /* BitVector.cpp */; };
    5353                0F242DA713F3B1E8007ADD4C /* WeakReferenceHarvester.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */; settings = {ATTRIBUTES = (Private, ); }; };
     54                0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */; settings = {ATTRIBUTES = (Private, ); }; };
     55                0F620175143FCD370068B77C /* DFGOperands.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620171143FCD2F0068B77C /* DFGOperands.h */; settings = {ATTRIBUTES = (Private, ); }; };
     56                0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F620170143FCD2F0068B77C /* DFGBasicBlock.h */; settings = {ATTRIBUTES = (Private, ); }; };
     57                0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
     58                0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F62016E143FCD2F0068B77C /* DFGAbstractState.h */; settings = {ATTRIBUTES = (Private, ); }; };
     59                0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */; };
    5460                0F636DA0142D27D700B2E66A /* PackedIntVector.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F636D9F142D27D200B2E66A /* PackedIntVector.h */; };
    55                 0F636DA2142D27F000B2E66A /* ActionablePrediction.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F636DA1142D27ED00B2E66A /* ActionablePrediction.h */; };
    5661                0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; };
    5762                0F963B2713F753BB0002D9B2 /* RedBlackTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F963B2613F753990002D9B2 /* RedBlackTree.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    810815                0F16D724142C39A200CF784A /* BitVector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BitVector.cpp; sourceTree = "<group>"; };
    811816                0F242DA513F3B1BB007ADD4C /* WeakReferenceHarvester.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WeakReferenceHarvester.h; sourceTree = "<group>"; };
     817                0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGAbstractState.cpp; path = dfg/DFGAbstractState.cpp; sourceTree = "<group>"; };
     818                0F62016E143FCD2F0068B77C /* DFGAbstractState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractState.h; path = dfg/DFGAbstractState.h; sourceTree = "<group>"; };
     819                0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAbstractValue.h; path = dfg/DFGAbstractValue.h; sourceTree = "<group>"; };
     820                0F620170143FCD2F0068B77C /* DFGBasicBlock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGBasicBlock.h; path = dfg/DFGBasicBlock.h; sourceTree = "<group>"; };
     821                0F620171143FCD2F0068B77C /* DFGOperands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOperands.h; path = dfg/DFGOperands.h; sourceTree = "<group>"; };
     822                0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGVariableAccessData.h; path = dfg/DFGVariableAccessData.h; sourceTree = "<group>"; };
    812823                0F636D9F142D27D200B2E66A /* PackedIntVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PackedIntVector.h; sourceTree = "<group>"; };
    813                 0F636DA1142D27ED00B2E66A /* ActionablePrediction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ActionablePrediction.h; sourceTree = "<group>"; };
    814824                0F77008E1402FDD60078EB39 /* SamplingCounter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SamplingCounter.h; sourceTree = "<group>"; };
    815825                0F7700911402FF280078EB39 /* SamplingCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SamplingCounter.cpp; sourceTree = "<group>"; };
     
    22842294                        isa = PBXGroup;
    22852295                        children = (
     2296                                0F62016D143FCD2F0068B77C /* DFGAbstractState.cpp */,
     2297                                0F62016E143FCD2F0068B77C /* DFGAbstractState.h */,
     2298                                0F62016F143FCD2F0068B77C /* DFGAbstractValue.h */,
     2299                                0F620170143FCD2F0068B77C /* DFGBasicBlock.h */,
     2300                                0F620171143FCD2F0068B77C /* DFGOperands.h */,
     2301                                0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */,
    22862302                                0FFF4BB2143955E600655BC0 /* DFGStructureSet.h */,
    22872303                                86EC9DB41328DF82002B2AD7 /* DFGByteCodeParser.cpp */,
     
    23852401                        isa = PBXGroup;
    23862402                        children = (
    2387                                 0F636DA1142D27ED00B2E66A /* ActionablePrediction.h */,
    23882403                                0FD82E8E14207A5100179C94 /* ValueProfile.cpp */,
    23892404                                0FD82E84141F3FDA00179C94 /* PredictedType.cpp */,
     
    28712886                                86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */,
    28722887                                0F636DA0142D27D700B2E66A /* PackedIntVector.h in Headers */,
    2873                                 0F636DA2142D27F000B2E66A /* ActionablePrediction.h in Headers */,
    28742888                                A7521E131429169A003C8D0C /* CardSet.h in Headers */,
    28752889                                0FD52AAE143035A00026DC9F /* UnionFind.h in Headers */,
     
    28782892                                0FFF4BB4143955E900655BC0 /* DFGStructureSet.h in Headers */,
    28792893                                8604F505143CE1C200B295F5 /* JSGlobalThis.h in Headers */,
     2894                                0F620174143FCD330068B77C /* DFGVariableAccessData.h in Headers */,
     2895                                0F620175143FCD370068B77C /* DFGOperands.h in Headers */,
     2896                                0F620176143FCD3B0068B77C /* DFGBasicBlock.h in Headers */,
     2897                                0F620177143FCD3F0068B77C /* DFGAbstractValue.h in Headers */,
     2898                                0F620178143FCD440068B77C /* DFGAbstractState.h in Headers */,
    28802899                        );
    28812900                        runOnlyForDeploymentPostprocessing = 0;
     
    34093428                                86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */,
    34103429                                0FE228EE1436AB2C00196C48 /* Heuristics.cpp in Sources */,
     3430                                0F620179143FCD480068B77C /* DFGAbstractState.cpp in Sources */,
    34113431                        );
    34123432                        runOnlyForDeploymentPostprocessing = 0;
  • trunk/Source/JavaScriptCore/bytecode/PredictedType.cpp

    r96894 r97218  
    4545    BoundsCheckedPointer<char> ptr(description, size);
    4646   
     47    bool isTop = true;
     48   
    4749    if (value & PredictCellOther)
    4850        ptr.strcat("Othercell");
     51    else
     52        isTop = false;
    4953   
    5054    if (value & PredictObjectOther)
    5155        ptr.strcat("Otherobj");
     56    else
     57        isTop = false;
    5258   
    5359    if (value & PredictFinalObject)
    5460        ptr.strcat("Final");
     61    else
     62        isTop = false;
    5563
    5664    if (value & PredictArray)
    5765        ptr.strcat("Array");
     66    else
     67        isTop = false;
    5868   
    5969    if (value & PredictString)
    6070        ptr.strcat("String");
     71    else
     72        isTop = false;
    6173   
    6274    if (value & PredictInt32)
    6375        ptr.strcat("Int");
     76    else
     77        isTop = false;
    6478   
    6579    if (value & PredictDouble)
    6680        ptr.strcat("Double");
     81    else
     82        isTop = false;
    6783   
    6884    if (value & PredictBoolean)
    6985        ptr.strcat("Bool");
     86    else
     87        isTop = false;
    7088   
    7189    if (value & PredictOther)
    7290        ptr.strcat("Other");
     91    else
     92        isTop = false;
     93   
     94    if (isTop)
     95        return "Top";
    7396   
    7497    *ptr++ = 0;
  • trunk/Source/JavaScriptCore/bytecode/PredictedType.h

    r96894 r97218  
    5151static const PredictedType PredictOther         = 0x4000; // It's definitely none of the above.
    5252static const PredictedType PredictTop           = 0x7fff; // It can be any of the above.
     53
     54typedef bool (*PredictionChecker)(PredictedType);
    5355
    5456inline bool isCellPrediction(PredictedType value)
     
    116118#endif
    117119
     120// Merge two predictions. Note that currently this just does left | right. It may
     121// seem tempting to do so directly, but you would be doing so at your own peril,
     122// since the merging protocol PredictedType may change at any time (and has already
     123// changed several times in its history).
    118124inline PredictedType mergePredictions(PredictedType left, PredictedType right)
    119125{
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r97197 r97218  
    129129    NodeIndex getLocal(unsigned operand)
    130130    {
    131         NodeIndex nodeIndex = m_currentBlock->m_localsAtTail[operand].value;
     131        NodeIndex nodeIndex = m_currentBlock->variablesAtTail.local(operand);
    132132
    133133        if (nodeIndex != NoNode) {
     
    148148        m_localPhiStack.append(PhiStackEntry(m_currentBlock, phi, operand));
    149149        nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), phi);
    150         m_currentBlock->m_localsAtTail[operand].value = nodeIndex;
    151        
    152         m_currentBlock->m_localsAtHead[operand].setFirstTime(nodeIndex);
     150        m_currentBlock->variablesAtTail.local(operand) = nodeIndex;
     151       
     152        m_currentBlock->variablesAtHead.setLocalFirstTime(operand, nodeIndex);
    153153       
    154154        return nodeIndex;
     
    156156    void setLocal(unsigned operand, NodeIndex value)
    157157    {
    158         m_currentBlock->m_localsAtTail[operand].value = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value);
     158        m_currentBlock->variablesAtTail.local(operand) = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value);
    159159    }
    160160
     
    165165        ASSERT(argument < m_numArguments);
    166166
    167         NodeIndex nodeIndex = m_currentBlock->m_argumentsAtTail[argument].value;
     167        NodeIndex nodeIndex = m_currentBlock->variablesAtTail.argument(argument);
    168168
    169169        if (nodeIndex != NoNode) {
     
    174174                ASSERT(node.local() == static_cast<VirtualRegister>(operand));
    175175                nodeIndex = addToGraph(GetLocal, OpInfo(node.variableAccessData()), nodeIndex);
    176                 m_currentBlock->m_argumentsAtTail[argument].value = nodeIndex;
     176                m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
    177177                return nodeIndex;
    178178            }
     
    190190        m_argumentPhiStack.append(PhiStackEntry(m_currentBlock, phi, argument));
    191191        nodeIndex = addToGraph(GetLocal, OpInfo(variableAccessData), phi);
    192         m_currentBlock->m_argumentsAtTail[argument].value = nodeIndex;
    193        
    194         m_currentBlock->m_argumentsAtHead[argument].setFirstTime(nodeIndex);
     192        m_currentBlock->variablesAtTail.argument(argument) = nodeIndex;
     193       
     194        m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, nodeIndex);
    195195       
    196196        return nodeIndex;
     
    201201        ASSERT(argument < m_numArguments);
    202202
    203         m_currentBlock->m_argumentsAtTail[argument].value = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value);
     203        m_currentBlock->variablesAtTail.argument(argument) = addToGraph(SetLocal, OpInfo(newVariableAccessData(operand)), value);
    204204    }
    205205
     
    787787            NodeIndex setArgument = addToGraph(SetArgument, OpInfo(newVariableAccessData(argument - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize)));
    788788            m_graph.m_arguments[argument] = setArgument;
    789             m_currentBlock->m_argumentsAtHead[argument].setFirstTime(setArgument);
    790             m_currentBlock->m_argumentsAtTail[argument].setFirstTime(setArgument);
     789            m_currentBlock->variablesAtHead.setArgumentFirstTime(argument, setArgument);
     790            m_currentBlock->variablesAtTail.setArgumentFirstTime(argument, setArgument);
    791791        }
    792792    }
     
    16931693            BasicBlock* predecessorBlock = m_graph.m_blocks[predecessors[i]].get();
    16941694
    1695             VariableRecord& var = (stackType == ArgumentPhiStack) ? predecessorBlock->m_argumentsAtTail[varNo] : predecessorBlock->m_localsAtTail[varNo];
    1696 
    1697             NodeIndex valueInPredecessor = var.value;
     1695            NodeIndex& var = (stackType == ArgumentPhiStack) ? predecessorBlock->variablesAtTail.argument(varNo) : predecessorBlock->variablesAtTail.local(varNo);
     1696
     1697            NodeIndex valueInPredecessor = var;
    16981698            if (valueInPredecessor == NoNode) {
    16991699                valueInPredecessor = addToGraph(Phi, OpInfo(newVariableAccessData(stackType == ArgumentPhiStack ? varNo - m_codeBlock->m_numParameters - RegisterFile::CallFrameHeaderSize : varNo)));
    1700                 var.setFirstTime(valueInPredecessor);
     1700                var = valueInPredecessor;
    17011701                if (stackType == ArgumentPhiStack)
    1702                     predecessorBlock->m_argumentsAtHead[varNo].setFirstTime(valueInPredecessor);
     1702                    predecessorBlock->variablesAtHead.setArgumentFirstTime(varNo, valueInPredecessor);
    17031703                else
    1704                     predecessorBlock->m_localsAtHead[varNo].setFirstTime(valueInPredecessor);
     1704                    predecessorBlock->variablesAtHead.setLocalFirstTime(varNo, valueInPredecessor);
    17051705                phiStack.append(PhiStackEntry(predecessorBlock, valueInPredecessor, varNo));
    17061706            } else if (m_graph[valueInPredecessor].op == GetLocal) {
     
    17621762        ASSERT(node.isTerminal());
    17631763
    1764         if (node.isJump())
    1765             m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
    1766         else if (node.isBranch()) {
    1767             m_graph.blockForBytecodeOffset(node.takenBytecodeOffset()).m_predecessors.append(index);
    1768             m_graph.blockForBytecodeOffset(node.notTakenBytecodeOffset()).m_predecessors.append(index);
     1764        if (node.isJump()) {
     1765            node.setTakenBlockIndex(m_graph.blockIndexForBytecodeOffset(node.takenBytecodeOffsetDuringParsing()));
     1766            m_graph.m_blocks[node.takenBlockIndex()]->m_predecessors.append(index);
     1767        } else if (node.isBranch()) {
     1768            node.setTakenBlockIndex(m_graph.blockIndexForBytecodeOffset(node.takenBytecodeOffsetDuringParsing()));
     1769            node.setNotTakenBlockIndex(m_graph.blockIndexForBytecodeOffset(node.notTakenBytecodeOffsetDuringParsing()));
     1770            m_graph.m_blocks[node.takenBlockIndex()]->m_predecessors.append(index);
     1771            m_graph.m_blocks[node.notTakenBlockIndex()]->m_predecessors.append(index);
    17691772        }
    17701773    }
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r96567 r97218  
    189189    }
    190190    if  (node.isBranch() || node.isJump()) {
    191         printf("%sT:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.takenBytecodeOffset()));
     191        printf("%sT:#%u", hasPrinted ? ", " : "", node.takenBlockIndex());
    192192        hasPrinted = true;
    193193    }
    194194    if  (node.isBranch()) {
    195         printf("%sF:#%u", hasPrinted ? ", " : "", blockIndexForBytecodeOffset(node.notTakenBytecodeOffset()));
     195        printf("%sF:#%u", hasPrinted ? ", " : "", node.notTakenBlockIndex());
    196196        hasPrinted = true;
    197197    }
     
    240240{
    241241    for (size_t b = 0; b < m_blocks.size(); ++b) {
    242         printf("Block #%u (bc#%u):  %s\n", (int)b, m_blocks[b]->bytecodeBegin, m_blocks[b]->isOSRTarget ? " (OSR target)" : "");
    243         for (size_t i = m_blocks[b]->begin; i < m_blocks[b]->end; ++i)
     242        BasicBlock* block = m_blocks[b].get();
     243        printf("Block #%u (bc#%u):  %s\n", (int)b, block->bytecodeBegin, block->isOSRTarget ? " (OSR target)" : "");
     244        printf("  vars: ");
     245        if (block->cfaHasVisited)
     246            dumpOperands(block->valuesAtHead, stdout);
     247        else
     248            printf("<empty>");
     249        printf("\n");
     250        for (size_t i = block->begin; i < block->end; ++i)
    244251            dump(i, codeBlock);
    245252    }
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r97197 r97218  
    3030
    3131#include "CodeBlock.h"
     32#include "DFGBasicBlock.h"
    3233#include "DFGNode.h"
    3334#include "PredictionTracker.h"
     
    4546namespace DFG {
    4647
    47 // helper function to distinguish vars & temporaries from arguments.
    48 inline bool operandIsArgument(int operand) { return operand < 0; }
    49 
    50 typedef uint32_t BlockIndex;
    51 
    52 // For every local variable we track any existing get or set of the value.
    53 // We track the get so that these may be shared, and we track the set to
    54 // retrieve the current value, and to reference the final definition.
    55 struct VariableRecord {
    56     VariableRecord()
    57         : value(NoNode)
    58     {
    59     }
    60    
    61     void setFirstTime(NodeIndex nodeIndex)
    62     {
    63         ASSERT(value == NoNode);
    64         value = nodeIndex;
    65     }
    66 
    67     NodeIndex value;
    68 };
    69 
    7048struct MethodCheckData {
    7149    // It is safe to refer to these directly because they are shadowed by
     
    11189    unsigned identifierNumber;
    11290    unsigned resolveInfoIndex;
    113 };
    114 
    115 typedef Vector <BlockIndex, 2> PredecessorList;
    116 
    117 struct BasicBlock {
    118     BasicBlock(unsigned bytecodeBegin, NodeIndex begin, unsigned numArguments, unsigned numLocals)
    119         : bytecodeBegin(bytecodeBegin)
    120         , begin(begin)
    121         , end(NoNode)
    122         , isOSRTarget(false)
    123         , m_argumentsAtHead(numArguments)
    124         , m_localsAtHead(numLocals)
    125         , m_argumentsAtTail(numArguments)
    126         , m_localsAtTail(numLocals)
    127     {
    128     }
    129 
    130     static inline BlockIndex getBytecodeBegin(OwnPtr<BasicBlock>* block)
    131     {
    132         return (*block)->bytecodeBegin;
    133     }
    134 
    135     unsigned bytecodeBegin;
    136     NodeIndex begin;
    137     NodeIndex end;
    138     bool isOSRTarget;
    139 
    140     PredecessorList m_predecessors;
    141    
    142     Vector<VariableRecord, 8> m_argumentsAtHead;
    143     Vector<VariableRecord, 16> m_localsAtHead;
    144    
    145     Vector<VariableRecord, 8> m_argumentsAtTail;
    146     Vector<VariableRecord, 16> m_localsAtTail;
    14791};
    14892
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator.h

    r97216 r97218  
    15161516    }
    15171517
     1518    BasicBlock* block()
     1519    {
     1520        return m_jit.graph().m_blocks[m_block].get();
     1521    }
     1522
    15181523#ifndef NDEBUG
    15191524    void dump(const char* label = 0);
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator32_64.cpp

    r97189 r97218  
    966966{
    967967    Node& branchNode = at(branchNodeIndex);
    968     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    969     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     968    BlockIndex taken = branchNode.takenBlockIndex();
     969    BlockIndex notTaken = branchNode.notTakenBlockIndex();
    970970   
    971971    if (taken == (m_block + 1)) {
     
    10291029{
    10301030    Node& branchNode = at(branchNodeIndex);
    1031     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    1032     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     1031    BlockIndex taken = branchNode.takenBlockIndex();
     1032    BlockIndex notTaken = branchNode.notTakenBlockIndex();
    10331033
    10341034    JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
     
    11581158{
    11591159    Node& branchNode = at(branchNodeIndex);
    1160     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    1161     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     1160    BlockIndex taken = branchNode.takenBlockIndex();
     1161    BlockIndex notTaken = branchNode.notTakenBlockIndex();
    11621162
    11631163    // The branch instruction will branch to the taken block.
  • trunk/Source/JavaScriptCore/dfg/DFGJITCodeGenerator64.cpp

    r97153 r97218  
    928928{
    929929    Node& branchNode = at(branchNodeIndex);
    930     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    931     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     930    BlockIndex taken = branchNode.takenBlockIndex();
     931    BlockIndex notTaken = branchNode.notTakenBlockIndex();
    932932   
    933933    if (taken == (m_block + 1)) {
     
    989989{
    990990    Node& branchNode = at(branchNodeIndex);
    991     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    992     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     991    BlockIndex taken = branchNode.takenBlockIndex();
     992    BlockIndex notTaken = branchNode.notTakenBlockIndex();
    993993
    994994    JITCompiler::ResultCondition callResultCondition = JITCompiler::NonZero;
     
    11111111{
    11121112    Node& branchNode = at(branchNodeIndex);
    1113     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    1114     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     1113    BlockIndex taken = branchNode.takenBlockIndex();
     1114    BlockIndex notTaken = branchNode.notTakenBlockIndex();
    11151115
    11161116    // The branch instruction will branch to the taken block.
  • trunk/Source/JavaScriptCore/dfg/DFGJITCompiler.h

    r97071 r97218  
    405405        OSREntryData* entry = codeBlock()->appendDFGOSREntryData(basicBlock.bytecodeBegin, differenceBetween(m_startOfCode, label()));
    406406       
    407         ActionablePredictions actionablePredictions(basicBlock.m_argumentsAtHead.size(), basicBlock.m_localsAtHead.size());
    408 
    409         for (unsigned i = 0; i < basicBlock.m_argumentsAtHead.size(); ++i) {
    410             NodeIndex nodeIndex = basicBlock.m_argumentsAtHead[i].value;
    411             if (nodeIndex != NoNode)
    412                 actionablePredictions.setArgument(i, actionablePredictionFromPredictedType(m_graph[nodeIndex].variableAccessData()->prediction()));
    413         }
     407        entry->m_expectedValues = basicBlock.valuesAtHead;
    414408       
    415         for (unsigned i = 0; i < basicBlock.m_localsAtHead.size(); ++i) {
    416             NodeIndex nodeIndex = basicBlock.m_localsAtHead[i].value;
    417             if (nodeIndex != NoNode)
    418                 actionablePredictions.setVariable(i, actionablePredictionFromPredictedType(m_graph[nodeIndex].variableAccessData()->prediction()));
    419         }
    420        
    421         actionablePredictions.pack();
    422        
    423         entry->m_predictions = actionablePredictions;
     409        // Fix the expected values: in our protocol, a dead variable will have an expected
     410        // value of (None, []). But the old JIT may stash some values there. So we really
     411        // need (Top, TOP).
     412        for (size_t argument = 0; argument < basicBlock.variablesAtHead.numberOfArguments(); ++argument) {
     413            if (basicBlock.variablesAtHead.argument(argument) == NoNode)
     414                entry->m_expectedValues.argument(argument).makeTop();
     415        }
     416        for (size_t local = 0; local < basicBlock.variablesAtHead.numberOfLocals(); ++local) {
     417            if (basicBlock.variablesAtHead.local(local) == NoNode)
     418                entry->m_expectedValues.local(local).makeTop();
     419        }
    424420#else
    425421        UNUSED_PARAM(basicBlock);
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r97030 r97218  
    2727#define DFGNode_h
    2828
    29 #include "DFGStructureSet.h"
    3029#include <wtf/BoundsCheckedPointer.h>
    3130#include <wtf/Platform.h>
    32 #include <wtf/UnionFind.h>
    3331
    3432// Emit various logging information for debugging, including dumping the dataflow graphs.
     
    6866
    6967#include "CodeBlock.h"
     68#include "DFGOperands.h"
     69#include "DFGVariableAccessData.h"
    7070#include "JSValue.h"
    7171#include "PredictedType.h"
     
    7575namespace JSC { namespace DFG {
    7676
    77 // Type for a virtual register number (spill location).
    78 // Using an enum to make this type-checked at compile time, to avert programmer errors.
    79 enum VirtualRegister { InvalidVirtualRegister = -1 };
    80 COMPILE_ASSERT(sizeof(VirtualRegister) == sizeof(int), VirtualRegister_is_32bit);
    81 
    8277// Type for a reference to another node in the graph.
    8378typedef uint32_t NodeIndex;
    8479static const NodeIndex NoNode = UINT_MAX;
     80
     81typedef uint32_t BlockIndex;
     82
     83struct NodeIndexTraits {
     84    static NodeIndex defaultValue() { return NoNode; }
     85};
    8586
    8687// Information used to map back from an exception to any handler/source information,
     
    109110private:
    110111    uint32_t m_bytecodeIndex;
    111 };
    112 
    113 class VariableAccessData: public UnionFind<VariableAccessData> {
    114 public:
    115     VariableAccessData()
    116         : m_local(static_cast<VirtualRegister>(std::numeric_limits<int>::min()))
    117         , m_prediction(PredictNone)
    118     {
    119     }
    120    
    121     VariableAccessData(VirtualRegister local)
    122         : m_local(local)
    123         , m_prediction(PredictNone)
    124     {
    125     }
    126    
    127     VirtualRegister local()
    128     {
    129         ASSERT(m_local == find()->m_local);
    130         return m_local;
    131     }
    132    
    133     int operand()
    134     {
    135         return static_cast<int>(local());
    136     }
    137    
    138     bool predict(PredictedType prediction)
    139     {
    140         return mergePrediction(find()->m_prediction, prediction);
    141     }
    142    
    143     PredictedType prediction()
    144     {
    145         return find()->m_prediction;
    146     }
    147    
    148 private:
    149     // This is slightly space-inefficient, since anything we're unified with
    150     // will have the same operand and should have the same prediction. But
    151     // putting them here simplifies the code, and we don't expect DFG space
    152     // usage for variable access nodes do be significant.
    153 
    154     VirtualRegister m_local;
    155     PredictedType m_prediction;
    156112};
    157113
     
    565521    VariableAccessData* variableAccessData()
    566522    {
     523        ASSERT(hasVariableAccessData());
    567524        return reinterpret_cast<VariableAccessData*>(m_opInfo)->find();
    568525    }
     
    756713    }
    757714
    758     unsigned takenBytecodeOffset()
     715    unsigned takenBytecodeOffsetDuringParsing()
    759716    {
    760717        ASSERT(isBranch() || isJump());
     
    762719    }
    763720
    764     unsigned notTakenBytecodeOffset()
     721    unsigned notTakenBytecodeOffsetDuringParsing()
     722    {
     723        ASSERT(isBranch());
     724        return m_opInfo2;
     725    }
     726   
     727    void setTakenBlockIndex(BlockIndex blockIndex)
     728    {
     729        ASSERT(isBranch() || isJump());
     730        m_opInfo = blockIndex;
     731    }
     732   
     733    void setNotTakenBlockIndex(BlockIndex blockIndex)
     734    {
     735        ASSERT(isBranch());
     736        m_opInfo2 = blockIndex;
     737    }
     738   
     739    BlockIndex takenBlockIndex()
     740    {
     741        ASSERT(isBranch() || isJump());
     742        return m_opInfo;
     743    }
     744   
     745    BlockIndex notTakenBlockIndex()
    765746    {
    766747        ASSERT(isBranch());
  • trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp

    r96375 r97218  
    7878    //    OSR at this time.
    7979   
    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()) {
     80    for (size_t argument = 0; argument < entry->m_expectedValues.numberOfArguments(); ++argument) {
     81        if (argument >= exec->argumentCountIncludingThis()) {
    8682#if ENABLE(JIT_VERBOSE_OSR)
    87             printf("    OSR failed because argument %u was not passed, expected %s.\n", i, actionablePredictionToString(prediction));
     83            printf("    OSR failed because argument %lu was not passed, expected ", argument);
     84            entry->m_expectedValues.argument(argument).dump(stdout);
     85            printf(".\n");
    8886#endif
    8987            return 0;
    9088        }
    9189       
    92         if (!valueObeysPrediction(globalData, exec->argument(i - 1), prediction)) {
     90        JSValue value;
     91        if (!argument)
     92            value = exec->hostThisValue();
     93        else
     94            value = exec->argument(argument - 1);
     95       
     96        if (!entry->m_expectedValues.argument(argument).validate(value)) {
    9397#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));
     98            printf("    OSR failed because argument %lu is %s, expected ", argument, value.description());
     99            entry->m_expectedValues.argument(argument).dump(stdout);
     100            printf(".\n");
    95101#endif
    96102            return 0;
     
    98104    }
    99105   
    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)) {
     106    for (size_t local = 0; local < entry->m_expectedValues.numberOfLocals(); ++local) {
     107        if (!entry->m_expectedValues.local(local).validate(exec->registers()[local].jsValue())) {
    106108#if ENABLE(JIT_VERBOSE_OSR)
    107             printf("    OSR failed because variable %u is %s, expected %s.\n", i, exec->registers()[i].jsValue().description(), actionablePredictionToString(prediction));
     109            printf("    OSR failed because variable %lu is %s, expected ", local, exec->registers()[local].jsValue().description());
     110            entry->m_expectedValues.local(local).dump(stdout);
     111            printf(".\n");
    108112#endif
    109113            return 0;
  • trunk/Source/JavaScriptCore/dfg/DFGOSREntry.h

    r96375 r97218  
    2727#define DFGOSREntry_h
    2828
    29 #include "ActionablePrediction.h"
     29#include "DFGAbstractValue.h"
     30#include "DFGOperands.h"
    3031
    3132namespace JSC {
     
    4041    unsigned m_bytecodeIndex;
    4142    unsigned m_machineCodeOffset;
    42     ActionablePredictions m_predictions;
     43    Operands<AbstractValue> m_expectedValues;
    4344};
    4445
  • trunk/Source/JavaScriptCore/dfg/DFGPropagator.cpp

    r97197 r97218  
    2929#if ENABLE(DFG_JIT)
    3030
     31#include "DFGAbstractState.h"
    3132#include "DFGGraph.h"
    3233#include "DFGScoreBoard.h"
     
    5657    {
    5758#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    58     m_graph.dump(m_codeBlock);
    59 #endif
    60 
    61 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    62         m_count = 0;
    63 #endif
    64         do {
    65             m_changed = false;
    66            
    67             // Up here we start with a backward pass because we suspect that to be
    68             // more profitable.
    69             propagateArithNodeFlagsBackward();
    70             if (!m_changed)
    71                 break;
    72            
    73             m_changed = false;
    74             propagateArithNodeFlagsForward();
    75         } while (m_changed);
    76        
    77 #if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    78         m_count = 0;
    79 #endif
    80         do {
    81             m_changed = false;
    82            
    83             // Forward propagation is near-optimal for both topologically-sorted and
    84             // DFS-sorted code.
    85             propagatePredictionsForward();
    86             if (!m_changed)
    87                 break;
    88            
    89             // Backward propagation reduces the likelihood that pathological code will
    90             // cause slowness. Loops (especially nested ones) resemble backward flow.
    91             // This pass captures two cases: (1) it detects if the forward fixpoint
    92             // found a sound solution and (2) short-circuits backward flow.
    93             m_changed = false;
    94             propagatePredictionsBackward();
    95         } while (m_changed);
    96        
     59        m_graph.dump(m_codeBlock);
     60#endif
     61
     62        propagateArithNodeFlags();
     63        propagatePredictions();
    9764        fixup();
    9865       
     
    11077
    11178        allocateVirtualRegisters();
     79
     80#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     81        printf("Graph after virtual register allocation:\n");
     82        m_graph.dump(m_codeBlock);
     83#endif
     84
     85        globalCFA();
    11286
    11387#if ENABLE(DFG_DEBUG_VERBOSE)
     
    273247        for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;)
    274248            propagateArithNodeFlags(m_graph[m_compileIndex]);
     249    }
     250   
     251    void propagateArithNodeFlags()
     252    {
     253#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     254        m_count = 0;
     255#endif
     256        do {
     257            m_changed = false;
     258           
     259            // Up here we start with a backward pass because we suspect that to be
     260            // more profitable.
     261            propagateArithNodeFlagsBackward();
     262            if (!m_changed)
     263                break;
     264           
     265            m_changed = false;
     266            propagateArithNodeFlagsForward();
     267        } while (m_changed);
    275268    }
    276269   
     
    609602
    610603#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
    611         printf("%s ", predictionToString(m_graph[m_compileIndex].prediction()));
     604        printf("%s\n", predictionToString(m_graph[m_compileIndex].prediction()));
    612605#endif
    613606       
     
    631624        for (m_compileIndex = m_graph.size(); m_compileIndex-- > 0;)
    632625            propagateNodePredictions(m_graph[m_compileIndex]);
     626    }
     627   
     628    void propagatePredictions()
     629    {
     630#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     631        m_count = 0;
     632#endif
     633        do {
     634            m_changed = false;
     635           
     636            // Forward propagation is near-optimal for both topologically-sorted and
     637            // DFS-sorted code.
     638            propagatePredictionsForward();
     639            if (!m_changed)
     640                break;
     641           
     642            // Backward propagation reduces the likelihood that pathological code will
     643            // cause slowness. Loops (especially nested ones) resemble backward flow.
     644            // This pass captures two cases: (1) it detects if the forward fixpoint
     645            // found a sound solution and (2) short-circuits backward flow.
     646            m_changed = false;
     647            propagatePredictionsBackward();
     648        } while (m_changed);
    633649    }
    634650   
     
    14541470    }
    14551471   
     1472    void performBlockCFA(AbstractState& state, BlockIndex blockIndex)
     1473    {
     1474        BasicBlock* block = m_graph.m_blocks[blockIndex].get();
     1475        if (!block->cfaShouldRevisit)
     1476            return;
     1477#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     1478        printf("   Block #%u (bc#%u):\n", blockIndex, block->bytecodeBegin);
     1479#endif
     1480        state.beginBasicBlock(block);
     1481#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     1482        printf("      head vars: ");
     1483        dumpOperands(block->valuesAtHead, stdout);
     1484        printf("\n");
     1485#endif
     1486        for (NodeIndex nodeIndex = block->begin; nodeIndex < block->end; ++nodeIndex) {
     1487            if (!m_graph[nodeIndex].shouldGenerate())
     1488                continue;
     1489#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     1490            printf("      %s @%u: ", Graph::opName(m_graph[nodeIndex].op), nodeIndex);
     1491            state.dump(stdout);
     1492            printf("\n");
     1493#endif
     1494            if (!state.execute(nodeIndex))
     1495                break;
     1496        }
     1497#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     1498        printf("      tail regs: ");
     1499        state.dump(stdout);
     1500        printf("\n");
     1501#endif
     1502        m_changed |= state.endBasicBlock(AbstractState::MergeToSuccessors);
     1503#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     1504        printf("      tail vars: ");
     1505        dumpOperands(block->valuesAtTail, stdout);
     1506        printf("\n");
     1507#endif
     1508    }
     1509   
     1510    void performForwardCFA(AbstractState& state)
     1511    {
     1512#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     1513        printf("CFA [%u]\n", ++m_count);
     1514#endif
     1515       
     1516        for (BlockIndex block = 0; block < m_graph.m_blocks.size(); ++block)
     1517            performBlockCFA(state, block);
     1518    }
     1519   
     1520    void globalCFA()
     1521    {
     1522#if ENABLE(DFG_DEBUG_PROPAGATION_VERBOSE)
     1523        m_count = 0;
     1524#endif
     1525       
     1526        // This implements a pseudo-worklist-based forward CFA, except that the visit order
     1527        // of blocks is the bytecode program order (which is nearly topological), and
     1528        // instead of a worklist we just walk all basic blocks checking if cfaShouldRevisit
     1529        // is set to true. This is likely to balance the efficiency properties of both
     1530        // worklist-based and forward fixpoint-based approaches. Like a worklist-based
     1531        // approach, it won't visit code if it's meaningless to do so (nothing changed at
     1532        // the head of the block or the predecessors have not been visited). Like a forward
     1533        // fixpoint-based approach, it has a high probability of only visiting a block
     1534        // after all predecessors have been visited. Only loops will cause this analysis to
     1535        // revisit blocks, and the amount of revisiting is proportional to loop depth.
     1536       
     1537        AbstractState::initialize(m_graph);
     1538       
     1539        AbstractState state(m_codeBlock, m_graph);
     1540       
     1541        do {
     1542            m_changed = false;
     1543            performForwardCFA(state);
     1544        } while (m_changed);
     1545    }
     1546   
    14561547    Graph& m_graph;
    14571548    JSGlobalData& m_globalData;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r97197 r97218  
    132132{
    133133    Node& branchNode = at(branchNodeIndex);
    134     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    135     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     134    BlockIndex taken = branchNode.takenBlockIndex();
     135    BlockIndex notTaken = branchNode.notTakenBlockIndex();
    136136   
    137137    SpeculateDoubleOperand op1(this, node.child1());
     
    144144}
    145145
    146 void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr)
     146void SpeculativeJIT::compilePeepHoleObjectEquality(Node& node, NodeIndex branchNodeIndex, void* vptr, PredictionChecker predictionCheck)
    147147{
    148148    Node& branchNode = at(branchNodeIndex);
    149     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    150     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     149    BlockIndex taken = branchNode.takenBlockIndex();
     150    BlockIndex notTaken = branchNode.notTakenBlockIndex();
    151151
    152152    MacroAssembler::RelationalCondition condition = MacroAssembler::Equal;
     
    165165    GPRReg op2GPR = op2.gpr();
    166166   
    167     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
    168     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
     167    if (!predictionCheck(m_state.forNode(node.child1()).m_type))
     168        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
     169    if (!predictionCheck(m_state.forNode(node.child2()).m_type))
     170        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
    169171   
    170172    addBranch(m_jit.branchPtr(condition, op1GPR, op2GPR), taken);
     
    176178{
    177179    Node& branchNode = at(branchNodeIndex);
    178     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.takenBytecodeOffset());
    179     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(branchNode.notTakenBytecodeOffset());
     180    BlockIndex taken = branchNode.takenBlockIndex();
     181    BlockIndex notTaken = branchNode.notTakenBlockIndex();
    180182
    181183    // The branch instruction will branch to the taken block.
     
    226228            use(node.child2());
    227229        } else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2()))) {
    228             compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr);
     230            compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction);
    229231            use(node.child1());
    230232            use(node.child2());
    231233        } else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2()))) {
    232             compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr);
     234            compilePeepHoleObjectEquality(node, branchNodeIndex, m_jit.globalData()->jsArrayVPtr, isArrayPrediction);
    233235            use(node.child1());
    234236            use(node.child2());
     
    263265#endif
    264266
    265     ASSERT(m_arguments.size() == block.m_argumentsAtHead.size());
     267    ASSERT(m_arguments.size() == block.variablesAtHead.numberOfArguments());
    266268    for (size_t i = 0; i < m_arguments.size(); ++i) {
    267         NodeIndex nodeIndex = block.m_argumentsAtHead[i].value;
     269        NodeIndex nodeIndex = block.variablesAtHead.argument(i);
    268270        if (nodeIndex == NoNode)
    269271            m_arguments[i] = ValueSource(ValueInRegisterFile);
     
    272274    }
    273275   
    274     ASSERT(m_variables.size() == block.m_localsAtHead.size());
     276    m_state.reset();
     277    m_state.beginBasicBlock(&block);
     278   
     279    ASSERT(m_variables.size() == block.variablesAtHead.numberOfLocals());
    275280    for (size_t i = 0; i < m_variables.size(); ++i) {
    276         NodeIndex nodeIndex = block.m_localsAtHead[i].value;
     281        NodeIndex nodeIndex = block.variablesAtHead.local(i);
    277282        if (nodeIndex == NoNode)
    278283            m_variables[i] = ValueSource(ValueInRegisterFile);
     
    343348        fprintf(stderr, "\n");
    344349#endif
     350       
     351        // Make sure that the abstract state is rematerialized for the next node.
     352        m_state.execute(m_compileIndex);
    345353       
    346354        if (node.shouldGenerate())
     
    544552    GPRReg indexReg = index.gpr();
    545553   
    546     if (!isKnownString(node.child1()))
     554    if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
    547555        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(stringReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
    548556   
     
    573581    GPRReg propertyReg = property.gpr();
    574582
    575     if (!isKnownString(node.child1()))
     583    if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
    576584        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
    577585
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r97153 r97218  
    2929#if ENABLE(DFG_JIT)
    3030
     31#include <dfg/DFGAbstractState.h>
    3132#include <dfg/DFGJITCodeGenerator.h>
    3233
     
    434435    }
    435436   
    436     bool isKnownArray(NodeIndex op1)
    437     {
    438         Node& node = at(op1);
    439         switch (node.op) {
    440         case GetLocal:
    441             return isArrayPrediction(node.variableAccessData()->prediction());
    442            
    443         case NewArray:
    444         case NewArrayBuffer:
    445             return true;
    446            
    447         default:
    448             return false;
    449         }
    450     }
    451 
    452     bool isKnownString(NodeIndex op1)
    453     {
    454         switch (at(op1).op) {
    455         case StrCat:
    456             return true;
    457            
    458         default:
    459             return false;
    460         }
    461     }
    462    
    463437    bool compare(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
    464438    bool compilePeepHoleBranch(Node&, MacroAssembler::RelationalCondition, MacroAssembler::DoubleCondition, S_DFGOperation_EJJ);
    465439    void compilePeepHoleIntegerBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::RelationalCondition);
    466440    void compilePeepHoleDoubleBranch(Node&, NodeIndex branchNodeIndex, JITCompiler::DoubleCondition);
    467     void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, void* vptr);
    468     void compileObjectEquality(Node&, void* vptr);
     441    void compilePeepHoleObjectEquality(Node&, NodeIndex branchNodeIndex, void* vptr, PredictionChecker);
     442    void compileObjectEquality(Node&, void* vptr, PredictionChecker);
    469443    void compileValueAdd(Node&);
    470     void compileObjectOrOtherLogicalNot(NodeIndex value, void* vptr);
     444    void compileObjectOrOtherLogicalNot(NodeIndex value, void* vptr, bool needSpeculationCheck);
    471445    void compileLogicalNot(Node&);
    472     void emitObjectOrOtherBranch(NodeIndex value, BlockIndex taken, BlockIndex notTaken, void *vptr);
     446    void emitObjectOrOtherBranch(NodeIndex value, BlockIndex taken, BlockIndex notTaken, void *vptr, bool needSpeculationCheck);
    473447    void emitBranch(Node&);
    474448   
     
    592566    uint32_t m_bytecodeIndexForOSR;
    593567   
     568    AbstractState m_state;
     569   
    594570    ValueRecovery computeValueRecoveryFor(const ValueSource&);
    595571
     
    824800    , m_lastSetOperand(std::numeric_limits<int>::max())
    825801    , m_bytecodeIndexForOSR(std::numeric_limits<uint32_t>::max())
     802    , m_state(m_jit.codeBlock(), m_jit.graph())
    826803{
    827804}
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r97189 r97218  
    359359}
    360360
    361 void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr)
     361void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr, PredictionChecker predictionCheck)
    362362{
    363363    SpeculateCellOperand op1(this, node.child1());
     
    371371    GPRReg resultPayloadGPR = resultPayload.gpr();
    372372   
    373     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
    374     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
     373    if (!predictionCheck(m_state.forNode(node.child1()).m_type))
     374        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
     375    if (!predictionCheck(m_state.forNode(node.child2()).m_type))
     376        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
    375377   
    376378    MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
     
    392394
    393395    if (Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2())))
    394         compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr);
     396        compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction);
    395397    else if (Node::shouldSpeculateArray(at(node.child1()), at(node.child2())))
    396         compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr);
     398        compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr, isArrayPrediction);
    397399    else if (!at(node.child1()).shouldSpeculateNumber() && !at(node.child2()).shouldSpeculateNumber())
    398400        nonSpeculativeNonPeepholeCompare(node, condition, operation);
     
    450452}
    451453
    452 void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void* vptr)
     454void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void* vptr, bool needSpeculationCheck)
    453455{
    454456    JSValueOperand value(this, nodeIndex);
     
    463465   
    464466    MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
    465     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR), MacroAssembler::TrustedImmPtr(vptr)));
     467    if (needSpeculationCheck)
     468        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR), MacroAssembler::TrustedImmPtr(vptr)));
    466469    m_jit.move(TrustedImm32(0), resultPayloadGPR);
    467470    MacroAssembler::Jump done = m_jit.jump();
     
    470473 
    471474    COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
    472     m_jit.move(valueTagGPR, resultPayloadGPR);
    473     m_jit.or32(TrustedImm32(1), resultPayloadGPR);
    474     speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, resultPayloadGPR, TrustedImm32(JSValue::NullTag)));
     475    if (needSpeculationCheck) {
     476        m_jit.move(valueTagGPR, resultPayloadGPR);
     477        m_jit.or32(TrustedImm32(1), resultPayloadGPR);
     478        speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, resultPayloadGPR, TrustedImm32(JSValue::NullTag)));
     479    }
    475480    m_jit.move(TrustedImm32(1), resultPayloadGPR);
    476481   
     
    485490
    486491    if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
    487         compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr);
     492        compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
    488493        return;
    489494    }
    490495    if (at(node.child1()).shouldSpeculateArrayOrOther()) {
    491         compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr);
     496        compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
    492497        return;
    493498    }
     
    555560}
    556561
    557 void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr)
     562void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr, bool needSpeculationCheck)
    558563{
    559564    JSValueOperand value(this, nodeIndex);
     
    564569   
    565570    MacroAssembler::Jump notCell = m_jit.branch32(MacroAssembler::NotEqual, valueTagGPR, TrustedImm32(JSValue::CellTag));
    566     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR), MacroAssembler::TrustedImmPtr(vptr)));
     571    if (needSpeculationCheck)
     572        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valuePayloadGPR), MacroAssembler::TrustedImmPtr(vptr)));
    567573    addBranch(m_jit.jump(), taken);
    568574   
     
    570576   
    571577    COMPILE_ASSERT((JSValue::UndefinedTag | 1) == JSValue::NullTag, UndefinedTag_OR_1_EQUALS_NullTag);
    572     m_jit.move(valueTagGPR, scratchGPR);
    573     m_jit.or32(TrustedImm32(1), scratchGPR);
    574     speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag)));
     578    if (needSpeculationCheck) {
     579        m_jit.move(valueTagGPR, scratchGPR);
     580        m_jit.or32(TrustedImm32(1), scratchGPR);
     581        speculationCheck(m_jit.branch32(MacroAssembler::NotEqual, scratchGPR, TrustedImm32(JSValue::NullTag)));
     582    }
    575583
    576584    if (notTaken != (m_block + 1))
     
    582590void SpeculativeJIT::emitBranch(Node& node)
    583591{
    584     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
    585     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
     592    BlockIndex taken = node.takenBlockIndex();
     593    BlockIndex notTaken = node.notTakenBlockIndex();
    586594
    587595    // FIXME: Add fast cases for known Boolean!
    588596
    589597    if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
    590         emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr);
     598        emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
    591599    } else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
    592         emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr);
     600        emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
    593601    } else if (at(node.child1()).shouldSpeculateNumber()) {
    594602        if (at(node.child1()).shouldSpeculateInteger()) {
     
    656664    case GetLocal: {
    657665        PredictedType prediction = node.variableAccessData()->prediction();
     666        AbstractValue& value = block()->valuesAtHead.operand(node.local());
    658667
    659668        // If we have no prediction for this local, then don't attempt to compile.
     
    696705        m_gprs.retain(tag.gpr(), virtualRegister, SpillOrderJS);
    697706
    698         DataFormat format = isBooleanPrediction(prediction) ? DataFormatJSBoolean : DataFormatJS;
     707        DataFormat format;
     708        if (isCellPrediction(value.m_type))
     709            format = DataFormatJSCell;
     710        else if (isBooleanPrediction(value.m_type))
     711            format = DataFormatJSBoolean;
     712        else
     713            format = DataFormatJS;
     714
    699715        m_generationInfo[virtualRegister].initJSValue(m_compileIndex, node.refCount(), tag.gpr(), result.gpr(), format);
    700716        break;
     
    725741            SpeculateCellOperand cell(this, node.child1());
    726742            GPRReg cellGPR = cell.gpr();
    727             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
     743            if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
     744                speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    728745            m_jit.storePtr(cellGPR, JITCompiler::payloadFor(node.local()));
    729746            noResult(m_compileIndex);
     
    13281345        // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
    13291346        // If we have predicted the base to be type array, we can skip the check.
    1330         if (!isKnownArray(node.child1()))
     1347        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
    13311348            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    13321349        speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
     
    13811398        // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
    13821399        // If we have predicted the base to be type array, we can skip the check.
    1383         if (!isKnownArray(node.child1()))
     1400        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
    13841401            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    13851402
     
    14631480        writeBarrier(baseGPR, valueTagGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
    14641481
    1465         if (!isKnownArray(node.child1()))
     1482        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
    14661483            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    14671484       
     
    15091526        GPRReg storageLengthGPR = storageLength.gpr();
    15101527       
    1511         if (!isKnownArray(node.child1()))
     1528        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
    15121529            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    15131530       
     
    15561573
    15571574    case DFG::Jump: {
    1558         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
     1575        BlockIndex taken = node.takenBlockIndex();
    15591576        if (taken != (m_block + 1))
    15601577            addBranch(m_jit.jump(), taken);
     
    15671584            SpeculateIntegerOperand op(this, node.child1());
    15681585           
    1569             BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
    1570             BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
     1586            BlockIndex taken = node.takenBlockIndex();
     1587            BlockIndex notTaken = node.notTakenBlockIndex();
    15711588           
    15721589            MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
     
    17801797            SpeculateCellOperand thisValue(this, node.child1());
    17811798           
    1782             speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
     1799            if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
     1800                speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
    17831801           
    17841802            cellResult(thisValue.gpr(), m_compileIndex);
     
    18221840        // that it's a FinalObject then we speculate on that directly. Otherwise we
    18231841        // do the slow (structure-based) check.
    1824         if (at(node.child1()).shouldSpeculateFinalObject())
    1825             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr)));
    1826         else {
     1842        if (at(node.child1()).shouldSpeculateFinalObject()) {
     1843            if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
     1844                speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr)));
     1845        } else {
    18271846            m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
    18281847            slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
     
    19601979        GPRReg resultGPR = result.gpr();
    19611980       
    1962         if (!isKnownArray(node.child1()))
     1981        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
    19631982            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    19641983       
     
    19791998        GPRReg resultGPR = result.gpr();
    19801999       
    1981         if (!isKnownString(node.child1()))
     2000        if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
    19822001            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
    19832002       
     
    19962015
    19972016    case CheckStructure: {
     2017        if (m_state.forNode(node.child1()).m_structure.isSubsetOf(node.structureSet())) {
     2018            noResult(m_compileIndex);
     2019            break;
     2020        }
     2021       
    19982022        SpeculateCellOperand base(this, node.child1());
    19992023       
     
    21222146        GPRReg scratchGPR = scratch.gpr();
    21232147       
    2124         speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure)));
     2148        if (!m_state.forNode(node.child1()).m_structure.doesNotContainAnyOtherThan(methodCheckData.structure))
     2149            speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure)));
    21252150        if (methodCheckData.prototype != m_jit.codeBlock()->globalObject()->methodCallDummy()) {
    21262151            m_jit.move(JITCompiler::TrustedImmPtr(methodCheckData.prototype->structureAddress()), scratchGPR);
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r97153 r97218  
    490490}
    491491
    492 void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr)
     492void SpeculativeJIT::compileObjectEquality(Node& node, void* vptr, PredictionChecker predictionCheck)
    493493{
    494494    SpeculateCellOperand op1(this, node.child1());
     
    500500    GPRReg resultGPR = result.gpr();
    501501   
    502     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
    503     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
     502    if (!predictionCheck(m_state.forNode(node.child1()).m_type))
     503        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op1GPR), MacroAssembler::TrustedImmPtr(vptr)));
     504    if (!predictionCheck(m_state.forNode(node.child2()).m_type))
     505        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(op2GPR), MacroAssembler::TrustedImmPtr(vptr)));
    504506   
    505507    MacroAssembler::Jump falseCase = m_jit.branchPtr(MacroAssembler::NotEqual, op1GPR, op2GPR);
     
    541543        jsValueResult(result.gpr(), m_compileIndex, DataFormatJSBoolean);
    542544    } else if (node.op == CompareEq && Node::shouldSpeculateFinalObject(at(node.child1()), at(node.child2())))
    543         compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr);
     545        compileObjectEquality(node, m_jit.globalData()->jsFinalObjectVPtr, isFinalObjectPrediction);
    544546    else if (node.op == CompareEq && Node::shouldSpeculateArray(at(node.child1()), at(node.child2())))
    545         compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr);
     547        compileObjectEquality(node, m_jit.globalData()->jsArrayVPtr, isArrayPrediction);
    546548    else
    547549        nonSpeculativeNonPeepholeCompare(node, condition, operation);
     
    569571}
    570572
    571 void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void *vptr)
     573void SpeculativeJIT::compileObjectOrOtherLogicalNot(NodeIndex nodeIndex, void *vptr, bool needSpeculationCheck)
    572574{
    573575    JSValueOperand value(this, nodeIndex);
     
    577579   
    578580    MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
    579     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr)));
     581    if (needSpeculationCheck)
     582        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr)));
    580583    m_jit.move(TrustedImm32(static_cast<int32_t>(ValueFalse)), resultGPR);
    581584    MacroAssembler::Jump done = m_jit.jump();
     
    583586    notCell.link(&m_jit);
    584587   
    585     m_jit.move(valueGPR, resultGPR);
    586     m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
    587     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, resultGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
     588    if (needSpeculationCheck) {
     589        m_jit.move(valueGPR, resultGPR);
     590        m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), resultGPR);
     591        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, resultGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
     592    }
    588593    m_jit.move(TrustedImm32(static_cast<int32_t>(ValueTrue)), resultGPR);
    589594   
     
    606611    }
    607612    if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
    608         compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr);
     613        compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
    609614        return;
    610615    }
    611616    if (at(node.child1()).shouldSpeculateArrayOrOther()) {
    612         compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr);
     617        compileObjectOrOtherLogicalNot(node.child1(), m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
    613618        return;
    614619    }
     
    670675}
    671676
    672 void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr)
     677void SpeculativeJIT::emitObjectOrOtherBranch(NodeIndex nodeIndex, BlockIndex taken, BlockIndex notTaken, void *vptr, bool needSpeculationCheck)
    673678{
    674679    JSValueOperand value(this, nodeIndex);
     
    676681   
    677682    MacroAssembler::Jump notCell = m_jit.branchTestPtr(MacroAssembler::NonZero, valueGPR, GPRInfo::tagMaskRegister);
    678     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr)));
     683    if (needSpeculationCheck)
     684        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(valueGPR), MacroAssembler::TrustedImmPtr(vptr)));
    679685    addBranch(m_jit.jump(), taken);
    680686   
    681687    notCell.link(&m_jit);
    682688   
    683     m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), valueGPR);
    684     speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, valueGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
     689    if (needSpeculationCheck) {
     690        m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), valueGPR);
     691        speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, valueGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
     692    }
    685693    if (notTaken != (m_block + 1))
    686694        addBranch(m_jit.jump(), notTaken);
     
    694702    GPRReg valueGPR = value.gpr();
    695703   
    696     BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
    697     BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
     704    BlockIndex taken = node.takenBlockIndex();
     705    BlockIndex notTaken = node.notTakenBlockIndex();
    698706   
    699707    if (isKnownBoolean(node.child1())) {
     
    713721        noResult(m_compileIndex);
    714722    } else if (at(node.child1()).shouldSpeculateFinalObjectOrOther()) {
    715         emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr);
     723        emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsFinalObjectVPtr, !isFinalObjectOrOtherPrediction(m_state.forNode(node.child1()).m_type));
    716724    } else if (at(node.child1()).shouldSpeculateArrayOrOther()) {
    717         emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr);
     725        emitObjectOrOtherBranch(node.child1(), taken, notTaken, m_jit.globalData()->jsArrayVPtr, !isArrayOrOtherPrediction(m_state.forNode(node.child1()).m_type));
    718726    } else if (at(node.child1()).shouldSpeculateNumber()) {
    719727        if (at(node.child1()).shouldSpeculateInteger()) {
     
    748756            addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(false)))), notTaken);
    749757            addBranch(m_jit.branchPtr(MacroAssembler::Equal, valueGPR, MacroAssembler::ImmPtr(JSValue::encode(jsBoolean(true)))), taken);
    750         }
    751        
    752         if (predictBoolean) {
     758
    753759            speculationCheck(m_jit.jump());
    754760            value.use();
     
    788794    case GetLocal: {
    789795        PredictedType prediction = node.variableAccessData()->prediction();
     796        AbstractValue& value = block()->valuesAtHead.operand(node.local());
    790797
    791798        // If we have no prediction for this local, then don't attempt to compile.
    792         if (prediction == PredictNone) {
     799        if (prediction == PredictNone || value.isClear()) {
    793800            terminateSpeculativeExecution();
    794801            break;
     
    796803       
    797804        GPRTemporary result(this);
    798         if (isInt32Prediction(prediction)) {
     805        if (isInt32Prediction(value.m_type)) {
    799806            m_jit.load32(JITCompiler::payloadFor(node.local()), result.gpr());
    800807
     
    815822
    816823        DataFormat format;
    817         if (isArrayPrediction(prediction))
     824        if (isCellPrediction(value.m_type))
    818825            format = DataFormatJSCell;
    819         else if (isBooleanPrediction(prediction))
     826        else if (isBooleanPrediction(value.m_type))
    820827            format = DataFormatJSBoolean;
    821828        else
     
    860867            SpeculateCellOperand cell(this, node.child1());
    861868            GPRReg cellGPR = cell.gpr();
    862             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
     869            if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
     870                speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(cellGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    863871            m_jit.storePtr(cellGPR, JITCompiler::addressFor(node.local()));
    864872            noResult(m_compileIndex);
     
    14631471        // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
    14641472        // If we have predicted the base to be type array, we can skip the check.
    1465         if (!isKnownArray(node.child1()))
     1473        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
    14661474            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    14671475        speculationCheck(m_jit.branch32(MacroAssembler::AboveOrEqual, propertyReg, MacroAssembler::Address(baseReg, JSArray::vectorLengthOffset())));
     
    15131521        // Check that base is an array, and that property is contained within m_vector (< m_vectorLength).
    15141522        // If we have predicted the base to be type array, we can skip the check.
    1515         if (!isKnownArray(node.child1()))
     1523        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
    15161524            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    15171525
     
    15961604        writeBarrier(baseGPR, valueGPR, node.child2(), WriteBarrierForPropertyAccess, storageGPR, storageLengthGPR);
    15971605
    1598         if (!isKnownArray(node.child1()))
     1606        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
    15991607            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    16001608       
     
    16391647        GPRReg storageLengthGPR = storageLength.gpr();
    16401648       
    1641         if (!isKnownArray(node.child1()))
     1649        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
    16421650            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    16431651       
     
    16821690
    16831691    case DFG::Jump: {
    1684         BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
     1692        BlockIndex taken = node.takenBlockIndex();
    16851693        if (taken != (m_block + 1))
    16861694            addBranch(m_jit.jump(), taken);
     
    16931701            SpeculateIntegerOperand op(this, node.child1());
    16941702           
    1695             BlockIndex taken = m_jit.graph().blockIndexForBytecodeOffset(node.takenBytecodeOffset());
    1696             BlockIndex notTaken = m_jit.graph().blockIndexForBytecodeOffset(node.notTakenBytecodeOffset());
     1703            BlockIndex taken = node.takenBlockIndex();
     1704            BlockIndex notTaken = node.notTakenBlockIndex();
    16971705           
    16981706            MacroAssembler::ResultCondition condition = MacroAssembler::NonZero;
     
    18671875            GPRReg scratchGPR = scratch.gpr();
    18681876           
    1869             m_jit.move(thisValueGPR, scratchGPR);
    1870             m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
    1871             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
     1877            if (!isOtherPrediction(m_state.forNode(node.child1()).m_type)) {
     1878                m_jit.move(thisValueGPR, scratchGPR);
     1879                m_jit.andPtr(MacroAssembler::TrustedImm32(~TagBitUndefined), scratchGPR);
     1880                speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, scratchGPR, MacroAssembler::TrustedImmPtr(reinterpret_cast<void*>(ValueNull))));
     1881            }
    18721882           
    18731883            m_jit.move(MacroAssembler::TrustedImmPtr(m_jit.codeBlock()->globalObject()), scratchGPR);
     
    18791889            SpeculateCellOperand thisValue(this, node.child1());
    18801890           
    1881             speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
     1891            if (!isObjectPrediction(m_state.forNode(node.child1()).m_type))
     1892                speculationCheck(m_jit.branchPtr(JITCompiler::Equal, JITCompiler::Address(thisValue.gpr()), JITCompiler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
    18821893           
    18831894            cellResult(thisValue.gpr(), m_compileIndex);
     
    19191930        // that it's a FinalObject then we speculate on that directly. Otherwise we
    19201931        // do the slow (structure-based) check.
    1921         if (at(node.child1()).shouldSpeculateFinalObject())
    1922             speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr)));
    1923         else {
     1932        if (at(node.child1()).shouldSpeculateFinalObject()) {
     1933            if (!isFinalObjectPrediction(m_state.forNode(node.child1()).m_type))
     1934                speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(protoGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsFinalObjectVPtr)));
     1935        } else {
    19241936            m_jit.loadPtr(MacroAssembler::Address(protoGPR, JSCell::structureOffset()), scratchGPR);
    19251937            slowPath.append(m_jit.branch8(MacroAssembler::Below, MacroAssembler::Address(scratchGPR, Structure::typeInfoTypeOffset()), MacroAssembler::TrustedImm32(ObjectType)));
     
    20502062        GPRReg resultGPR = result.gpr();
    20512063       
    2052         if (!isKnownArray(node.child1()))
     2064        if (!isArrayPrediction(m_state.forNode(node.child1()).m_type))
    20532065            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsArrayVPtr)));
    20542066       
     
    20692081        GPRReg resultGPR = result.gpr();
    20702082       
    2071         if (!isKnownString(node.child1()))
     2083        if (!isStringPrediction(m_state.forNode(node.child1()).m_type))
    20722084            speculationCheck(m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseGPR), MacroAssembler::TrustedImmPtr(m_jit.globalData()->jsStringVPtr)));
    20732085       
     
    20842096    }
    20852097    case CheckStructure: {
     2098        if (m_state.forNode(node.child1()).m_structure.isSubsetOf(node.structureSet())) {
     2099            noResult(m_compileIndex);
     2100            break;
     2101        }
     2102       
    20862103        SpeculateCellOperand base(this, node.child1());
    20872104       
     
    22032220        GPRReg scratchGPR = scratch.gpr();
    22042221       
    2205         speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure)));
     2222        if (!m_state.forNode(node.child1()).m_structure.doesNotContainAnyOtherThan(methodCheckData.structure))
     2223            speculationCheck(m_jit.branchPtr(JITCompiler::NotEqual, JITCompiler::Address(baseGPR, JSCell::structureOffset()), JITCompiler::TrustedImmPtr(methodCheckData.structure)));
    22062224        if (methodCheckData.prototype != m_jit.codeBlock()->globalObject()->methodCallDummy()) {
    22072225            m_jit.move(JITCompiler::TrustedImmPtr(methodCheckData.prototype->structureAddress()), scratchGPR);
  • trunk/Source/JavaScriptCore/dfg/DFGStructureSet.h

    r96527 r97218  
    2727#define DFGStructureSet_h
    2828
     29#include <wtf/Platform.h>
     30
     31#if ENABLE(DFG_JIT)
     32
     33#include "PredictedType.h"
     34#include <stdio.h>
    2935#include <wtf/Vector.h>
    3036
     
    3541namespace DFG {
    3642
     43class StructureAbstractValue;
     44
    3745class StructureSet {
    3846public:
     
    4250    {
    4351        m_structures.append(structure);
     52    }
     53   
     54    void clear()
     55    {
     56        m_structures.clear();
    4457    }
    4558   
     
    105118    Structure* last() const { return m_structures.last(); }
    106119
     120    PredictedType predictionFromStructures() const
     121    {
     122        PredictedType result = PredictNone;
     123       
     124        for (size_t i = 0; i < m_structures.size(); ++i)
     125            mergePrediction(result, predictionFromStructure(m_structures[i]));
     126       
     127        return result;
     128    }
     129   
     130    bool operator==(const StructureSet& other) const
     131    {
     132        if (m_structures.size() != other.m_structures.size())
     133            return false;
     134       
     135        for (size_t i = 0; i < m_structures.size(); ++i) {
     136            if (!other.contains(m_structures[i]))
     137                return false;
     138        }
     139       
     140        return true;
     141    }
     142   
     143#ifndef NDEBUG
     144    void dump(FILE* out)
     145    {
     146        fprintf(out, "[");
     147        for (size_t i = 0; i < m_structures.size(); ++i) {
     148            if (i)
     149                fprintf(out, ", ");
     150            fprintf(out, "%p", m_structures[i]);
     151        }
     152        fprintf(out, "]");
     153    }
     154#endif
     155   
    107156private:
     157    friend class StructureAbstractValue;
     158   
    108159    Vector<Structure*, 2> m_structures;
    109160};
     
    111162} } // namespace JSC::DFG
    112163
     164#endif // ENABLE(DFG_JIT)
     165
    113166#endif // DFGStructureSet_h
Note: See TracChangeset for help on using the changeset viewer.