diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-08-12 09:27:39 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-08-12 09:27:39 +0200 |
commit | 3749d61e1f7a59f5ec5067e560af1eb610c82015 (patch) | |
tree | 73dc228333948738bbe02976cacca8cd382bc978 /Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp | |
parent | b32b4dcd9a51ab8de6afc53d9e17f8707e1f7a5e (diff) |
Imported WebKit commit a77350243e054f3460d1137301d8b3faee3d2052 (http://svn.webkit.org/repository/webkit/trunk@125365)
New snapshot with build fixes for latest API changes in Qt and all WK1 Win MSVC fixes upstream
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp | 159 |
1 files changed, 158 insertions, 1 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp index 179ad45fa..f17e2d7e4 100644 --- a/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp +++ b/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp @@ -56,6 +56,163 @@ SpeculativeJIT::~SpeculativeJIT() WTF::deleteAllValues(m_slowPathGenerators); } +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail) +{ + if (!m_compileOkay) + return; + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_stream->size())); +} + +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail); +} + +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps(); + for (unsigned i = 0; i < jumpVector.size(); ++i) + speculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i]); +} + +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::JumpList& jumpsToFail) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail); +} + +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) +{ + if (!m_compileOkay) + return; + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + m_jit.codeBlock()->appendSpeculationRecovery(recovery); + m_jit.codeBlock()->appendOSRExit(OSRExit(kind, jsValueSource, m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), jumpToFail, this, m_stream->size(), m_jit.codeBlock()->numberOfSpeculationRecoveries())); +} + +void SpeculativeJIT::speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail, const SpeculationRecovery& recovery) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail, recovery); +} + +JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex) +{ + if (!m_compileOkay) + return 0; + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + OSRExit& exit = m_jit.codeBlock()->osrExit( + m_jit.codeBlock()->appendOSRExit( + OSRExit(kind, jsValueSource, + m_jit.graph().methodOfGettingAValueProfileFor(nodeIndex), + JITCompiler::Jump(), this, m_stream->size()))); + exit.m_watchpointIndex = m_jit.codeBlock()->appendWatchpoint( + JumpReplacementWatchpoint(m_jit.watchpointLabel())); + return &m_jit.codeBlock()->watchpoint(exit.m_watchpointIndex); +} + +JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind) +{ + return speculationWatchpoint(kind, JSValueSource(), NoNode); +} + +void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail); + +#if !ASSERT_DISABLED + if (!valueRecovery) { + // Check that the preceding node was a SetLocal with the same code origin. + Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(m_indexInBlock - 1)); + ASSERT(setLocal->op() == SetLocal); + ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin); + } +#endif + + unsigned setLocalIndexInBlock = m_indexInBlock + 1; + + Node* setLocal = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock)); + bool hadInt32ToDouble = false; + + if (setLocal->op() == Int32ToDouble) { + setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock)); + hadInt32ToDouble = true; + } + if (setLocal->op() == Flush || setLocal->op() == Phantom) + setLocal = &at(m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock)); + + if (!!valueRecovery) { + if (hadInt32ToDouble) + ASSERT(at(setLocal->child1()).child1() == m_compileIndex); + else + ASSERT(setLocal->child1() == m_compileIndex); + } + ASSERT(setLocal->op() == SetLocal); + ASSERT(setLocal->codeOrigin == at(m_compileIndex).codeOrigin); + + Node* nextNode = &at(m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1)); + ASSERT(nextNode->codeOrigin != at(m_compileIndex).codeOrigin); + + OSRExit& exit = m_jit.codeBlock()->lastOSRExit(); + exit.m_codeOrigin = nextNode->codeOrigin; + + if (!valueRecovery) + return; + exit.m_lastSetOperand = setLocal->local(); + exit.m_valueRecoveryOverride = adoptRef( + new ValueRecoveryOverride(setLocal->local(), valueRecovery)); +} + +void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& valueRecovery) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + Vector<MacroAssembler::Jump, 16> jumpVector = jumpsToFail.jumps(); + for (unsigned i = 0; i < jumpVector.size(); ++i) + forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpVector[i], valueRecovery); +} + +void SpeculativeJIT::speculationCheckWithConditionalDirection(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, bool isForward) +{ + if (isForward) + forwardSpeculationCheck(kind, jsValueSource, nodeIndex, jumpToFail); + else + speculationCheck(kind, jsValueSource, nodeIndex, jumpToFail); +} + +void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); +#if DFG_ENABLE(DEBUG_VERBOSE) + dataLog("SpeculativeJIT was terminated.\n"); +#endif + if (!m_compileOkay) + return; + speculationCheck(kind, jsValueRegs, nodeIndex, m_jit.jump()); + m_compileOkay = false; +} + +void SpeculativeJIT::terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); + terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.index()); +} + +void SpeculativeJIT::terminateSpeculativeExecutionWithConditionalDirection(ExitKind kind, JSValueRegs jsValueRegs, NodeIndex nodeIndex, bool isForward) +{ + ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes); +#if DFG_ENABLE(DEBUG_VERBOSE) + dataLog("SpeculativeJIT was terminated.\n"); +#endif + if (!m_compileOkay) + return; + speculationCheckWithConditionalDirection(kind, jsValueRegs, nodeIndex, m_jit.jump(), isForward); + m_compileOkay = false; +} + void SpeculativeJIT::addSlowPathGenerator(PassOwnPtr<SlowPathGenerator> slowPathGenerator) { m_slowPathGenerators.append(slowPathGenerator.leakPtr()); @@ -2902,7 +3059,7 @@ void SpeculativeJIT::compileGetIndexedPropertyStorage(Node& node) ASSERT_NOT_REACHED(); } else if (at(node.child1()).prediction() == SpecString) { if (!isStringSpeculation(m_state.forNode(node.child1()).m_type)) - speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::classInfoOffset()), MacroAssembler::TrustedImmPtr(&JSString::s_info))); + speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node.child1(), m_jit.branchPtr(MacroAssembler::NotEqual, MacroAssembler::Address(baseReg, JSCell::structureOffset()), MacroAssembler::TrustedImmPtr(m_jit.globalData()->stringStructure.get()))); m_jit.loadPtr(MacroAssembler::Address(baseReg, JSString::offsetOfValue()), storageReg); |