+2018-01-03 Robin Morisset <rmorisset@apple.com>
+
+ Inlining of a function that ends in op_unreachable crashes
+ https://bugs.webkit.org/show_bug.cgi?id=181027
+
+ Reviewed by Filip Pizlo.
+
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::allocateTargetableBlock):
+ (JSC::DFG::ByteCodeParser::inlineCall):
+
2018-01-02 Saam Barati <sbarati@apple.com>
Incorrect assertion inside AccessCase
// It is also used when doing an early return from an inlined callee: it is easier to fix the bytecode index later on if needed
// than to move the right index all the way to the treatment of op_ret.
BasicBlock* allocateTargetableBlock(unsigned bytecodeIndex);
+ BasicBlock* allocateTargetableBlock(InlineStackEntry*, unsigned bytecodeIndex);
BasicBlock* allocateUntargetableBlock();
// An untargetable block can be given a bytecodeIndex to be later managed by linkBlock, but only once, and it can never go in the other direction
void makeBlockTargetable(BasicBlock*, unsigned bytecodeIndex);
BasicBlock* ByteCodeParser::allocateTargetableBlock(unsigned bytecodeIndex)
{
+ return allocateTargetableBlock(m_inlineStackTop, bytecodeIndex);
+}
+
+BasicBlock* ByteCodeParser::allocateTargetableBlock(InlineStackEntry* stackEntry, unsigned bytecodeIndex)
+{
ASSERT(bytecodeIndex != UINT_MAX);
Ref<BasicBlock> block = adoptRef(*new BasicBlock(bytecodeIndex, m_numArguments, m_numLocals, 1));
BasicBlock* blockPtr = block.ptr();
// m_blockLinkingTargets must always be sorted in increasing order of bytecodeBegin
- if (m_inlineStackTop->m_blockLinkingTargets.size())
- ASSERT(m_inlineStackTop->m_blockLinkingTargets.last()->bytecodeBegin < bytecodeIndex);
- m_inlineStackTop->m_blockLinkingTargets.append(blockPtr);
+ if (stackEntry->m_blockLinkingTargets.size())
+ ASSERT(stackEntry->m_blockLinkingTargets.last()->bytecodeBegin < bytecodeIndex);
+ stackEntry->m_blockLinkingTargets.append(blockPtr);
m_graph.appendBlock(WTFMove(block));
return blockPtr;
}
linkBlocks(inlineStackEntry.m_unlinkedBlocks, inlineStackEntry.m_blockLinkingTargets);
- // There is an invariant that we use here: every function has at least one op_ret somewhere.
- // And when parseBlock encounters an op_ret, it setups a continuation block if there was none.
- // If this invariant was to be changed, we would need to allocate a new block here in the case where there was no continuation block ready.
- RELEASE_ASSERT(inlineStackEntry.m_continuationBlock);
- m_currentBlock = inlineStackEntry.m_continuationBlock;
+ // Most functions have at least one op_ret and thus set up the continuation block.
+ // In some rare cases, a function ends in op_unreachable, forcing us to allocate a new continuationBlock here.
+ // We must be careful to allocate it in the caller and not the top of the inline stack, since the callee is still on the stack at this point.
+ if (inlineStackEntry.m_continuationBlock)
+ m_currentBlock = inlineStackEntry.m_continuationBlock;
+ else
+ m_currentBlock = allocateTargetableBlock(inlineStackEntry.m_caller, m_currentIndex);
ASSERT(!m_currentBlock->terminal());
prepareToParseBlock();