summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp127
1 files changed, 71 insertions, 56 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
index 5de36a0da..01e0cdecd 100644
--- a/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@
#include "DFGInsertionSet.h"
#include "DFGPhase.h"
#include "DFGValidate.h"
-#include "Operations.h"
+#include "JSCInlines.h"
namespace JSC { namespace DFG {
@@ -46,6 +46,9 @@ public:
bool run()
{
+ // FIXME: We should make this work in SSA. https://bugs.webkit.org/show_bug.cgi?id=148260
+ DFG_ASSERT(m_graph, nullptr, m_graph.m_form != SSA);
+
const bool extremeLogging = false;
bool outerChanged = false;
@@ -59,7 +62,7 @@ public:
continue;
ASSERT(block->isReachable);
- switch (block->last()->op()) {
+ switch (block->terminal()->op()) {
case Jump: {
// Successor with one predecessor -> merge.
if (block->successor(0)->predecessors.size() == 1) {
@@ -79,6 +82,8 @@ public:
// suboptimal, because if my successor has multiple predecessors then we'll
// be keeping alive things on other predecessor edges unnecessarily.
// What we really need is the notion of end-of-block ghosties!
+ // FIXME: Allow putting phantoms after terminals.
+ // https://bugs.webkit.org/show_bug.cgi?id=126778
break;
}
@@ -97,17 +102,19 @@ public:
if (extremeLogging)
m_graph.dump();
m_graph.dethread();
-
- ASSERT(block->last()->isTerminal());
- CodeOrigin boundaryCodeOrigin = block->last()->codeOrigin;
- block->last()->convertToPhantom();
- ASSERT(block->last()->refCount() == 1);
-
- jettisonBlock(block, jettisonedBlock, boundaryCodeOrigin);
-
- block->appendNode(
- m_graph, SpecNone, Jump, boundaryCodeOrigin,
+
+ Node* terminal = block->terminal();
+ ASSERT(terminal->isTerminal());
+ NodeOrigin boundaryNodeOrigin = terminal->origin;
+
+ jettisonBlock(block, jettisonedBlock, boundaryNodeOrigin);
+
+ block->replaceTerminal(
+ m_graph, SpecNone, Jump, boundaryNodeOrigin,
OpInfo(targetBlock));
+
+ ASSERT(block->terminal());
+
}
innerChanged = outerChanged = true;
break;
@@ -127,44 +134,47 @@ public:
}
case Switch: {
- SwitchData* data = block->last()->switchData();
+ SwitchData* data = block->terminal()->switchData();
// Prune out cases that end up jumping to default.
for (unsigned i = 0; i < data->cases.size(); ++i) {
- if (data->cases[i].target == data->fallThrough)
- data->cases[i--] = data->cases.takeLast();
+ if (data->cases[i].target.block == data->fallThrough.block) {
+ data->fallThrough.count += data->cases[i].target.count;
+ data->cases[i--] = data->cases.last();
+ data->cases.removeLast();
+ }
}
// If there are no cases other than default then this turns
// into a jump.
if (data->cases.isEmpty()) {
- convertToJump(block, data->fallThrough);
+ convertToJump(block, data->fallThrough.block);
innerChanged = outerChanged = true;
break;
}
// Switch on constant -> jettison all other targets and merge.
- if (block->last()->child1()->hasConstant()) {
- JSValue value = m_graph.valueOfJSConstant(block->last()->child1().node());
+ Node* terminal = block->terminal();
+ if (terminal->child1()->hasConstant()) {
+ FrozenValue* value = terminal->child1()->constant();
TriState found = FalseTriState;
BasicBlock* targetBlock = 0;
for (unsigned i = data->cases.size(); found == FalseTriState && i--;) {
found = data->cases[i].value.strictEqual(value);
if (found == TrueTriState)
- targetBlock = data->cases[i].target;
+ targetBlock = data->cases[i].target.block;
}
if (found == MixedTriState)
break;
if (found == FalseTriState)
- targetBlock = data->fallThrough;
+ targetBlock = data->fallThrough.block;
ASSERT(targetBlock);
Vector<BasicBlock*, 1> jettisonedBlocks;
- for (unsigned i = block->numSuccessors(); i--;) {
- BasicBlock* jettisonedBlock = block->successor(i);
- if (jettisonedBlock != targetBlock)
- jettisonedBlocks.append(jettisonedBlock);
+ for (BasicBlock* successor : terminal->successors()) {
+ if (successor != targetBlock)
+ jettisonedBlocks.append(successor);
}
if (targetBlock->predecessors.size() == 1) {
@@ -178,12 +188,13 @@ public:
m_graph.dump();
m_graph.dethread();
- CodeOrigin boundaryCodeOrigin = block->last()->codeOrigin;
- block->last()->convertToPhantom();
+ NodeOrigin boundaryNodeOrigin = terminal->origin;
+
for (unsigned i = jettisonedBlocks.size(); i--;)
- jettisonBlock(block, jettisonedBlocks[i], boundaryCodeOrigin);
- block->appendNode(
- m_graph, SpecNone, Jump, boundaryCodeOrigin, OpInfo(targetBlock));
+ jettisonBlock(block, jettisonedBlocks[i], boundaryNodeOrigin);
+
+ block->replaceTerminal(
+ m_graph, SpecNone, Jump, boundaryNodeOrigin, OpInfo(targetBlock));
}
innerChanged = outerChanged = true;
break;
@@ -233,7 +244,7 @@ public:
}
if (Options::validateGraphAtEachPhase())
- validate(m_graph);
+ validate();
} while (innerChanged);
return outerChanged;
@@ -248,36 +259,40 @@ private:
m_graph.dethread();
mergeBlocks(block, targetBlock, noBlocks());
} else {
- Node* branch = block->last();
- ASSERT(branch->isTerminal());
+ Node* branch = block->terminal();
ASSERT(branch->op() == Branch || branch->op() == Switch);
- branch->convertToPhantom();
- ASSERT(branch->refCount() == 1);
-
- block->appendNode(
- m_graph, SpecNone, Jump, branch->codeOrigin,
- OpInfo(targetBlock));
+
+ block->replaceTerminal(
+ m_graph, SpecNone, Jump, branch->origin, OpInfo(targetBlock));
}
}
-
- void keepOperandAlive(BasicBlock* block, BasicBlock* jettisonedBlock, CodeOrigin codeOrigin, VirtualRegister operand)
+
+ void keepOperandAlive(BasicBlock* block, BasicBlock* jettisonedBlock, NodeOrigin nodeOrigin, VirtualRegister operand)
{
Node* livenessNode = jettisonedBlock->variablesAtHead.operand(operand);
if (!livenessNode)
return;
- if (livenessNode->variableAccessData()->isCaptured())
- return;
+ NodeType nodeType;
+ if (livenessNode->flags() & NodeIsFlushed)
+ nodeType = Flush;
+ else {
+ // This seems like it shouldn't be necessary because we could just rematerialize
+ // PhantomLocals or something similar using bytecode liveness. However, in ThreadedCPS, it's
+ // worth the sanity to maintain this eagerly. See
+ // https://bugs.webkit.org/show_bug.cgi?id=144086
+ nodeType = PhantomLocal;
+ }
block->appendNode(
- m_graph, SpecNone, PhantomLocal, codeOrigin,
+ m_graph, SpecNone, nodeType, nodeOrigin,
OpInfo(livenessNode->variableAccessData()));
}
- void jettisonBlock(BasicBlock* block, BasicBlock* jettisonedBlock, CodeOrigin boundaryCodeOrigin)
+ void jettisonBlock(BasicBlock* block, BasicBlock* jettisonedBlock, NodeOrigin boundaryNodeOrigin)
{
for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfArguments(); ++i)
- keepOperandAlive(block, jettisonedBlock, boundaryCodeOrigin, virtualRegisterForArgument(i));
+ keepOperandAlive(block, jettisonedBlock, boundaryNodeOrigin, virtualRegisterForArgument(i));
for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfLocals(); ++i)
- keepOperandAlive(block, jettisonedBlock, boundaryCodeOrigin, virtualRegisterForLocal(i));
+ keepOperandAlive(block, jettisonedBlock, boundaryNodeOrigin, virtualRegisterForLocal(i));
fixJettisonedPredecessors(block, jettisonedBlock);
}
@@ -310,11 +325,12 @@ private:
// kept alive.
// Remove the terminal of firstBlock since we don't need it anymore. Well, we don't
- // really remove it; we actually turn it into a Phantom.
- ASSERT(firstBlock->last()->isTerminal());
- CodeOrigin boundaryCodeOrigin = firstBlock->last()->codeOrigin;
- firstBlock->last()->convertToPhantom();
- ASSERT(firstBlock->last()->refCount() == 1);
+ // really remove it; we actually turn it into a check.
+ Node* terminal = firstBlock->terminal();
+ ASSERT(terminal->isTerminal());
+ NodeOrigin boundaryNodeOrigin = terminal->origin;
+ terminal->remove();
+ ASSERT(terminal->refCount() == 1);
for (unsigned i = jettisonedBlocks.size(); i--;) {
BasicBlock* jettisonedBlock = jettisonedBlocks[i];
@@ -324,9 +340,9 @@ private:
// different path than secondBlock.
for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfArguments(); ++i)
- keepOperandAlive(firstBlock, jettisonedBlock, boundaryCodeOrigin, virtualRegisterForArgument(i));
+ keepOperandAlive(firstBlock, jettisonedBlock, boundaryNodeOrigin, virtualRegisterForArgument(i));
for (size_t i = 0; i < jettisonedBlock->variablesAtHead.numberOfLocals(); ++i)
- keepOperandAlive(firstBlock, jettisonedBlock, boundaryCodeOrigin, virtualRegisterForLocal(i));
+ keepOperandAlive(firstBlock, jettisonedBlock, boundaryNodeOrigin, virtualRegisterForLocal(i));
}
for (size_t i = 0; i < secondBlock->phis.size(); ++i)
@@ -335,7 +351,7 @@ private:
for (size_t i = 0; i < secondBlock->size(); ++i)
firstBlock->append(secondBlock->at(i));
- ASSERT(firstBlock->last()->isTerminal());
+ ASSERT(firstBlock->terminal()->isTerminal());
// Fix the predecessors of my new successors. This is tricky, since we are going to reset
// all predecessors anyway due to reachability analysis. But we need to fix the
@@ -364,7 +380,6 @@ private:
bool performCFGSimplification(Graph& graph)
{
- SamplingRegion samplingRegion("DFG CFG Simplification Phase");
return runPhase<CFGSimplificationPhase>(graph);
}