Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp (124419 => 124420)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2012-08-02 08:17:13 UTC (rev 124419)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.cpp 2012-08-02 08:22:57 UTC (rev 124420)
@@ -56,6 +56,163 @@
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());
Modified: trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h (124419 => 124420)
--- trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2012-08-02 08:17:13 UTC (rev 124419)
+++ trunk/Source/_javascript_Core/dfg/DFGSpeculativeJIT.h 2012-08-02 08:22:57 UTC (rev 124420)
@@ -2163,163 +2163,33 @@
#endif
// Add a speculation check without additional recovery.
- void 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 speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::Jump jumpToFail)
- {
- ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
- speculationCheck(kind, jsValueSource, nodeUse.index(), jumpToFail);
- }
+ void speculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail);
+ void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail);
// Add a set of speculation checks without additional recovery.
- void 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 speculationCheck(ExitKind kind, JSValueSource jsValueSource, Edge nodeUse, MacroAssembler::JumpList& jumpsToFail)
- {
- ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
- speculationCheck(kind, jsValueSource, nodeUse.index(), jumpsToFail);
- }
+ void speculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::JumpList& jumpsToFail);
+ void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::JumpList& jumpsToFail);
// Add a speculation check with additional recovery.
- void 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 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);
- }
+ void speculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&);
+ void speculationCheck(ExitKind, JSValueSource, Edge, MacroAssembler::Jump jumpToFail, const SpeculationRecovery&);
// Use this like you would use speculationCheck(), except that you don't pass it a jump
// (because you don't have to execute a branch; that's kind of the whole point), and you
// must register the returned Watchpoint with something relevant. In general, this should
// be used with extreme care. Use speculationCheck() unless you've got an amazing reason
// not to.
- JumpReplacementWatchpoint* 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* speculationWatchpoint(ExitKind, JSValueSource, NodeIndex);
// The default for speculation watchpoints is that they're uncounted, because the
// act of firing a watchpoint invalidates it. So, future recompilations will not
// attempt to set this watchpoint again.
- JumpReplacementWatchpoint* speculationWatchpoint(ExitKind kind = UncountableWatchpoint)
- {
- return speculationWatchpoint(kind, JSValueSource(), NoNode);
- }
+ JumpReplacementWatchpoint* speculationWatchpoint(ExitKind = UncountableWatchpoint);
// Note: not specifying the valueRecovery argument (leaving it as ValueRecovery()) implies
// that you've ensured that there exists a MovHint prior to your use of forwardSpeculationCheck().
- void forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& 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 forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, NodeIndex nodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& 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 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 forwardSpeculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::Jump jumpToFail, const ValueRecovery& = ValueRecovery());
+ void forwardSpeculationCheck(ExitKind, JSValueSource, NodeIndex, MacroAssembler::JumpList& jumpsToFail, const ValueRecovery& = ValueRecovery());
+ void speculationCheckWithConditionalDirection(ExitKind, JSValueSource, NodeIndex nodeIndex, MacroAssembler::Jump jumpToFail, bool isForward);
// Called when we statically determine that a speculation will fail.
- void 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 terminateSpeculativeExecution(ExitKind kind, JSValueRegs jsValueRegs, Edge nodeUse)
- {
- ASSERT(at(m_compileIndex).canExit() || m_isCheckingArgumentTypes);
- terminateSpeculativeExecution(kind, jsValueRegs, nodeUse.index());
- }
- void 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 terminateSpeculativeExecution(ExitKind, JSValueRegs, NodeIndex);
+ void terminateSpeculativeExecution(ExitKind, JSValueRegs, Edge);
+ void terminateSpeculativeExecutionWithConditionalDirection(ExitKind, JSValueRegs, NodeIndex, bool isForward);
template<bool strict>
GPRReg fillSpeculateIntInternal(NodeIndex, DataFormat& returnFormat);