DFG should hoist structure checks
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 2 Aug 2012 04:32:30 +0000 (04:32 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 2 Aug 2012 04:32:30 +0000 (04:32 +0000)
commit6d0cc74f63c68fe11b2dc6ff7b7ecccf118badb6
treec8f3b43ad69dbadc95a7f6c19c86dfea7e677686
parentf9daaf8db381106f5eb3cde313e256a179c7523e
DFG should hoist structure checks
https://bugs.webkit.org/show_bug.cgi?id=92696

Source/JavaScriptCore:

Reviewed by Gavin Barraclough.

This hoists structure checks in the same way that we would hoist array checks, but with added
complexity to cope with the fact that the structure of an object may change. This is handled
by performing a side effects analysis over the region in which the respective variable is
live. If a structure clobbering side effect may happen then we either hoist the structure
checks and fall back on structure transition watchpoints (if the watchpoint set is still
valid), or we avoid hoisting altogether.

Doing this required teaching the CFA that we may have an expectation that an object has a
particular structure even after structure clobbering happens, in the sense that structure
proofs that were cobbered can be revived using watchpoints. CFA must know about this so that
OSR entry may know about it, since we cannot allow entry to happen if the variable has a
clobbered structure proof, will have a watchpoint to revive the proof, and the variable in
the baseline JIT has a completely unrelated structure.

This is mostly performance neutral.

* CMakeLists.txt:
* GNUmakefile.list.am:
* JavaScriptCore.xcodeproj/project.pbxproj:
* Target.pri:
* bytecode/ValueRecovery.h:
(JSC::ValueRecovery::isSet):
(JSC::ValueRecovery::operator!):
(ValueRecovery):
* dfg/DFGAbstractState.cpp:
(JSC::DFG::AbstractState::execute):
(JSC::DFG::AbstractState::clobberWorld):
(DFG):
(JSC::DFG::AbstractState::clobberCapturedVars):
* dfg/DFGAbstractState.h:
(AbstractState):
* dfg/DFGAbstractValue.h:
(JSC::DFG::AbstractValue::clear):
(JSC::DFG::AbstractValue::isClear):
(JSC::DFG::AbstractValue::makeTop):
(JSC::DFG::AbstractValue::isTop):
(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::operator==):
(JSC::DFG::AbstractValue::merge):
(JSC::DFG::AbstractValue::filter):
(JSC::DFG::AbstractValue::validate):
(JSC::DFG::AbstractValue::validateForEntry):
(AbstractValue):
(JSC::DFG::AbstractValue::checkConsistency):
(JSC::DFG::AbstractValue::dump):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::setLocal):
(JSC::DFG::ByteCodeParser::getArgument):
(JSC::DFG::ByteCodeParser::setArgument):
(JSC::DFG::ByteCodeParser::parseBlock):
(JSC::DFG::ByteCodeParser::fixVariableAccessSpeculations):
* dfg/DFGCSEPhase.cpp:
(JSC::DFG::CSEPhase::checkStructureLoadElimination):
(JSC::DFG::CSEPhase::structureTransitionWatchpointElimination):
(JSC::DFG::CSEPhase::putStructureStoreElimination):
(JSC::DFG::CSEPhase::getLocalLoadElimination):
(JSC::DFG::CSEPhase::performNodeCSE):
* dfg/DFGDriver.cpp:
(JSC::DFG::compile):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::vote):
(Graph):
* dfg/DFGNode.h:
(JSC::DFG::Node::convertToStructureTransitionWatchpoint):
(Node):
(JSC::DFG::Node::hasStructureSet):
* dfg/DFGNodeType.h:
(DFG):
* dfg/DFGOSREntry.cpp:
(JSC::DFG::prepareOSREntry):
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
(PredictionPropagationPhase):
(JSC::DFG::PredictionPropagationPhase::doRoundOfDoubleVoting):
* dfg/DFGSpeculativeJIT.h:
(SpeculativeJIT):
(JSC::DFG::SpeculativeJIT::forwardSpeculationCheck):
(JSC::DFG::SpeculativeJIT::speculationCheckWithConditionalDirection):
(JSC::DFG::SpeculativeJIT::terminateSpeculativeExecutionWithConditionalDirection):
(JSC::DFG::SpeculateCellOperand::SpeculateCellOperand):
(JSC::DFG::SpeculateCellOperand::gpr):
(SpeculateCellOperand):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::fillSpeculateCell):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStructureCheckHoistingPhase.cpp: Added.
(DFG):
(StructureCheckHoistingPhase):
(JSC::DFG::StructureCheckHoistingPhase::StructureCheckHoistingPhase):
(JSC::DFG::StructureCheckHoistingPhase::run):
(JSC::DFG::StructureCheckHoistingPhase::noticeStructureCheck):
(JSC::DFG::StructureCheckHoistingPhase::noticeClobber):
(JSC::DFG::StructureCheckHoistingPhase::clobber):
(CheckData):
(JSC::DFG::StructureCheckHoistingPhase::CheckData::CheckData):
(JSC::DFG::performStructureCheckHoisting):
* dfg/DFGStructureCheckHoistingPhase.h: Added.
(DFG):
* dfg/DFGVariableAccessData.h:
(VariableAccessData):
(JSC::DFG::VariableAccessData::VariableAccessData):
(JSC::DFG::VariableAccessData::mergeStructureCheckHoistingFailed):
(JSC::DFG::VariableAccessData::structureCheckHoistingFailed):
(JSC::DFG::VariableAccessData::clearVotes):
(JSC::DFG::VariableAccessData::vote):
(JSC::DFG::VariableAccessData::voteRatio):
(JSC::DFG::VariableAccessData::shouldUseDoubleFormatAccordingToVote):
* runtime/Options.h:
(JSC):

LayoutTests:

Rubber stamped by Gavin Barraclough.

Added a new test that covers the following scenarios:

- OSR entry if a variable with a hoisted check has an unexpected structure, structures get clobbered, and
  we're protecting ourselves with structure transition watchpoints.

- OSR exit on hoisted structure checks, if the object doesn't have the expected structure, and where the
  source of the assignment is side-effecting.

I combined these into a single test because there is no way to test the latter without testing the former.

* fast/js/dfg-osr-entry-hoisted-clobbered-structure-check-expected.txt: Added.
* fast/js/dfg-osr-entry-hoisted-clobbered-structure-check.html: Added.
* fast/js/jsc-test-list:
* fast/js/script-tests/dfg-osr-entry-hoisted-clobbered-structure-check.js: Added.
(foo):
(bar):
(baz):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@124404 268f45cc-cd09-0410-ab3c-d52691b4dbfc
30 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/js/dfg-osr-entry-hoisted-clobbered-structure-check-expected.txt [new file with mode: 0644]
LayoutTests/fast/js/dfg-osr-entry-hoisted-clobbered-structure-check.html [new file with mode: 0644]
LayoutTests/fast/js/jsc-test-list
LayoutTests/fast/js/script-tests/dfg-osr-entry-hoisted-clobbered-structure-check.js [new file with mode: 0644]
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/GNUmakefile.list.am
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/Target.pri
Source/JavaScriptCore/bytecode/ValueRecovery.h
Source/JavaScriptCore/dfg/DFGAbstractState.cpp
Source/JavaScriptCore/dfg/DFGAbstractState.h
Source/JavaScriptCore/dfg/DFGAbstractValue.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
Source/JavaScriptCore/dfg/DFGDriver.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGOSREntry.cpp
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGStructureCheckHoistingPhase.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGVariableAccessData.h
Source/JavaScriptCore/runtime/Options.h