Diff
Modified: branches/safari-602-branch/Source/_javascript_Core/ChangeLog (205226 => 205227)
--- branches/safari-602-branch/Source/_javascript_Core/ChangeLog 2016-08-31 07:19:50 UTC (rev 205226)
+++ branches/safari-602-branch/Source/_javascript_Core/ChangeLog 2016-08-31 07:19:55 UTC (rev 205227)
@@ -1,5 +1,48 @@
2016-08-30 Babak Shafiei <[email protected]>
+ Merge r203802. rdar://problem/27991569
+
+ 2016-07-27 Benjamin Poulain <[email protected]>
+
+ [JSC] Fix a bunch of use-after-free of DFG::Node
+ https://bugs.webkit.org/show_bug.cgi?id=160228
+
+ Reviewed by Mark Lam.
+
+ FTL had a few places where we use a node after it has been
+ deleted. The dangling pointers come from the SSA liveness information
+ kept on the basic blocks.
+
+ This patch fixes the issues I could find and adds liveness invalidation
+ to help finding dependencies like these.
+
+ * dfg/DFGBasicBlock.h:
+ (JSC::DFG::BasicBlock::SSAData::invalidate):
+
+ * dfg/DFGConstantFoldingPhase.cpp:
+ (JSC::DFG::ConstantFoldingPhase::run):
+ Constant folding phase was deleting nodes in the loop over basic blocks.
+ The problem is the deleted nodes can be referenced by other blocks.
+ When the abstract interpreter was manipulating the abstract values of those
+ it was doing so on the dead nodes.
+
+ * dfg/DFGConstantHoistingPhase.cpp:
+ Just invalidation. Nothing wrong here since the useless nodes were
+ kept live while iterating the blocks.
+
+ * dfg/DFGGraph.cpp:
+ (JSC::DFG::Graph::killBlockAndItsContents):
+ (JSC::DFG::Graph::killUnreachableBlocks):
+ (JSC::DFG::Graph::invalidateNodeLiveness):
+
+ * dfg/DFGGraph.h:
+ * dfg/DFGPlan.cpp:
+ (JSC::DFG::Plan::compileInThreadImpl):
+ We had a lot of use-after-free in LCIM because we were using the stale
+ live nodes deleted by previous phases.
+
+2016-08-30 Babak Shafiei <[email protected]>
+
Merge r203798. rdar://problem/27991578
2016-07-27 Keith Miller <[email protected]>
Modified: branches/safari-602-branch/Source/_javascript_Core/dfg/DFGBasicBlock.h (205226 => 205227)
--- branches/safari-602-branch/Source/_javascript_Core/dfg/DFGBasicBlock.h 2016-08-31 07:19:50 UTC (rev 205226)
+++ branches/safari-602-branch/Source/_javascript_Core/dfg/DFGBasicBlock.h 2016-08-31 07:19:55 UTC (rev 205227)
@@ -239,6 +239,14 @@
struct SSAData {
WTF_MAKE_FAST_ALLOCATED;
public:
+ void invalidate()
+ {
+ liveAtTail.clear();
+ liveAtHead.clear();
+ valuesAtHead.clear();
+ valuesAtTail.clear();
+ }
+
AvailabilityMap availabilityAtHead;
AvailabilityMap availabilityAtTail;
Modified: branches/safari-602-branch/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp (205226 => 205227)
--- branches/safari-602-branch/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2016-08-31 07:19:50 UTC (rev 205226)
+++ branches/safari-602-branch/Source/_javascript_Core/dfg/DFGConstantFoldingPhase.cpp 2016-08-31 07:19:55 UTC (rev 205227)
@@ -71,6 +71,7 @@
// It's now possible to simplify basic blocks by placing an Unreachable terminator right
// after anything that invalidates AI.
bool didClipBlock = false;
+ Vector<Node*> nodesToDelete;
for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
m_state.beginBasicBlock(block);
for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
@@ -83,7 +84,7 @@
if (!m_state.isValid()) {
NodeOrigin origin = block->at(nodeIndex)->origin;
for (unsigned killIndex = nodeIndex; killIndex < block->size(); ++killIndex)
- m_graph.m_allocator.free(block->at(killIndex));
+ nodesToDelete.append(block->at(killIndex));
block->resize(nodeIndex);
block->appendNode(m_graph, SpecNone, Unreachable, origin);
didClipBlock = true;
@@ -96,6 +97,12 @@
if (didClipBlock) {
changed = true;
+
+ m_graph.invalidateNodeLiveness();
+
+ for (Node* node : nodesToDelete)
+ m_graph.m_allocator.free(node);
+
m_graph.invalidateCFG();
m_graph.resetReachability();
m_graph.killUnreachableBlocks();
Modified: branches/safari-602-branch/Source/_javascript_Core/dfg/DFGConstantHoistingPhase.cpp (205226 => 205227)
--- branches/safari-602-branch/Source/_javascript_Core/dfg/DFGConstantHoistingPhase.cpp 2016-08-31 07:19:50 UTC (rev 205226)
+++ branches/safari-602-branch/Source/_javascript_Core/dfg/DFGConstantHoistingPhase.cpp 2016-08-31 07:19:55 UTC (rev 205227)
@@ -128,6 +128,7 @@
}
// And finally free the constants that we removed.
+ m_graph.invalidateNodeLiveness();
for (Node* node : toFree)
m_graph.m_allocator.free(node);
Modified: branches/safari-602-branch/Source/_javascript_Core/dfg/DFGGraph.cpp (205226 => 205227)
--- branches/safari-602-branch/Source/_javascript_Core/dfg/DFGGraph.cpp 2016-08-31 07:19:50 UTC (rev 205226)
+++ branches/safari-602-branch/Source/_javascript_Core/dfg/DFGGraph.cpp 2016-08-31 07:19:55 UTC (rev 205227)
@@ -744,6 +744,8 @@
void Graph::killBlockAndItsContents(BasicBlock* block)
{
+ if (auto& ssaData = block->ssa)
+ ssaData->invalidate();
for (unsigned phiIndex = block->phis.size(); phiIndex--;)
m_allocator.free(block->phis[phiIndex]);
for (unsigned nodeIndex = block->size(); nodeIndex--;)
@@ -754,9 +756,8 @@
void Graph::killUnreachableBlocks()
{
- // FIXME: This probably creates dangling references from Upsilons to Phis in SSA.
- // https://bugs.webkit.org/show_bug.cgi?id=159164
-
+ invalidateNodeLiveness();
+
for (BlockIndex blockIndex = 0; blockIndex < numBlocks(); ++blockIndex) {
BasicBlock* block = this->block(blockIndex);
if (!block)
@@ -778,6 +779,15 @@
m_backwardsCFG = nullptr;
}
+void Graph::invalidateNodeLiveness()
+{
+ if (m_form != SSA)
+ return;
+
+ for (BasicBlock* block : blocksInNaturalOrder())
+ block->ssa->invalidate();
+}
+
void Graph::substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal)
{
for (unsigned indexInBlock = startIndexInBlock; indexInBlock < block.size(); ++indexInBlock) {
Modified: branches/safari-602-branch/Source/_javascript_Core/dfg/DFGGraph.h (205226 => 205227)
--- branches/safari-602-branch/Source/_javascript_Core/dfg/DFGGraph.h 2016-08-31 07:19:50 UTC (rev 205226)
+++ branches/safari-602-branch/Source/_javascript_Core/dfg/DFGGraph.h 2016-08-31 07:19:55 UTC (rev 205227)
@@ -533,6 +533,7 @@
void substituteGetLocal(BasicBlock& block, unsigned startIndexInBlock, VariableAccessData* variableAccessData, Node* newGetLocal);
void invalidateCFG();
+ void invalidateNodeLiveness();
void clearFlagsOnAllNodes(NodeFlags);
Modified: branches/safari-602-branch/Source/_javascript_Core/dfg/DFGPlan.cpp (205226 => 205227)
--- branches/safari-602-branch/Source/_javascript_Core/dfg/DFGPlan.cpp 2016-08-31 07:19:50 UTC (rev 205226)
+++ branches/safari-602-branch/Source/_javascript_Core/dfg/DFGPlan.cpp 2016-08-31 07:19:55 UTC (rev 205227)
@@ -426,6 +426,8 @@
// wrong with running LICM earlier, if we wanted to put other CFG transforms above this point.
// Alternatively, we could run loop pre-header creation after SSA conversion - but if we did that
// then we'd need to do some simple SSA fix-up.
+ performLivenessAnalysis(dfg);
+ performCFA(dfg);
performLICM(dfg);
// FIXME: Currently: IntegerRangeOptimization *must* be run after LICM.