Changeset 164207 in webkit


Ignore:
Timestamp:
Feb 16, 2014 10:35:32 PM (10 years ago)
Author:
fpizlo@apple.com
Message:

FTL should inline polymorphic heap accesses
https://bugs.webkit.org/show_bug.cgi?id=128795

Source/JavaScriptCore:

Reviewed by Oliver Hunt.

We now inline GetByIds that we know are pure but polymorphic. They manifest in DFG IR
as MultiGetByOffset, and in LLVM IR as a switch with a basic block for each kind of
read.

2% speed-up on Octane mostly due to a 18% speed-up on deltablue.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bytecode/CodeBlock.cpp:

(JSC::CodeBlock::dumpBytecode):

  • bytecode/ExitingJITType.cpp: Added.

(WTF::printInternal):

  • bytecode/ExitingJITType.h:
  • bytecode/GetByIdStatus.cpp:

(JSC::GetByIdStatus::computeFromLLInt):
(JSC::GetByIdStatus::computeForChain):
(JSC::GetByIdStatus::computeForStubInfo):
(JSC::GetByIdStatus::computeFor):
(JSC::GetByIdStatus::dump):

  • bytecode/GetByIdStatus.h:

(JSC::GetByIdStatus::GetByIdStatus):
(JSC::GetByIdStatus::numVariants):
(JSC::GetByIdStatus::variants):
(JSC::GetByIdStatus::at):
(JSC::GetByIdStatus::operator[]):

  • bytecode/GetByIdVariant.cpp: Added.

(JSC::GetByIdVariant::dump):
(JSC::GetByIdVariant::dumpInContext):

  • bytecode/GetByIdVariant.h: Added.

(JSC::GetByIdVariant::GetByIdVariant):
(JSC::GetByIdVariant::isSet):
(JSC::GetByIdVariant::operator!):
(JSC::GetByIdVariant::structureSet):
(JSC::GetByIdVariant::chain):
(JSC::GetByIdVariant::specificValue):
(JSC::GetByIdVariant::offset):

  • dfg/DFGAbstractInterpreterInlines.h:

(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

  • dfg/DFGByteCodeParser.cpp:

(JSC::DFG::ByteCodeParser::emitPrototypeChecks):
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::parseBlock):

  • dfg/DFGCSEPhase.cpp:

(JSC::DFG::CSEPhase::getByOffsetLoadElimination):
(JSC::DFG::CSEPhase::performNodeCSE):

  • dfg/DFGClobberize.h:

(JSC::DFG::clobberize):

  • dfg/DFGCommon.h:

(JSC::DFG::verboseCompilationEnabled):
(JSC::DFG::logCompilationChanges):
(JSC::DFG::shouldShowDisassembly):

  • dfg/DFGConstantFoldingPhase.cpp:

(JSC::DFG::ConstantFoldingPhase::foldConstants):
(JSC::DFG::ConstantFoldingPhase::emitGetByOffset):

  • dfg/DFGDriver.cpp:

(JSC::DFG::compileImpl):

  • dfg/DFGFixupPhase.cpp:

(JSC::DFG::FixupPhase::fixupNode):

  • dfg/DFGGraph.cpp:

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

  • dfg/DFGGraph.h:

(JSC::DFG::Graph::convertToConstant):

  • dfg/DFGNode.h:

(JSC::DFG::Node::convertToGetByOffset):
(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasMultiGetByOffsetData):
(JSC::DFG::Node::multiGetByOffsetData):

  • dfg/DFGNodeType.h:
  • dfg/DFGPhase.h:

(JSC::DFG::Phase::graph):
(JSC::DFG::runAndLog):

  • dfg/DFGPlan.cpp:

(JSC::DFG::dumpAndVerifyGraph):
(JSC::DFG::Plan::compileInThread):
(JSC::DFG::Plan::compileInThreadImpl):

  • dfg/DFGPredictionPropagationPhase.cpp:

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

  • dfg/DFGSafeToExecute.h:

(JSC::DFG::safeToExecute):

  • dfg/DFGSpeculativeJIT32_64.cpp:

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

  • dfg/DFGSpeculativeJIT64.cpp:

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

  • dfg/DFGTypeCheckHoistingPhase.cpp:

(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
(JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):

  • ftl/FTLCapabilities.cpp:

(JSC::FTL::canCompile):

  • ftl/FTLCompile.cpp:

(JSC::FTL::fixFunctionBasedOnStackMaps):
(JSC::FTL::compile):

  • ftl/FTLLowerDFGToLLVM.cpp:

(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):

  • ftl/FTLState.h:

(JSC::FTL::verboseCompilationEnabled):
(JSC::FTL::showDisassembly):

  • jsc.cpp:

(GlobalObject::finishCreation):
(functionEffectful42):

  • runtime/IntendedStructureChain.cpp:

(JSC::IntendedStructureChain::dump):
(JSC::IntendedStructureChain::dumpInContext):

  • runtime/IntendedStructureChain.h:
  • runtime/Options.cpp:

(JSC::recomputeDependentOptions):

  • runtime/Options.h:
  • tests/stress/fold-multi-get-by-offset-to-get-by-offset-with-watchpoint.js: Added.

(foo):
(bar):

  • tests/stress/fold-multi-get-by-offset-to-get-by-offset.js: Added.

(foo):
(bar):

  • tests/stress/multi-get-by-offset-proto-and-self.js: Added.

(foo):
(Foo):

Source/WTF:

Reviewed by Oliver Hunt.

  • wtf/PrintStream.h:

(WTF::PointerDumpInContext::PointerDumpInContext):
(WTF::PointerDumpInContext::dump):
(WTF::pointerDumpInContext):

LayoutTests:

Reviewed by Oliver Hunt.

  • js/regress/polymorphic-get-by-id-expected.txt: Added.
  • js/regress/polymorphic-get-by-id.html: Added.
  • js/regress/script-tests/polymorphic-get-by-id.js: Added.

(foo):

Location:
trunk
Files:
9 added
40 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r164206 r164207  
     12014-02-15  Filip Pizlo  <fpizlo@apple.com>
     2
     3        FTL should inline polymorphic heap accesses
     4        https://bugs.webkit.org/show_bug.cgi?id=128795
     5
     6        Reviewed by Oliver Hunt.
     7
     8        * js/regress/polymorphic-get-by-id-expected.txt: Added.
     9        * js/regress/polymorphic-get-by-id.html: Added.
     10        * js/regress/script-tests/polymorphic-get-by-id.js: Added.
     11        (foo):
     12
    1132014-02-16  Filip Pizlo  <fpizlo@apple.com>
    214
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r164096 r164207  
    7171    bytecode/ExecutionCounter.cpp
    7272    bytecode/ExitKind.cpp
     73    bytecode/ExitingJITType.cpp
    7374    bytecode/GetByIdStatus.cpp
     75    bytecode/GetByIdVariant.cpp
    7476    bytecode/InlineCallFrameSet.cpp
    7577    bytecode/JumpTable.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r164205 r164207  
     12014-02-15  Filip Pizlo  <fpizlo@apple.com>
     2
     3        FTL should inline polymorphic heap accesses
     4        https://bugs.webkit.org/show_bug.cgi?id=128795
     5
     6        Reviewed by Oliver Hunt.
     7       
     8        We now inline GetByIds that we know are pure but polymorphic. They manifest in DFG IR
     9        as MultiGetByOffset, and in LLVM IR as a switch with a basic block for each kind of
     10        read.
     11       
     12        2% speed-up on Octane mostly due to a 18% speed-up on deltablue.
     13
     14        * CMakeLists.txt:
     15        * GNUmakefile.list.am:
     16        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     17        * JavaScriptCore.xcodeproj/project.pbxproj:
     18        * bytecode/CodeBlock.cpp:
     19        (JSC::CodeBlock::dumpBytecode):
     20        * bytecode/ExitingJITType.cpp: Added.
     21        (WTF::printInternal):
     22        * bytecode/ExitingJITType.h:
     23        * bytecode/GetByIdStatus.cpp:
     24        (JSC::GetByIdStatus::computeFromLLInt):
     25        (JSC::GetByIdStatus::computeForChain):
     26        (JSC::GetByIdStatus::computeForStubInfo):
     27        (JSC::GetByIdStatus::computeFor):
     28        (JSC::GetByIdStatus::dump):
     29        * bytecode/GetByIdStatus.h:
     30        (JSC::GetByIdStatus::GetByIdStatus):
     31        (JSC::GetByIdStatus::numVariants):
     32        (JSC::GetByIdStatus::variants):
     33        (JSC::GetByIdStatus::at):
     34        (JSC::GetByIdStatus::operator[]):
     35        * bytecode/GetByIdVariant.cpp: Added.
     36        (JSC::GetByIdVariant::dump):
     37        (JSC::GetByIdVariant::dumpInContext):
     38        * bytecode/GetByIdVariant.h: Added.
     39        (JSC::GetByIdVariant::GetByIdVariant):
     40        (JSC::GetByIdVariant::isSet):
     41        (JSC::GetByIdVariant::operator!):
     42        (JSC::GetByIdVariant::structureSet):
     43        (JSC::GetByIdVariant::chain):
     44        (JSC::GetByIdVariant::specificValue):
     45        (JSC::GetByIdVariant::offset):
     46        * dfg/DFGAbstractInterpreterInlines.h:
     47        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     48        * dfg/DFGByteCodeParser.cpp:
     49        (JSC::DFG::ByteCodeParser::emitPrototypeChecks):
     50        (JSC::DFG::ByteCodeParser::handleGetById):
     51        (JSC::DFG::ByteCodeParser::parseBlock):
     52        * dfg/DFGCSEPhase.cpp:
     53        (JSC::DFG::CSEPhase::getByOffsetLoadElimination):
     54        (JSC::DFG::CSEPhase::performNodeCSE):
     55        * dfg/DFGClobberize.h:
     56        (JSC::DFG::clobberize):
     57        * dfg/DFGCommon.h:
     58        (JSC::DFG::verboseCompilationEnabled):
     59        (JSC::DFG::logCompilationChanges):
     60        (JSC::DFG::shouldShowDisassembly):
     61        * dfg/DFGConstantFoldingPhase.cpp:
     62        (JSC::DFG::ConstantFoldingPhase::foldConstants):
     63        (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
     64        * dfg/DFGDriver.cpp:
     65        (JSC::DFG::compileImpl):
     66        * dfg/DFGFixupPhase.cpp:
     67        (JSC::DFG::FixupPhase::fixupNode):
     68        * dfg/DFGGraph.cpp:
     69        (JSC::DFG::Graph::dump):
     70        * dfg/DFGGraph.h:
     71        (JSC::DFG::Graph::convertToConstant):
     72        * dfg/DFGNode.h:
     73        (JSC::DFG::Node::convertToGetByOffset):
     74        (JSC::DFG::Node::hasHeapPrediction):
     75        (JSC::DFG::Node::hasMultiGetByOffsetData):
     76        (JSC::DFG::Node::multiGetByOffsetData):
     77        * dfg/DFGNodeType.h:
     78        * dfg/DFGPhase.h:
     79        (JSC::DFG::Phase::graph):
     80        (JSC::DFG::runAndLog):
     81        * dfg/DFGPlan.cpp:
     82        (JSC::DFG::dumpAndVerifyGraph):
     83        (JSC::DFG::Plan::compileInThread):
     84        (JSC::DFG::Plan::compileInThreadImpl):
     85        * dfg/DFGPredictionPropagationPhase.cpp:
     86        (JSC::DFG::PredictionPropagationPhase::propagate):
     87        * dfg/DFGSafeToExecute.h:
     88        (JSC::DFG::safeToExecute):
     89        * dfg/DFGSpeculativeJIT32_64.cpp:
     90        (JSC::DFG::SpeculativeJIT::compile):
     91        * dfg/DFGSpeculativeJIT64.cpp:
     92        (JSC::DFG::SpeculativeJIT::compile):
     93        * dfg/DFGTypeCheckHoistingPhase.cpp:
     94        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantStructureChecks):
     95        (JSC::DFG::TypeCheckHoistingPhase::identifyRedundantArrayChecks):
     96        * ftl/FTLCapabilities.cpp:
     97        (JSC::FTL::canCompile):
     98        * ftl/FTLCompile.cpp:
     99        (JSC::FTL::fixFunctionBasedOnStackMaps):
     100        (JSC::FTL::compile):
     101        * ftl/FTLLowerDFGToLLVM.cpp:
     102        (JSC::FTL::LowerDFGToLLVM::compileNode):
     103        (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
     104        * ftl/FTLState.h:
     105        (JSC::FTL::verboseCompilationEnabled):
     106        (JSC::FTL::showDisassembly):
     107        * jsc.cpp:
     108        (GlobalObject::finishCreation):
     109        (functionEffectful42):
     110        * runtime/IntendedStructureChain.cpp:
     111        (JSC::IntendedStructureChain::dump):
     112        (JSC::IntendedStructureChain::dumpInContext):
     113        * runtime/IntendedStructureChain.h:
     114        * runtime/Options.cpp:
     115        (JSC::recomputeDependentOptions):
     116        * runtime/Options.h:
     117        * tests/stress/fold-multi-get-by-offset-to-get-by-offset-with-watchpoint.js: Added.
     118        (foo):
     119        (bar):
     120        * tests/stress/fold-multi-get-by-offset-to-get-by-offset.js: Added.
     121        (foo):
     122        (bar):
     123        * tests/stress/multi-get-by-offset-proto-and-self.js: Added.
     124        (foo):
     125        (Foo):
     126
    11272014-02-16  Filip Pizlo  <fpizlo@apple.com>
    2128
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r164059 r164207  
    148148        Source/JavaScriptCore/bytecode/ExitKind.cpp \
    149149        Source/JavaScriptCore/bytecode/ExitKind.h \
     150        Source/JavaScriptCore/bytecode/ExitingJITType.cpp \
     151        Source/JavaScriptCore/bytecode/ExitingJITType.h \
    150152        Source/JavaScriptCore/bytecode/ExpressionRangeInfo.h \
    151153        Source/JavaScriptCore/bytecode/FullBytecodeLiveness.h \
    152154        Source/JavaScriptCore/bytecode/GetByIdStatus.cpp \
    153155        Source/JavaScriptCore/bytecode/GetByIdStatus.h \
     156        Source/JavaScriptCore/bytecode/GetByIdVariant.cpp \
     157        Source/JavaScriptCore/bytecode/GetByIdVariant.h \
    154158        Source/JavaScriptCore/bytecode/HandlerInfo.h \
    155159        Source/JavaScriptCore/bytecode/InlineCallFrameSet.cpp \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r164164 r164207  
    326326    <ClCompile Include="..\bytecode\ExecutionCounter.cpp" />
    327327    <ClCompile Include="..\bytecode\ExitKind.cpp" />
     328    <ClCompile Include="..\bytecode\ExitingJITType.cpp" />
    328329    <ClCompile Include="..\bytecode\GetByIdStatus.cpp" />
     330    <ClCompile Include="..\bytecode\GetByIdVariant.cpp" />
    329331    <ClCompile Include="..\bytecode\InlineCallFrameSet.cpp" />
    330332    <ClCompile Include="..\bytecode\JumpTable.cpp" />
     
    841843    <ClInclude Include="..\bytecode\ExpressionRangeInfo.h" />
    842844    <ClInclude Include="..\bytecode\GetByIdStatus.h" />
     845    <ClInclude Include="..\bytecode\GetByIdVariant.h" />
    843846    <ClInclude Include="..\bytecode\HandlerInfo.h" />
    844847    <ClInclude Include="..\bytecode\InlineCallFrameSet.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r164144 r164207  
    6060
    6161/* Begin PBXBuildFile section */
     62                0F0332C018ADFAE1005F979A /* ExitingJITType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */; };
     63                0F0332C318B01763005F979A /* GetByIdVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0332C118B01763005F979A /* GetByIdVariant.cpp */; };
     64                0F0332C418B01763005F979A /* GetByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0332C218B01763005F979A /* GetByIdVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
    6265                0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
    6366                0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    211214                0F2FCCFE18A60070001A27F8 /* DFGThreadData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2FCCF718A60070001A27F8 /* DFGThreadData.cpp */; };
    212215                0F2FCCFF18A60070001A27F8 /* DFGThreadData.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2FCCF818A60070001A27F8 /* DFGThreadData.h */; settings = {ATTRIBUTES = (Private, ); }; };
     216                0F300B7818AB051100A6D72E /* DFGNodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
    213217                0F300B7B18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */; };
    214218                0F300B7C18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
    215                 0F300B7818AB051100A6D72E /* DFGNodeOrigin.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */; settings = {ATTRIBUTES = (Private, ); }; };
    216219                0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */; };
    217220                0F34B14A16D42013001CDA5A /* DFGUseKind.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F34B14816D4200E001CDA5A /* DFGUseKind.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    15251528
    15261529/* Begin PBXFileReference section */
     1530                0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExitingJITType.cpp; sourceTree = "<group>"; };
     1531                0F0332C118B01763005F979A /* GetByIdVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetByIdVariant.cpp; sourceTree = "<group>"; };
     1532                0F0332C218B01763005F979A /* GetByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetByIdVariant.h; sourceTree = "<group>"; };
    15271533                0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = "<group>"; };
    15281534                0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = "<group>"; };
     
    16751681                0F2FCCF718A60070001A27F8 /* DFGThreadData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGThreadData.cpp; path = dfg/DFGThreadData.cpp; sourceTree = "<group>"; };
    16761682                0F2FCCF818A60070001A27F8 /* DFGThreadData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGThreadData.h; path = dfg/DFGThreadData.h; sourceTree = "<group>"; };
     1683                0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeOrigin.h; path = dfg/DFGNodeOrigin.h; sourceTree = "<group>"; };
    16771684                0F300B7918AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGIntegerCheckCombiningPhase.cpp; path = dfg/DFGIntegerCheckCombiningPhase.cpp; sourceTree = "<group>"; };
    16781685                0F300B7A18AB1B1400A6D72E /* DFGIntegerCheckCombiningPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGIntegerCheckCombiningPhase.h; path = dfg/DFGIntegerCheckCombiningPhase.h; sourceTree = "<group>"; };
    1679                 0F300B7718AB051100A6D72E /* DFGNodeOrigin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGNodeOrigin.h; path = dfg/DFGNodeOrigin.h; sourceTree = "<group>"; };
    16801686                0F34B14716D4200E001CDA5A /* DFGUseKind.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUseKind.cpp; path = dfg/DFGUseKind.cpp; sourceTree = "<group>"; };
    16811687                0F34B14816D4200E001CDA5A /* DFGUseKind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUseKind.h; path = dfg/DFGUseKind.h; sourceTree = "<group>"; };
     
    45204526                                0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */,
    45214527                                0F56A1D115000F31002992B1 /* ExecutionCounter.h */,
     4528                                0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */,
    45224529                                0F3AC753188E5EC80032029F /* ExitingJITType.h */,
    45234530                                0FB105821675480C00F8AB6E /* ExitKind.cpp */,
     
    45274534                                0F93329514CA7DC10085F3C6 /* GetByIdStatus.cpp */,
    45284535                                0F93329614CA7DC10085F3C6 /* GetByIdStatus.h */,
     4536                                0F0332C118B01763005F979A /* GetByIdVariant.cpp */,
     4537                                0F0332C218B01763005F979A /* GetByIdVariant.h */,
    45294538                                0F0B83A814BCF55E00885B4F /* HandlerInfo.h */,
    45304539                                0F24E55317F0B71C00ABB217 /* InlineCallFrameSet.cpp */,
     
    48234832                                BC18C3E70E16F5CD00B34460 /* ArrayPrototype.h in Headers */,
    48244833                                BC18C5240E16FC8A00B34460 /* ArrayPrototype.lut.h in Headers */,
     4834                                0F0332C418B01763005F979A /* GetByIdVariant.h in Headers */,
    48254835                                0FB7F39615ED8E4600F167B2 /* ArrayStorage.h in Headers */,
    48264836                                9688CB150ED12B4E001D649F /* AssemblerBuffer.h in Headers */,
     
    60946104                                A704D90517A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp in Sources */,
    60956105                                0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */,
     6106                                0F0332C018ADFAE1005F979A /* ExitingJITType.cpp in Sources */,
    60966107                                0FEA0A33170D40BF00BB722C /* DFGJITCode.cpp in Sources */,
    60976108                                86EC9DCB1328DF82002B2AD7 /* DFGJITCompiler.cpp in Sources */,
     
    63776388                                148F21B7107EC5470042EC2C /* Nodes.cpp in Sources */,
    63786389                                655EB29B10CE2581001A990E /* NodesCodegen.cpp in Sources */,
     6390                                0F0332C318B01763005F979A /* GetByIdVariant.cpp in Sources */,
    63796391                                14469DE2107EC7E700650446 /* NumberConstructor.cpp in Sources */,
    63806392                                14469DE3107EC7E700650446 /* NumberObject.cpp in Sources */,
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r164092 r164207  
    13781378        CommaPrinter comma;
    13791379        for (unsigned i = 0; i < exitSites.size(); ++i)
    1380             out.print(comma, exitSites[i].kind());
     1380            out.print(comma, exitSites[i].kind(), " ", exitSites[i].jitType());
    13811381    }
    13821382#else // ENABLE(DFG_JIT)
  • trunk/Source/JavaScriptCore/bytecode/ExitingJITType.h

    r163027 r164207  
    5252} // namespace JSC
    5353
     54namespace WTF {
     55
     56class PrintStream;
     57void printInternal(PrintStream&, JSC::ExitingJITType);
     58
     59} // namespace WTF
     60
    5461#endif // ExitingJITType_h
    5562
  • trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp

    r164164 r164207  
    3232#include "LowLevelInterpreter.h"
    3333#include "JSCInlines.h"
     34#include <wtf/ListDump.h>
    3435
    3536namespace JSC {
     
    7273        return GetByIdStatus(NoInformation, false);
    7374   
    74     return GetByIdStatus(Simple, false, StructureSet(structure), offset, specificValue);
     75    return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue));
    7576#else
    7677    return GetByIdStatus(NoInformation, false);
     
    7879}
    7980
    80 void GetByIdStatus::computeForChain(GetByIdStatus& result, CodeBlock* profiledBlock, StringImpl* uid)
     81bool GetByIdStatus::computeForChain(CodeBlock* profiledBlock, StringImpl* uid, PassRefPtr<IntendedStructureChain> passedChain)
    8182{
    8283#if ENABLE(JIT)
     84    RefPtr<IntendedStructureChain> chain = passedChain;
     85   
    8386    // Validate the chain. If the chain is invalid, then currently the best thing
    8487    // we can do is to assume that TakesSlow is true. In the future, it might be
     
    9194    // cached on in the baseline JIT and when the DFG tried to inline the access,
    9295    // then we fall back on a polymorphic access.
    93     if (!result.m_chain->isStillValid())
    94         return;
    95 
    96     if (result.m_chain->head()->takesSlowPathInDFGForImpureProperty())
    97         return;
    98     size_t chainSize = result.m_chain->size();
     96    if (!chain->isStillValid())
     97        return false;
     98
     99    if (chain->head()->takesSlowPathInDFGForImpureProperty())
     100        return false;
     101    size_t chainSize = chain->size();
    99102    for (size_t i = 0; i < chainSize; i++) {
    100         if (result.m_chain->at(i)->takesSlowPathInDFGForImpureProperty())
    101             return;
    102     }
    103 
    104     JSObject* currentObject = result.m_chain->terminalPrototype();
    105     Structure* currentStructure = result.m_chain->last();
     103        if (chain->at(i)->takesSlowPathInDFGForImpureProperty())
     104            return false;
     105    }
     106
     107    JSObject* currentObject = chain->terminalPrototype();
     108    Structure* currentStructure = chain->last();
    106109   
    107110    ASSERT_UNUSED(currentObject, currentObject);
    108        
     111   
    109112    unsigned attributesIgnored;
    110113    JSCell* specificValue;
    111        
    112     result.m_offset = currentStructure->getConcurrently(
     114   
     115    PropertyOffset offset = currentStructure->getConcurrently(
    113116        *profiledBlock->vm(), uid, attributesIgnored, specificValue);
    114117    if (currentStructure->isDictionary())
    115118        specificValue = 0;
    116     if (!isValidOffset(result.m_offset))
    117         return;
    118        
    119     result.m_structureSet.add(result.m_chain->head());
    120     result.m_specificValue = JSValue(specificValue);
    121 #else
    122     UNUSED_PARAM(result);
     119    if (!isValidOffset(offset))
     120        return false;
     121   
     122    m_variants.append(
     123        GetByIdVariant(StructureSet(chain->head()), offset, specificValue, chain));
     124    return true;
     125#else // ENABLE(JIT)
    123126    UNUSED_PARAM(profiledBlock);
    124127    UNUSED_PARAM(uid);
     128    UNUSED_PARAM(passedChain);
    125129    UNREACHABLE_FOR_PLATFORM();
    126 #endif
     130    return false;
     131#endif // ENABLE(JIT)
    127132}
    128133
     
    175180    // Finally figure out if we can derive an access strategy.
    176181    GetByIdStatus result;
     182    result.m_state = Simple;
    177183    result.m_wasSeenInJIT = true; // This is interesting for bytecode dumping only.
    178184    switch (stubInfo->accessType) {
     
    186192        unsigned attributesIgnored;
    187193        JSCell* specificValue;
    188         result.m_offset = structure->getConcurrently(
     194        GetByIdVariant variant;
     195        variant.m_offset = structure->getConcurrently(
    189196            *profiledBlock->vm(), uid, attributesIgnored, specificValue);
     197        if (!isValidOffset(variant.m_offset))
     198            return GetByIdStatus(TakesSlowPath, true);
     199       
    190200        if (structure->isDictionary())
    191201            specificValue = 0;
    192202       
    193         if (isValidOffset(result.m_offset)) {
    194             result.m_structureSet.add(structure);
    195             result.m_specificValue = JSValue(specificValue);
    196         }
    197        
    198         if (isValidOffset(result.m_offset))
    199             ASSERT(result.m_structureSet.size());
    200         break;
     203        variant.m_structureSet.add(structure);
     204        variant.m_specificValue = JSValue(specificValue);
     205        result.m_variants.append(variant);
     206        return result;
    201207    }
    202208       
    203209    case access_get_by_id_self_list: {
    204         for (int i = 0; i < listSize; ++i) {
    205             ASSERT(list->list[i].isDirect);
    206            
    207             Structure* structure = list->list[i].base.get();
     210        for (int listIndex = 0; listIndex < listSize; ++listIndex) {
     211            ASSERT(list->list[listIndex].isDirect);
     212           
     213            Structure* structure = list->list[listIndex].base.get();
    208214            if (structure->takesSlowPathInDFGForImpureProperty())
    209215                return GetByIdStatus(TakesSlowPath, true);
    210 
    211             if (result.m_structureSet.contains(structure))
     216           
     217            if (list->list[listIndex].chain.get()) {
     218                RefPtr<IntendedStructureChain> chain = adoptRef(new IntendedStructureChain(
     219                    profiledBlock, structure, list->list[listIndex].chain.get(),
     220                    list->list[listIndex].count));
     221                if (!result.computeForChain(profiledBlock, uid, chain))
     222                    return GetByIdStatus(TakesSlowPath, true);
    212223                continue;
     224            }
    213225           
    214226            unsigned attributesIgnored;
     
    219231                specificValue = 0;
    220232           
    221             if (!isValidOffset(myOffset)) {
    222                 result.m_offset = invalidOffset;
     233            if (!isValidOffset(myOffset))
     234                return GetByIdStatus(TakesSlowPath, true);
     235
     236            bool found = false;
     237            for (unsigned variantIndex = 0; variantIndex < result.m_variants.size(); ++variantIndex) {
     238                GetByIdVariant& variant = result.m_variants[variantIndex];
     239                if (variant.m_chain)
     240                    continue;
     241               
     242                if (variant.m_offset != myOffset)
     243                    continue;
     244
     245                found = true;
     246                if (variant.m_structureSet.contains(structure))
     247                    break;
     248               
     249                if (variant.m_specificValue != JSValue(specificValue))
     250                    variant.m_specificValue = JSValue();
     251               
     252                variant.m_structureSet.add(structure);
    223253                break;
    224254            }
    225                    
    226             if (!i) {
    227                 result.m_offset = myOffset;
    228                 result.m_specificValue = JSValue(specificValue);
    229             } else if (result.m_offset != myOffset) {
    230                 result.m_offset = invalidOffset;
    231                 break;
    232             } else if (result.m_specificValue != JSValue(specificValue))
    233                 result.m_specificValue = JSValue();
    234            
    235             result.m_structureSet.add(structure);
     255           
     256            if (found)
     257                continue;
     258           
     259            result.m_variants.append(
     260                GetByIdVariant(StructureSet(structure), myOffset, specificValue));
    236261        }
    237                    
    238         if (isValidOffset(result.m_offset))
    239             ASSERT(result.m_structureSet.size());
    240         break;
     262       
     263        return result;
    241264    }
    242265       
     
    244267        if (!stubInfo->u.getByIdChain.isDirect)
    245268            return GetByIdStatus(MakesCalls, true);
    246         result.m_chain = adoptRef(new IntendedStructureChain(
     269        RefPtr<IntendedStructureChain> chain = adoptRef(new IntendedStructureChain(
    247270            profiledBlock,
    248271            stubInfo->u.getByIdChain.baseObjectStructure.get(),
    249272            stubInfo->u.getByIdChain.chain.get(),
    250273            stubInfo->u.getByIdChain.count));
    251         computeForChain(result, profiledBlock, uid);
    252         break;
     274        if (result.computeForChain(profiledBlock, uid, chain))
     275            return result;
     276        return GetByIdStatus(TakesSlowPath, true);
    253277    }
    254278       
    255279    default:
    256         ASSERT(!isValidOffset(result.m_offset));
    257         break;
    258     }
    259    
    260     if (!isValidOffset(result.m_offset)) {
    261         result.m_state = TakesSlowPath;
    262         result.m_structureSet.clear();
    263         result.m_chain.clear();
    264         result.m_specificValue = JSValue();
    265     } else
    266         result.m_state = Simple;
    267    
    268     return result;
     280        return GetByIdStatus(TakesSlowPath, true);
     281    }
     282   
     283    RELEASE_ASSERT_NOT_REACHED();
     284    return GetByIdStatus();
    269285}
    270286#endif // ENABLE(JIT)
     
    281297            result = computeForStubInfo(locker, dfgBlock, dfgMap.get(codeOrigin), uid);
    282298        }
    283    
     299       
    284300        if (result.takesSlowPath())
    285301            return result;
     
    319335        return GetByIdStatus(TakesSlowPath);
    320336
    321     GetByIdStatus result;
    322     result.m_wasSeenInJIT = false; // To my knowledge nobody that uses computeFor(VM&, Structure*, StringImpl*) reads this field, but I might as well be honest: no, it wasn't seen in the JIT, since I computed it statically.
    323337    unsigned attributes;
    324338    JSCell* specificValue;
    325     result.m_offset = structure->getConcurrently(vm, uid, attributes, specificValue);
    326     if (!isValidOffset(result.m_offset))
     339    PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
     340    if (!isValidOffset(offset))
    327341        return GetByIdStatus(TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it.
    328342    if (attributes & Accessor)
     
    330344    if (structure->isDictionary())
    331345        specificValue = 0;
    332     result.m_structureSet.add(structure);
    333     result.m_specificValue = JSValue(specificValue);
    334     result.m_state = Simple;
    335     return result;
     346    return GetByIdStatus(
     347        Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue));
     348}
     349
     350void GetByIdStatus::dump(PrintStream& out) const
     351{
     352    out.print("(");
     353    switch (m_state) {
     354    case NoInformation:
     355        out.print("NoInformation");
     356        break;
     357    case Simple:
     358        out.print("Simple");
     359        break;
     360    case TakesSlowPath:
     361        out.print("TakesSlowPath");
     362        break;
     363    case MakesCalls:
     364        out.print("MakesCalls");
     365        break;
     366    }
     367    out.print(", ", listDump(m_variants), ", seenInJIT = ", m_wasSeenInJIT, ")");
    336368}
    337369
  • trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.h

    r164164 r164207  
    3030#include "ConcurrentJITLock.h"
    3131#include "ExitingJITType.h"
    32 #include "IntendedStructureChain.h"
    33 #include "PropertyOffset.h"
    34 #include "StructureSet.h"
     32#include "GetByIdVariant.h"
    3533#include "StructureStubInfo.h"
    3634
     
    5149    GetByIdStatus()
    5250        : m_state(NoInformation)
    53         , m_offset(invalidOffset)
    5451    {
    5552    }
     
    5754    explicit GetByIdStatus(State state)
    5855        : m_state(state)
    59         , m_offset(invalidOffset)
    6056    {
    6157        ASSERT(state == NoInformation || state == TakesSlowPath || state == MakesCalls);
     
    6359   
    6460    GetByIdStatus(
    65         State state, bool wasSeenInJIT, const StructureSet& structureSet = StructureSet(),
    66         PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(), PassRefPtr<IntendedStructureChain> chain = nullptr)
     61        State state, bool wasSeenInJIT, const GetByIdVariant& variant = GetByIdVariant())
    6762        : m_state(state)
    68         , m_structureSet(structureSet)
    69         , m_chain(chain)
    70         , m_specificValue(specificValue)
    71         , m_offset(offset)
    7263        , m_wasSeenInJIT(wasSeenInJIT)
    7364    {
    74         ASSERT((state == Simple) == (offset != invalidOffset));
     65        ASSERT((state == Simple) == variant.isSet());
     66        m_variants.append(variant);
    7567    }
    7668   
     
    8577    bool operator!() const { return !isSet(); }
    8678    bool isSimple() const { return m_state == Simple; }
     79
     80    size_t numVariants() const { return m_variants.size(); }
     81    const Vector<GetByIdVariant, 1>& variants() const { return m_variants; }
     82    const GetByIdVariant& at(size_t index) const { return m_variants[index]; }
     83    const GetByIdVariant& operator[](size_t index) const { return at(index); }
     84
    8785    bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
    8886    bool makesCalls() const { return m_state == MakesCalls; }
    8987   
    90     const StructureSet& structureSet() const { return m_structureSet; }
    91     IntendedStructureChain* chain() const { return const_cast<IntendedStructureChain*>(m_chain.get()); } // Returns null if this is a direct access.
    92     JSValue specificValue() const { return m_specificValue; } // Returns JSValue() if there is no specific value.
    93     PropertyOffset offset() const { return m_offset; }
     88    bool wasSeenInJIT() const { return m_wasSeenInJIT; }
    9489   
    95     bool wasSeenInJIT() const { return m_wasSeenInJIT; }
     90    void dump(PrintStream&) const;
    9691   
    9792private:
     
    10297    static GetByIdStatus computeForStubInfo(const ConcurrentJITLocker&, CodeBlock*, StructureStubInfo*, StringImpl* uid);
    10398#endif
    104     static void computeForChain(GetByIdStatus& result, CodeBlock*, StringImpl* uid);
     99    bool computeForChain(CodeBlock*, StringImpl* uid, PassRefPtr<IntendedStructureChain>);
    105100    static GetByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, StringImpl* uid);
    106101   
    107102    State m_state;
    108     StructureSet m_structureSet;
    109     RefPtr<IntendedStructureChain> m_chain;
    110     JSValue m_specificValue;
    111     PropertyOffset m_offset;
     103    Vector<GetByIdVariant, 1> m_variants;
    112104    bool m_wasSeenInJIT;
    113105};
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r164059 r164207  
    14521452                    m_graph.m_vm, structure,
    14531453                    m_graph.identifiers()[node->identifierNumber()]);
    1454                 if (status.isSimple()) {
     1454                if (status.isSimple() && status.numVariants() == 1) {
    14551455                    // Assert things that we can't handle and that the computeFor() method
    14561456                    // above won't be able to return.
    1457                     ASSERT(status.structureSet().size() == 1);
    1458                     ASSERT(!status.chain());
     1457                    ASSERT(status[0].structureSet().size() == 1);
     1458                    ASSERT(!status[0].chain());
    14591459                   
    1460                     if (status.specificValue())
    1461                         setConstant(node, status.specificValue());
     1460                    if (status[0].specificValue())
     1461                        setConstant(node, status[0].specificValue());
    14621462                    else
    14631463                        forNode(node).makeHeapTop();
    1464                     filter(node->child1(), status.structureSet());
     1464                    filter(node->child1(), status[0].structureSet());
    14651465                   
    14661466                    m_state.setFoundConstants(true);
     
    16301630       
    16311631    case GetByOffset: {
     1632        forNode(node).makeHeapTop();
     1633        break;
     1634    }
     1635       
     1636    case MultiGetByOffset: {
     1637        AbstractValue& value = forNode(node->child1());
     1638        ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
     1639
     1640        if (Structure* structure = value.bestProvenStructure()) {
     1641            bool done = false;
     1642            for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
     1643                const GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
     1644                if (!variant.structureSet().contains(structure))
     1645                    continue;
     1646               
     1647                if (variant.chain())
     1648                    break;
     1649               
     1650                filter(value, structure);
     1651                forNode(node).makeHeapTop();
     1652                m_state.setFoundConstants(true);
     1653                done = true;
     1654                break;
     1655            }
     1656            if (done)
     1657                break;
     1658        }
     1659       
     1660        StructureSet set;
     1661        for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;)
     1662            set.addAll(node->multiGetByOffsetData().variants[i].structureSet());
     1663       
     1664        filter(value, set);
    16321665        forNode(node).makeHeapTop();
    16331666        break;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r164059 r164207  
    181181        int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber,
    182182        const GetByIdStatus&);
     183    Node* emitPrototypeChecks(const GetByIdVariant&);
    183184
    184185    Node* getScope(bool skipTop, unsigned skipCount);
     
    18281829}
    18291830
     1831Node* ByteCodeParser::emitPrototypeChecks(const GetByIdVariant& variant)
     1832{
     1833    Node* base = 0;
     1834    m_graph.chains().addLazily(variant.chain());
     1835    Structure* currentStructure = variant.structureSet().singletonStructure();
     1836    JSObject* currentObject = 0;
     1837    for (unsigned i = 0; i < variant.chain()->size(); ++i) {
     1838        currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
     1839        currentStructure = variant.chain()->at(i);
     1840        base = cellConstantWithStructureCheck(currentObject, currentStructure);
     1841    }
     1842    RELEASE_ASSERT(base);
     1843    return base;
     1844}
     1845
    18301846void ByteCodeParser::handleGetById(
    18311847    int destinationOperand, SpeculatedType prediction, Node* base, unsigned identifierNumber,
     
    18401856    }
    18411857   
    1842     ASSERT(getByIdStatus.structureSet().size());
     1858    if (getByIdStatus.numVariants() > 1) {
     1859        if (!isFTL(m_graph.m_plan.mode)) {
     1860            set(VirtualRegister(destinationOperand),
     1861                addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
     1862            return;
     1863        }
     1864       
     1865        // 1) Emit prototype structure checks for all chains. This could sort of maybe not be
     1866        //    optimal, if there is some rarely executed case in the chain that requires a lot
     1867        //    of checks and those checks are not watchpointable.
     1868        for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) {
     1869            if (getByIdStatus[variantIndex].chain())
     1870                emitPrototypeChecks(getByIdStatus[variantIndex]);
     1871        }
     1872       
     1873        // 2) Emit a MultiGetByOffset
     1874        MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
     1875        data->variants = getByIdStatus.variants();
     1876        data->identifierNumber = identifierNumber;
     1877        set(VirtualRegister(destinationOperand),
     1878            addToGraph(MultiGetByOffset, OpInfo(data), OpInfo(prediction), base));
     1879        return;
     1880    }
     1881   
     1882    ASSERT(getByIdStatus.numVariants() == 1);
     1883    GetByIdVariant variant = getByIdStatus[0];
    18431884               
    18441885    if (m_graph.compilation())
     
    18471888    Node* originalBaseForBaselineJIT = base;
    18481889               
    1849     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
    1850    
    1851     if (getByIdStatus.chain()) {
    1852         m_graph.chains().addLazily(getByIdStatus.chain());
    1853         Structure* currentStructure = getByIdStatus.structureSet().singletonStructure();
    1854         JSObject* currentObject = 0;
    1855         for (unsigned i = 0; i < getByIdStatus.chain()->size(); ++i) {
    1856             currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
    1857             currentStructure = getByIdStatus.chain()->at(i);
    1858             base = cellConstantWithStructureCheck(currentObject, currentStructure);
    1859         }
    1860     }
     1890    addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
     1891   
     1892    if (variant.chain())
     1893        base = emitPrototypeChecks(variant);
    18611894   
    18621895    // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to
     
    18661899    // access was compiled to a WeakJSConstant specific value, in which case we might not
    18671900    // have any explicit use of the base at all.
    1868     if (getByIdStatus.specificValue() || originalBaseForBaselineJIT != base)
     1901    if (variant.specificValue() || originalBaseForBaselineJIT != base)
    18691902        addToGraph(Phantom, originalBaseForBaselineJIT);
    18701903   
    1871     if (getByIdStatus.specificValue()) {
    1872         ASSERT(getByIdStatus.specificValue().isCell());
    1873        
    1874         set(VirtualRegister(destinationOperand), cellConstant(getByIdStatus.specificValue().asCell()));
     1904    if (variant.specificValue()) {
     1905        ASSERT(variant.specificValue().isCell());
     1906       
     1907        set(VirtualRegister(destinationOperand), cellConstant(variant.specificValue().asCell()));
    18751908        return;
    18761909    }
    18771910   
    18781911    handleGetByOffset(
    1879         destinationOperand, prediction, base, identifierNumber, getByIdStatus.offset());
     1912        destinationOperand, prediction, base, identifierNumber, variant.offset());
    18801913}
    18811914
     
    31413174            case GlobalPropertyWithVarInjectionChecks: {
    31423175                GetByIdStatus status = GetByIdStatus::computeFor(*m_vm, structure, uid);
    3143                 if (status.takesSlowPath()) {
     3176                if (status.state() != GetByIdStatus::Simple || status.numVariants() != 1) {
    31443177                    set(VirtualRegister(dst), addToGraph(GetByIdFlush, OpInfo(identifierNumber), OpInfo(prediction), get(VirtualRegister(scope))));
    31453178                    break;
    31463179                }
    3147                 Node* base = cellConstantWithStructureCheck(globalObject, status.structureSet().singletonStructure());
     3180                Node* base = cellConstantWithStructureCheck(globalObject, status[0].structureSet().singletonStructure());
    31483181                addToGraph(Phantom, get(VirtualRegister(scope)));
    3149                 if (JSValue specificValue = status.specificValue())
     3182                if (JSValue specificValue = status[0].specificValue())
    31503183                    set(VirtualRegister(dst), cellConstant(specificValue.asCell()));
    31513184                else
  • trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp

    r164059 r164207  
    643643    }
    644644   
    645     Node* getByOffsetLoadElimination(unsigned identifierNumber, Node* child1)
    646     {
    647         for (unsigned i = m_indexInBlock; i--;) {
    648             Node* node = m_currentBlock->at(i);
    649             if (node == child1)
     645    Node* getByOffsetLoadElimination(unsigned identifierNumber, Node* base)
     646    {
     647        for (unsigned i = m_indexInBlock; i--;) {
     648            Node* node = m_currentBlock->at(i);
     649            if (node == base)
    650650                break;
    651651
    652652            switch (node->op()) {
    653653            case GetByOffset:
    654                 if (node->child1() == child1
     654                if (node->child2() == base
    655655                    && m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber)
    656656                    return node;
    657657                break;
    658658               
     659            case MultiGetByOffset:
     660                if (node->child1() == base
     661                    && node->multiGetByOffsetData().identifierNumber == identifierNumber)
     662                    return node;
     663                break;
     664               
    659665            case PutByOffset:
    660666                if (m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber) {
    661                     if (node->child1() == child1) // Must be same property storage.
     667                    if (node->child2() == base) // Must be same property storage.
    662668                        return node->child3().node();
    663669                    return 0;
     
    14021408            if (cseMode == StoreElimination)
    14031409                break;
    1404             setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child1().node()));
     1410            setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child2().node()));
     1411            break;
     1412           
     1413        case MultiGetByOffset:
     1414            if (cseMode == StoreElimination)
     1415                break;
     1416            setReplacement(getByOffsetLoadElimination(node->multiGetByOffsetData().identifierNumber, node->child1().node()));
    14051417            break;
    14061418           
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r164059 r164207  
    471471        return;
    472472       
     473    case MultiGetByOffset:
     474        read(AbstractHeap(NamedProperties, node->multiGetByOffsetData().identifierNumber));
     475        return;
     476       
    473477    case PutByOffset:
    474478        write(AbstractHeap(NamedProperties, graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber));
  • trunk/Source/JavaScriptCore/dfg/DFGCommon.h

    r163027 r164207  
    2929#include <wtf/Platform.h>
    3030
     31#include "DFGCompilationMode.h"
     32
    3133#if ENABLE(DFG_JIT)
    3234
     
    6466};
    6567
    66 inline bool verboseCompilationEnabled()
    67 {
    68     return Options::verboseCompilation() || Options::dumpGraphAtEachPhase();
    69 }
    70 
    71 inline bool logCompilationChanges()
    72 {
    73     return verboseCompilationEnabled() || Options::logCompilationChanges();
     68inline bool verboseCompilationEnabled(CompilationMode mode = DFGMode)
     69{
     70    return Options::verboseCompilation() || Options::dumpGraphAtEachPhase() || (isFTL(mode) && Options::verboseFTLCompilation());
     71}
     72
     73inline bool logCompilationChanges(CompilationMode mode = DFGMode)
     74{
     75    return verboseCompilationEnabled(mode) || Options::logCompilationChanges();
    7476}
    7577
     
    289291
    290292// Unconditionally disable DFG disassembly support if the DFG is not compiled in.
    291 inline bool shouldShowDisassembly()
     293inline bool shouldShowDisassembly(CompilationMode mode = DFGMode)
    292294{
    293295#if ENABLE(DFG_JIT)
    294     return Options::showDisassembly() || Options::showDFGDisassembly();
     296    return Options::showDisassembly() || Options::showDFGDisassembly() || (isFTL(mode) && Options::showFTLDisassembly());
    295297#else
    296298    return false;
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r163946 r164207  
    152152                break;
    153153            }
     154               
     155            case MultiGetByOffset: {
     156                Edge childEdge = node->child1();
     157                Node* child = childEdge.node();
     158                MultiGetByOffsetData& data = node->multiGetByOffsetData();
     159
     160                Structure* structure = m_state.forNode(child).bestProvenStructure();
     161                if (!structure)
     162                    break;
     163               
     164                for (unsigned i = data.variants.size(); i--;) {
     165                    const GetByIdVariant& variant = data.variants[i];
     166                    if (!variant.structureSet().contains(structure))
     167                        continue;
     168                   
     169                    if (variant.chain())
     170                        break;
     171                   
     172                    emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber);
     173                    eliminated = true;
     174                    break;
     175                }
     176                break;
     177            }
    154178       
    155179            case GetById:
    156180            case GetByIdFlush: {
    157                 NodeOrigin origin = node->origin;
    158181                Edge childEdge = node->child1();
    159182                Node* child = childEdge.node();
     
    167190                    break;
    168191               
    169                 bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton();
    170                 bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
    171                
    172192                GetByIdStatus status = GetByIdStatus::computeFor(
    173193                    vm(), structure, m_graph.identifiers()[identifierNumber]);
    174194               
    175                 if (!status.isSimple()) {
     195                if (!status.isSimple() || status.numVariants() != 1) {
    176196                    // FIXME: We could handle prototype cases.
    177197                    // https://bugs.webkit.org/show_bug.cgi?id=110386
     
    179199                }
    180200               
    181                 ASSERT(status.structureSet().size() == 1);
    182                 ASSERT(!status.chain());
    183                 ASSERT(status.structureSet().singletonStructure() == structure);
    184                
    185                 // Now before we do anything else, push the CFA forward over the GetById
    186                 // and make sure we signal to the loop that it should continue and not
    187                 // do any eliminations.
    188                 m_interpreter.execute(indexInBlock);
     201                emitGetByOffset(indexInBlock, node, structure, status[0], identifierNumber);
    189202                eliminated = true;
    190                
    191                 if (needsWatchpoint) {
    192                     m_insertionSet.insertNode(
    193                         indexInBlock, SpecNone, StructureTransitionWatchpoint, origin,
    194                         OpInfo(structure), childEdge);
    195                 } else if (needsCellCheck) {
    196                     m_insertionSet.insertNode(
    197                         indexInBlock, SpecNone, Phantom, origin, childEdge);
    198                 }
    199                
    200                 childEdge.setUseKind(KnownCellUse);
    201                
    202                 Edge propertyStorage;
    203                
    204                 if (isInlineOffset(status.offset()))
    205                     propertyStorage = childEdge;
    206                 else {
    207                     propertyStorage = Edge(m_insertionSet.insertNode(
    208                         indexInBlock, SpecNone, GetButterfly, origin, childEdge));
    209                 }
    210                
    211                 node->convertToGetByOffset(m_graph.m_storageAccessData.size(), propertyStorage);
    212                
    213                 StorageAccessData storageAccessData;
    214                 storageAccessData.offset = status.offset();
    215                 storageAccessData.identifierNumber = identifierNumber;
    216                 m_graph.m_storageAccessData.append(storageAccessData);
    217203                break;
    218204            }
     
    407393        return changed;
    408394    }
     395       
     396    void emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant& variant, unsigned identifierNumber)
     397    {
     398        NodeOrigin origin = node->origin;
     399        Edge childEdge = node->child1();
     400        Node* child = childEdge.node();
     401
     402        bool needsWatchpoint = !m_state.forNode(child).m_currentKnownStructure.hasSingleton();
     403        bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
     404       
     405        ASSERT(!variant.chain());
     406        ASSERT(variant.structureSet().contains(structure));
     407       
     408        // Now before we do anything else, push the CFA forward over the GetById
     409        // and make sure we signal to the loop that it should continue and not
     410        // do any eliminations.
     411        m_interpreter.execute(indexInBlock);
     412       
     413        if (needsWatchpoint) {
     414            m_insertionSet.insertNode(
     415                indexInBlock, SpecNone, StructureTransitionWatchpoint, origin,
     416                OpInfo(structure), childEdge);
     417        } else if (needsCellCheck) {
     418            m_insertionSet.insertNode(
     419                indexInBlock, SpecNone, Phantom, origin, childEdge);
     420        }
     421       
     422        if (variant.specificValue()) {
     423            m_graph.convertToConstant(node, variant.specificValue());
     424            return;
     425        }
     426       
     427        childEdge.setUseKind(KnownCellUse);
     428       
     429        Edge propertyStorage;
     430       
     431        if (isInlineOffset(variant.offset()))
     432            propertyStorage = childEdge;
     433        else {
     434            propertyStorage = Edge(m_insertionSet.insertNode(
     435                indexInBlock, SpecNone, GetButterfly, origin, childEdge));
     436        }
     437       
     438        node->convertToGetByOffset(m_graph.m_storageAccessData.size(), propertyStorage);
     439       
     440        StorageAccessData storageAccessData;
     441        storageAccessData.offset = variant.offset();
     442        storageAccessData.identifierNumber = identifierNumber;
     443        m_graph.m_storageAccessData.append(storageAccessData);
     444    }
    409445
    410446    void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell)
  • trunk/Source/JavaScriptCore/dfg/DFGDriver.cpp

    r163844 r164207  
    8383        return CompilationInvalidated;
    8484
    85     if (logCompilationChanges())
     85    if (logCompilationChanges(mode))
    8686        dataLog("DFG(Driver) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n");
    8787   
     
    116116        Worklist* worklist = ensureGlobalWorklistFor(mode);
    117117        plan->callback = callback;
    118         if (logCompilationChanges())
     118        if (logCompilationChanges(mode))
    119119            dataLog("Deferring DFG compilation of ", *codeBlock, " with queue length ", worklist->queueLength(), ".\n");
    120120        worklist->enqueue(plan);
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r164059 r164207  
    879879                fixEdge<KnownCellUse>(node->child1());
    880880            fixEdge<KnownCellUse>(node->child2());
     881            break;
     882        }
     883           
     884        case MultiGetByOffset: {
     885            fixEdge<CellUse>(node->child1());
    881886            break;
    882887        }
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r163946 r164207  
    247247        out.print(", ", static_cast<ptrdiff_t>(storageAccessData.offset));
    248248    }
     249    if (node->hasMultiGetByOffsetData()) {
     250        MultiGetByOffsetData& data = node->multiGetByOffsetData();
     251        out.print(comma, "id", data.identifierNumber, "{", identifiers()[data.identifierNumber], "}");
     252        for (unsigned i = 0; i < data.variants.size(); ++i)
     253            out.print(comma, inContext(data.variants[i], context));
     254    }
    249255    ASSERT(node->hasVariableAccessData(*this) == node->hasLocal(*this));
    250256    if (node->hasVariableAccessData(*this)) {
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r164059 r164207  
    178178    void convertToConstant(Node* node, JSValue value)
    179179    {
    180         convertToConstant(node, constantRegisterForConstant(value));
     180        if (value.isObject())
     181            node->convertToWeakConstant(value.asCell());
     182        else
     183            convertToConstant(node, constantRegisterForConstant(value));
    181184    }
    182185
     
    828831    SegmentedVector<NewArrayBufferData, 4> m_newArrayBufferData;
    829832    SegmentedVector<SwitchData, 4> m_switchData;
     833    Bag<MultiGetByOffsetData> m_multiGetByOffsetData;
    830834    Vector<InlineVariableData, 4> m_inlineVariableData;
    831835    OwnPtr<InlineCallFrameSet> m_inlineCallFrames;
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r164059 r164207  
    4242#include "DFGNodeType.h"
    4343#include "DFGVariableAccessData.h"
     44#include "GetByIdVariant.h"
    4445#include "JSCJSValue.h"
    4546#include "Operands.h"
     
    5354class Graph;
    5455struct BasicBlock;
     56
     57struct MultiGetByOffsetData {
     58    unsigned identifierNumber;
     59    Vector<GetByIdVariant, 2> variants;
     60};
    5561
    5662struct StructureTransitionData {
     
    407413    void convertToGetByOffset(unsigned storageAccessDataIndex, Edge storage)
    408414    {
    409         ASSERT(m_op == GetById || m_op == GetByIdFlush);
     415        ASSERT(m_op == GetById || m_op == GetByIdFlush || m_op == MultiGetByOffset);
    410416        m_opInfo = storageAccessDataIndex;
    411417        children.setChild2(children.child1());
     
    906912        case Construct:
    907913        case GetByOffset:
     914        case MultiGetByOffset:
    908915        case GetClosureVar:
    909916        case ArrayPop:
     
    10531060        ASSERT(hasStorageAccessData());
    10541061        return m_opInfo;
     1062    }
     1063   
     1064    bool hasMultiGetByOffsetData()
     1065    {
     1066        return op() == MultiGetByOffset;
     1067    }
     1068   
     1069    MultiGetByOffsetData& multiGetByOffsetData()
     1070    {
     1071        return *reinterpret_cast<MultiGetByOffsetData*>(m_opInfo);
    10551072    }
    10561073   
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r164059 r164207  
    176176    macro(TypedArrayWatchpoint, NodeMustGenerate) \
    177177    macro(GetByOffset, NodeResultJS) \
     178    macro(MultiGetByOffset, NodeResultJS) \
    178179    macro(PutByOffset, NodeMustGenerate) \
    179180    macro(GetArrayLength, NodeResultInt32) \
  • trunk/Source/JavaScriptCore/dfg/DFGPhase.h

    r163802 r164207  
    5252    const char* name() const { return m_name; }
    5353   
     54    Graph& graph() { return m_graph; }
     55   
    5456    // Each phase must have a run() method.
    5557   
     
    7476{
    7577    bool result = phase.run();
    76     if (result && logCompilationChanges())
     78    if (result && logCompilationChanges(phase.graph().m_plan.mode))
    7779        dataLogF("Phase %s changed the IR.\n", phase.name());
    7880    return result;
  • trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp

    r164059 r164207  
    8686{
    8787    GraphDumpMode modeForFinalValidate = DumpGraph;
    88     if (verboseCompilationEnabled()) {
     88    if (verboseCompilationEnabled(graph.m_plan.mode)) {
    8989        dataLog(text, "\n");
    9090        graph.dump();
     
    150150    CompilationScope compilationScope;
    151151
    152     if (logCompilationChanges())
     152    if (logCompilationChanges(mode))
    153153        dataLog("DFG(Plan) compiling ", *codeBlock, " with ", mode, ", number of instructions = ", codeBlock->instructionCount(), "\n");
    154154
     
    184184Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
    185185{
    186     if (verboseCompilationEnabled() && osrEntryBytecodeIndex != UINT_MAX) {
     186    if (verboseCompilationEnabled(mode) && osrEntryBytecodeIndex != UINT_MAX) {
    187187        dataLog("\n");
    188188        dataLog("Compiler must handle OSR entry from bc#", osrEntryBytecodeIndex, " with values: ", mustHandleValues, "\n");
     
    231231    dfg.m_fixpointState = FixpointNotConverged;
    232232    for (;; ++count) {
    233         if (logCompilationChanges())
     233        if (logCompilationChanges(mode))
    234234            dataLogF("DFG beginning optimization fixpoint iteration #%u.\n", count);
    235235        bool changed = false;
     
    251251    }
    252252   
    253     if (logCompilationChanges())
     253    if (logCompilationChanges(mode))
    254254        dataLogF("DFG optimization fixpoint converged in %u iterations.\n", count);
    255255
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r164059 r164207  
    178178        case GetMyArgumentByValSafe:
    179179        case GetByOffset:
     180        case MultiGetByOffset:
    180181        case Call:
    181182        case Construct:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r164059 r164207  
    254254    case ConstantStoragePointer:
    255255    case Check:
     256    case MultiGetByOffset:
    256257        return true;
    257258       
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r164059 r164207  
    46904690    case CheckInBounds:
    46914691    case ArithIMul:
     4692    case MultiGetByOffset:
    46924693        RELEASE_ASSERT_NOT_REACHED();
    46934694        break;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r164059 r164207  
    50115011    case CheckInBounds:
    50125012    case ArithIMul:
     5013    case MultiGetByOffset:
    50135014        RELEASE_ASSERT_NOT_REACHED();
    50145015        break;
  • trunk/Source/JavaScriptCore/dfg/DFGTypeCheckHoistingPhase.cpp

    r164059 r164207  
    247247                case HardPhantom:
    248248                case MovHint:
     249                case MultiGetByOffset:
    249250                    // Don't count these uses.
    250251                    break;
     
    346347                case HardPhantom:
    347348                case MovHint:
     349                case MultiGetByOffset:
    348350                    // Don't count these uses.
    349351                    break;
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r164178 r164207  
    138138    case GetById:
    139139    case ToThis:
     140    case MultiGetByOffset:
    140141        // These are OK.
    141142        break;
  • trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp

    r164069 r164207  
    248248            OSRExit& exit = jitCode->osrExit[i];
    249249           
    250             if (Options::verboseCompilation())
     250            if (verboseCompilationEnabled())
    251251                dataLog("Handling OSR stackmap #", exit.m_stackmapID, " for ", exit.m_codeOrigin, "\n");
    252252
     
    270270            }
    271271           
    272             if (Options::verboseCompilation()) {
     272            if (verboseCompilationEnabled()) {
    273273                DumpContext context;
    274274                dataLog("    Exit values: ", inContext(exit.m_values, &context), "\n");
     
    287287            GetByIdDescriptor& getById = state.getByIds[i];
    288288           
    289             if (Options::verboseCompilation())
     289            if (verboseCompilationEnabled())
    290290                dataLog("Handling GetById stackmap #", getById.stackmapID(), "\n");
    291291           
     
    325325            PutByIdDescriptor& putById = state.putByIds[i];
    326326           
    327             if (Options::verboseCompilation())
     327            if (verboseCompilationEnabled())
    328328                dataLog("Handling PutById stackmap #", putById.stackmapID(), "\n");
    329329           
     
    542542        }
    543543
    544         if (DFG::shouldShowDisassembly() || DFG::verboseCompilationEnabled())
     544        if (shouldShowDisassembly() || verboseCompilationEnabled())
    545545            state.dumpState("after optimization");
    546546   
     
    578578    state.jitCode->unwindInfo.parse(
    579579        state.compactUnwind, state.compactUnwindSize, state.generatedFunction);
    580     if (DFG::shouldShowDisassembly())
     580    if (shouldShowDisassembly())
    581581        dataLog("Unwind info for ", CodeBlockWithJITType(state.graph.m_codeBlock, JITCode::FTLJIT), ":\n    ", state.jitCode->unwindInfo, "\n");
    582582   
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r164178 r164207  
    464464        case GetByOffset:
    465465            compileGetByOffset();
     466            break;
     467        case MultiGetByOffset:
     468            compileMultiGetByOffset();
    466469            break;
    467470        case PutByOffset:
     
    30763079    }
    30773080   
     3081    void compileMultiGetByOffset()
     3082    {
     3083        LValue base = lowCell(m_node->child1());
     3084       
     3085        MultiGetByOffsetData& data = m_node->multiGetByOffsetData();
     3086       
     3087        Vector<LBasicBlock, 2> blocks(data.variants.size());
     3088        for (unsigned i = data.variants.size(); i--;)
     3089            blocks[i] = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset case ", i));
     3090        LBasicBlock exit = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset fail"));
     3091        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("MultiGetByOffset continuation"));
     3092       
     3093        Vector<SwitchCase, 2> cases;
     3094        for (unsigned i = data.variants.size(); i--;) {
     3095            GetByIdVariant variant = data.variants[i];
     3096            for (unsigned j = variant.structureSet().size(); j--;)
     3097                cases.append(SwitchCase(weakPointer(variant.structureSet()[j]), blocks[i]));
     3098        }
     3099        m_out.switchInstruction(m_out.loadPtr(base, m_heaps.JSCell_structure), cases, exit);
     3100       
     3101        LBasicBlock lastNext = m_out.m_nextBlock;
     3102       
     3103        Vector<ValueFromBlock, 2> results;
     3104        for (unsigned i = data.variants.size(); i--;) {
     3105            m_out.appendTo(blocks[i], i + 1 < data.variants.size() ? blocks[i + 1] : exit);
     3106           
     3107            GetByIdVariant variant = data.variants[i];
     3108            LValue result;
     3109            if (variant.specificValue())
     3110                result = m_out.constInt64(JSValue::encode(variant.specificValue()));
     3111            else {
     3112                LValue propertyBase;
     3113                if (variant.chain())
     3114                    propertyBase = weakPointer(variant.chain()->terminalPrototype());
     3115                else
     3116                    propertyBase = base;
     3117                if (!isInlineOffset(variant.offset()))
     3118                    propertyBase = m_out.loadPtr(propertyBase, m_heaps.JSObject_butterfly);
     3119                result = m_out.load64(
     3120                    m_out.address(
     3121                        m_heaps.properties[data.identifierNumber],
     3122                        propertyBase,
     3123                        offsetRelativeToBase(variant.offset())));
     3124            }
     3125           
     3126            results.append(m_out.anchor(result));
     3127            m_out.jump(continuation);
     3128        }
     3129       
     3130        m_out.appendTo(exit, continuation);
     3131        terminate(BadCache);
     3132        m_out.unreachable();
     3133       
     3134        m_out.appendTo(continuation, lastNext);
     3135        setJSValue(m_out.phi(m_out.int64, results));
     3136    }
     3137   
    30783138    void compilePutByOffset()
    30793139    {
  • trunk/Source/JavaScriptCore/ftl/FTLState.h

    r164069 r164207  
    3131#if ENABLE(FTL_JIT)
    3232
     33#include "DFGCommon.h"
    3334#include "DFGGraph.h"
    3435#include "FTLAbbreviations.h"
     
    4243
    4344namespace JSC { namespace FTL {
     45
     46inline bool verboseCompilationEnabled()
     47{
     48    return DFG::verboseCompilationEnabled(DFG::FTLMode);
     49}
     50
     51inline bool showDisassembly()
     52{
     53    return DFG::shouldShowDisassembly(DFG::FTLMode);
     54}
    4455
    4556class State {
  • trunk/Source/JavaScriptCore/jsc.cpp

    r164059 r164207  
    239239static NO_RETURN_WITH_VALUE EncodedJSValue JSC_HOST_CALL functionQuit(ExecState*);
    240240static EncodedJSValue JSC_HOST_CALL functionFalse(ExecState*);
     241static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
    241242
    242243#if ENABLE(SAMPLING_FLAGS)
     
    374375        putDirectNativeFunction(vm, this, Identifier(&vm, "DFGTrue"), 0, functionFalse, DFGTrue, DontEnum | JSC::Function);
    375376       
     377        addFunction(vm, "effectful42", functionEffectful42, 0);
     378       
    376379        JSArray* array = constructEmptyArray(globalExec(), 0);
    377380        for (size_t i = 0; i < arguments.size(); ++i)
     
    726729{
    727730    return JSValue::encode(jsBoolean(false));
     731}
     732
     733EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*)
     734{
     735    return JSValue::encode(jsNumber(42));
    728736}
    729737
  • trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp

    r163844 r164207  
    3030#include "JSCInlines.h"
    3131#include "StructureChain.h"
     32#include <wtf/CommaPrinter.h>
    3233
    3334namespace JSC {
     
    146147}
    147148
     149void IntendedStructureChain::dump(PrintStream& out) const
     150{
     151    dumpInContext(out, 0);
     152}
     153
     154void IntendedStructureChain::dumpInContext(PrintStream& out, DumpContext* context) const
     155{
     156    out.print(
     157        "(global = ", RawPointer(m_globalObject), ", head = ",
     158        pointerDumpInContext(m_head, context), ", vector = [");
     159    CommaPrinter comma;
     160    for (unsigned i = 0; i < m_vector.size(); ++i)
     161        out.print(comma, pointerDumpInContext(m_vector[i], context));
     162    out.print("])");
     163}
     164
    148165} // namespace JSC
    149166
  • trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.h

    r163691 r164207  
    3636class StructureChain;
    3737class VM;
     38struct DumpContext;
    3839
    3940class IntendedStructureChain : public RefCounted<IntendedStructureChain> {
     
    6263   
    6364    void visitChildren(SlotVisitor&);
     65    void dump(PrintStream&) const;
     66    void dumpInContext(PrintStream&, DumpContext*) const;
    6467   
    6568private:
  • trunk/Source/JavaScriptCore/runtime/Options.cpp

    r163794 r164207  
    190190    if (Options::showDisassembly()
    191191        || Options::showDFGDisassembly()
     192        || Options::showFTLDisassembly()
    192193        || Options::dumpBytecodeAtDFGTime()
    193194        || Options::dumpGraphAtEachPhase()
    194195        || Options::verboseCompilation()
     196        || Options::verboseFTLCompilation()
    195197        || Options::logCompilationChanges()
    196198        || Options::validateGraph()
  • trunk/Source/JavaScriptCore/runtime/Options.h

    r163838 r164207  
    113113    v(bool, showDisassembly, false) \
    114114    v(bool, showDFGDisassembly, false) \
     115    v(bool, showFTLDisassembly, false) \
    115116    v(bool, showAllDFGNodes, false) \
    116117    v(optionRange, bytecodeRangeToDFGCompile, 0) \
     
    118119    v(bool, dumpGraphAtEachPhase, false) \
    119120    v(bool, verboseCompilation, false) \
     121    v(bool, verboseFTLCompilation, false) \
    120122    v(bool, logCompilationChanges, false) \
    121123    v(bool, printEachOSRExit, false) \
  • trunk/Source/WTF/ChangeLog

    r164190 r164207  
     12014-02-15  Filip Pizlo  <fpizlo@apple.com>
     2
     3        FTL should inline polymorphic heap accesses
     4        https://bugs.webkit.org/show_bug.cgi?id=128795
     5
     6        Reviewed by Oliver Hunt.
     7
     8        * wtf/PrintStream.h:
     9        (WTF::PointerDumpInContext::PointerDumpInContext):
     10        (WTF::PointerDumpInContext::dump):
     11        (WTF::pointerDumpInContext):
     12
    1132014-02-16  Zan Dobersek  <zdobersek@igalia.com>
    214
  • trunk/Source/WTF/wtf/PrintStream.h

    r159448 r164207  
    366366
    367367template<typename T, typename U>
     368class PointerDumpInContext {
     369public:
     370    PointerDumpInContext(const T* ptr, U* context)
     371        : m_ptr(ptr)
     372        , m_context(context)
     373    {
     374    }
     375   
     376    void dump(PrintStream& out) const
     377    {
     378        if (m_ptr)
     379            m_ptr->dumpInContext(out, m_context);
     380        else
     381            out.print("(null)");
     382    }
     383
     384private:
     385    const T* m_ptr;
     386    U* m_context;
     387};
     388
     389template<typename T, typename U>
     390PointerDumpInContext<T, U> pointerDumpInContext(const T* ptr, U* context)
     391{
     392    return PointerDumpInContext<T, U>(ptr, context);
     393}
     394
     395template<typename T, typename U>
    368396class ValueIgnoringContext {
    369397public:
     
    397425using WTF::inContext;
    398426using WTF::pointerDump;
     427using WTF::pointerDumpInContext;
    399428
    400429#endif // PrintStream_h
Note: See TracChangeset for help on using the changeset viewer.