Commit c02ffd60 authored by oliver@apple.com's avatar oliver@apple.com

fourthTier: DFG should abstract out how it does forward exits, and that code should be simplified

https://bugs.webkit.org/show_bug.cgi?id=113894

Reviewed by Mark Hahnenberg.

1) We previously had two different ways of convertingToForward, one path for
   where we had a ValueRecovery for the current node and one where we didn't.
   But the paths were doing exactly the same thing except that if you have a
   ValueRecovery, you also find the last applicable mov hint and do some
   extra things. This patch combines the two paths and bases both of them on
   the previous no-ValueRecovery path, which was simpler to begin with.

2) This moves the logic into DFG::OSRExit, which further simplifies the code
   and makes the logic available to the FTL.

* dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::convertToForward):
(DFG):
* dfg/DFGOSRExit.h:
(DFG):
(OSRExit):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::convertLastOSRExitToForward):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@153114 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 9a1ae938
2013-04-03 Filip Pizlo <fpizlo@apple.com>
fourthTier: DFG should abstract out how it does forward exits, and that code should be simplified
https://bugs.webkit.org/show_bug.cgi?id=113894
Reviewed by Mark Hahnenberg.
1) We previously had two different ways of convertingToForward, one path for
where we had a ValueRecovery for the current node and one where we didn't.
But the paths were doing exactly the same thing except that if you have a
ValueRecovery, you also find the last applicable mov hint and do some
extra things. This patch combines the two paths and bases both of them on
the previous no-ValueRecovery path, which was simpler to begin with.
2) This moves the logic into DFG::OSRExit, which further simplifies the code
and makes the logic available to the FTL.
* dfg/DFGOSRExit.cpp:
(JSC::DFG::OSRExit::convertToForward):
(DFG):
* dfg/DFGOSRExit.h:
(DFG):
(OSRExit):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::convertLastOSRExitToForward):
2013-07-15 Oliver Hunt <oliver@apple.com>
Merge dfgFourthTier r147582
2013-07-15 Oliver Hunt <oliver@apple.com>
Merge dfgFourthTier r147014
......
......@@ -29,6 +29,7 @@
#if ENABLE(DFG_JIT)
#include "DFGAssemblyHelpers.h"
#include "DFGGraph.h"
#include "DFGSpeculativeJIT.h"
#include "JSCellInlines.h"
......@@ -86,6 +87,52 @@ bool OSRExit::considerAddingAsFrequentExitSiteSlow(CodeBlock* profiledCodeBlock)
return baselineCodeBlockForOriginAndBaselineCodeBlock(m_codeOriginForExitProfile, profiledCodeBlock)->addFrequentExitSite(exitSite);
}
void OSRExit::convertToForward(BasicBlock* block, Node* currentNode, unsigned nodeIndex, const ValueRecovery& valueRecovery)
{
// Check that either the current node is a SetLocal, or the preceding node was a
// SetLocal with the same code origin, or that we've provided a valueRecovery.
if (!ASSERT_DISABLED
&& !valueRecovery
&& !currentNode->containsMovHint()) {
Node* setLocal = block->at(nodeIndex - 1);
ASSERT_UNUSED(setLocal, setLocal->containsMovHint());
ASSERT_UNUSED(setLocal, setLocal->codeOrigin == currentNode->codeOrigin);
}
// Find the first node for the next bytecode instruction. Also track the last mov hint
// on this node.
unsigned indexInBlock = nodeIndex + 1;
Node* node = 0;
Node* lastMovHint = 0;
for (;;) {
if (indexInBlock == block->size()) {
// This is an inline return. Give up and do a backwards speculation. This is safe
// because an inline return has its own bytecode index and it's always safe to
// reexecute that bytecode.
ASSERT(node->op() == Jump);
return;
}
node = block->at(indexInBlock);
if (node->containsMovHint() && node->child1() == currentNode)
lastMovHint = node;
if (node->codeOrigin != currentNode->codeOrigin)
break;
indexInBlock++;
}
ASSERT(node->codeOrigin != currentNode->codeOrigin);
m_codeOrigin = node->codeOrigin;
if (!valueRecovery)
return;
ASSERT(lastMovHint);
ASSERT(lastMovHint->child1() == currentNode);
m_lastSetOperand = lastMovHint->local();
m_valueRecoveryOverride = adoptRef(
new ValueRecoveryOverride(lastMovHint->local(), valueRecovery));
}
} } // namespace JSC::DFG
#endif // ENABLE(DFG_JIT)
......@@ -45,6 +45,8 @@
namespace JSC { namespace DFG {
class SpeculativeJIT;
struct BasicBlock;
struct Node;
// This enum describes the types of additional recovery that
// may need be performed should a speculation check fail.
......@@ -111,6 +113,8 @@ struct OSRExit {
MacroAssembler::Jump getPatchableCodeOffsetAsJump() const;
CodeLocationJump codeLocationForRepatch(CodeBlock*) const;
void correctJump(LinkBuffer&);
void convertToForward(BasicBlock*, Node*, unsigned nodeIndex, const ValueRecovery&);
unsigned m_streamIndex;
int m_lastSetOperand;
......
......@@ -223,70 +223,8 @@ JumpReplacementWatchpoint* SpeculativeJIT::speculationWatchpoint(ExitKind kind)
void SpeculativeJIT::convertLastOSRExitToForward(const ValueRecovery& valueRecovery)
{
if (!valueRecovery) {
// Check that either the current node is a SetLocal, or the preceding node was a
// SetLocal with the same code origin.
if (!m_currentNode->containsMovHint()) {
Node* setLocal = m_jit.graph().m_blocks[m_block]->at(m_indexInBlock - 1);
ASSERT_UNUSED(setLocal, setLocal->containsMovHint());
ASSERT_UNUSED(setLocal, setLocal->codeOrigin == m_currentNode->codeOrigin);
}
// Find the next node.
unsigned indexInBlock = m_indexInBlock + 1;
Node* node = 0;
for (;;) {
if (indexInBlock == m_jit.graph().m_blocks[m_block]->size()) {
// This is an inline return. Give up and do a backwards speculation. This is safe
// because an inline return has its own bytecode index and it's always safe to
// reexecute that bytecode.
ASSERT(node->op() == Jump);
return;
}
node = m_jit.graph().m_blocks[m_block]->at(indexInBlock);
if (node->codeOrigin != m_currentNode->codeOrigin)
break;
indexInBlock++;
}
ASSERT(node->codeOrigin != m_currentNode->codeOrigin);
OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
exit.m_codeOrigin = node->codeOrigin;
return;
}
unsigned setLocalIndexInBlock = m_indexInBlock + 1;
Node* setLocal = m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock);
bool hadInt32ToDouble = false;
if (setLocal->op() == ForwardInt32ToDouble) {
setLocal = m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock);
hadInt32ToDouble = true;
}
if (setLocal->op() == Flush || setLocal->op() == Phantom)
setLocal = m_jit.graph().m_blocks[m_block]->at(++setLocalIndexInBlock);
if (hadInt32ToDouble)
ASSERT(setLocal->child1()->child1() == m_currentNode);
else
ASSERT(setLocal->child1() == m_currentNode);
ASSERT(setLocal->containsMovHint());
ASSERT(setLocal->codeOrigin == m_currentNode->codeOrigin);
Node* nextNode = m_jit.graph().m_blocks[m_block]->at(setLocalIndexInBlock + 1);
if (nextNode->op() == Jump && nextNode->codeOrigin == m_currentNode->codeOrigin) {
// We're at an inlined return. Use a backward speculation instead.
return;
}
ASSERT(nextNode->codeOrigin != m_currentNode->codeOrigin);
OSRExit& exit = m_jit.codeBlock()->lastOSRExit();
exit.m_codeOrigin = nextNode->codeOrigin;
exit.m_lastSetOperand = setLocal->local();
exit.m_valueRecoveryOverride = adoptRef(
new ValueRecoveryOverride(setLocal->local(), valueRecovery));
m_jit.codeBlock()->lastOSRExit().convertToForward(
m_jit.graph().m_blocks[m_block].get(), m_currentNode, m_indexInBlock, valueRecovery);
}
void SpeculativeJIT::forwardSpeculationCheck(ExitKind kind, JSValueSource jsValueSource, Node* node, MacroAssembler::Jump jumpToFail, const ValueRecovery& valueRecovery)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment