summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.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/DFGCPSRethreadingPhase.cpp
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp164
1 files changed, 94 insertions, 70 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp b/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
index 5f646f3a0..fbc9c2dd8 100644
--- a/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-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
@@ -31,7 +31,7 @@
#include "DFGBasicBlockInlines.h"
#include "DFGGraph.h"
#include "DFGPhase.h"
-#include "Operations.h"
+#include "JSCInlines.h"
namespace JSC { namespace DFG {
@@ -44,6 +44,8 @@ public:
bool run()
{
+ RELEASE_ASSERT(m_graph.m_refCountState == EverythingIsLive);
+
if (m_graph.m_form == ThreadedCPS)
return false;
@@ -51,8 +53,10 @@ public:
freeUnnecessaryNodes();
m_graph.clearReplacements();
canonicalizeLocalsInBlocks();
+ specialCaseArguments();
propagatePhis<LocalOperand>();
propagatePhis<ArgumentOperand>();
+ computeIsFlushed();
m_graph.m_form = ThreadedCPS;
return true;
@@ -68,8 +72,6 @@ private:
void freeUnnecessaryNodes()
{
- SamplingRegion samplingRegion("DFG CPS Rethreading: freeUnnecessaryNodes");
-
for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
BasicBlock* block = m_graph.block(blockIndex);
if (!block)
@@ -87,13 +89,15 @@ private:
node->children.setChild1(Edge());
break;
case Phantom:
- if (!node->child1())
+ if (!node->child1()) {
+ m_graph.deleteNode(node);
continue;
+ }
switch (node->child1()->op()) {
case Phi:
case SetArgument:
case SetLocal:
- node->convertToPhantomLocal();
+ node->convertPhantomToPhantomLocal();
break;
default:
ASSERT(node->child1()->hasResult());
@@ -108,43 +112,43 @@ private:
block->resize(toIndex);
for (unsigned phiIndex = block->phis.size(); phiIndex--;)
- m_graph.m_allocator.free(block->phis[phiIndex]);
+ m_graph.deleteNode(block->phis[phiIndex]);
block->phis.resize(0);
}
}
template<OperandKind operandKind>
- void clearVariablesAtHeadAndTail()
+ void clearVariables()
{
ASSERT(
m_block->variablesAtHead.sizeFor<operandKind>()
== m_block->variablesAtTail.sizeFor<operandKind>());
for (unsigned i = m_block->variablesAtHead.sizeFor<operandKind>(); i--;) {
- m_block->variablesAtHead.atFor<operandKind>(i) = 0;
- m_block->variablesAtTail.atFor<operandKind>(i) = 0;
+ m_block->variablesAtHead.atFor<operandKind>(i) = nullptr;
+ m_block->variablesAtTail.atFor<operandKind>(i) = nullptr;
}
}
- ALWAYS_INLINE Node* addPhiSilently(BasicBlock* block, const CodeOrigin& codeOrigin, VariableAccessData* variable)
+ ALWAYS_INLINE Node* addPhiSilently(BasicBlock* block, const NodeOrigin& origin, VariableAccessData* variable)
{
- Node* result = m_graph.addNode(SpecNone, Phi, codeOrigin, OpInfo(variable));
+ Node* result = m_graph.addNode(Phi, origin, OpInfo(variable));
block->phis.append(result);
return result;
}
template<OperandKind operandKind>
- ALWAYS_INLINE Node* addPhi(BasicBlock* block, const CodeOrigin& codeOrigin, VariableAccessData* variable, size_t index)
+ ALWAYS_INLINE Node* addPhi(BasicBlock* block, const NodeOrigin& origin, VariableAccessData* variable, size_t index)
{
- Node* result = addPhiSilently(block, codeOrigin, variable);
+ Node* result = addPhiSilently(block, origin, variable);
phiStackFor<operandKind>().append(PhiStackEntry(block, index, result));
return result;
}
template<OperandKind operandKind>
- ALWAYS_INLINE Node* addPhi(const CodeOrigin& codeOrigin, VariableAccessData* variable, size_t index)
+ ALWAYS_INLINE Node* addPhi(const NodeOrigin& origin, VariableAccessData* variable, size_t index)
{
- return addPhi<operandKind>(m_block, codeOrigin, variable, index);
+ return addPhi<operandKind>(m_block, origin, variable, index);
}
template<OperandKind operandKind>
@@ -181,34 +185,19 @@ private:
return;
}
- if (variable->isCaptured()) {
- variable->setIsLoadedFrom(true);
- if (otherNode->op() == GetLocal)
- otherNode = otherNode->child1().node();
- else
- ASSERT(otherNode->op() == SetLocal || otherNode->op() == SetArgument);
-
- ASSERT(otherNode->op() == Phi || otherNode->op() == SetLocal || otherNode->op() == SetArgument);
-
- // Keep this GetLocal but link it to the prior ones.
- node->children.setChild1(Edge(otherNode));
- m_block->variablesAtTail.atFor<operandKind>(idx) = node;
- return;
- }
-
if (otherNode->op() == GetLocal) {
// Replace all references to this GetLocal with otherNode.
- node->misc.replacement = otherNode;
+ node->replaceWith(otherNode);
return;
}
ASSERT(otherNode->op() == SetLocal);
- node->misc.replacement = otherNode->child1().node();
+ node->replaceWith(otherNode->child1().node());
return;
}
variable->setIsLoadedFrom(true);
- Node* phi = addPhi<operandKind>(node->codeOrigin, variable, idx);
+ Node* phi = addPhi<operandKind>(node->origin, variable, idx);
node->children.setChild1(Edge(phi));
m_block->variablesAtHead.atFor<operandKind>(idx) = phi;
m_block->variablesAtTail.atFor<operandKind>(idx) = node;
@@ -223,11 +212,6 @@ private:
canonicalizeGetLocalFor<LocalOperand>(node, variable, variable->local().toLocal());
}
- void canonicalizeSetLocal(Node* node)
- {
- m_block->variablesAtTail.setOperand(node->local(), node);
- }
-
template<NodeType nodeType, OperandKind operandKind>
void canonicalizeFlushOrPhantomLocalFor(Node* node, VariableAccessData* variable, size_t idx)
{
@@ -254,13 +238,9 @@ private:
// for the purpose of OSR. PhantomLocal(SetLocal) means: at this point I
// know that I would have read the value written by that SetLocal. This is
// redundant and inefficient, since really it just means that we want to
- // be keeping the operand to the SetLocal alive. The SetLocal may die, and
- // we'll be fine because OSR tracks dead SetLocals.
+ // keep the last MovHinted value of that local alive.
- // So we turn this into a Phantom on the child of the SetLocal.
-
- node->convertToPhantom();
- node->children.setChild1(otherNode->child1());
+ node->remove();
return;
}
@@ -276,7 +256,7 @@ private:
}
variable->setIsLoadedFrom(true);
- node->children.setChild1(Edge(addPhi<operandKind>(node->codeOrigin, variable, idx)));
+ node->children.setChild1(Edge(addPhi<operandKind>(node->origin, variable, idx)));
m_block->variablesAtHead.atFor<operandKind>(idx) = node;
m_block->variablesAtTail.atFor<operandKind>(idx) = node;
}
@@ -291,13 +271,9 @@ private:
canonicalizeFlushOrPhantomLocalFor<nodeType, LocalOperand>(node, variable, variable->local().toLocal());
}
- void canonicalizeSetArgument(Node* node)
+ void canonicalizeSet(Node* node)
{
- VirtualRegister local = node->local();
- ASSERT(local.isArgument());
- int argument = local.toArgument();
- m_block->variablesAtHead.setArgumentFirstTime(argument, node);
- m_block->variablesAtTail.setArgumentFirstTime(argument, node);
+ m_block->variablesAtTail.setOperand(node->local(), node);
}
void canonicalizeLocalsInBlock()
@@ -306,8 +282,8 @@ private:
return;
ASSERT(m_block->isReachable);
- clearVariablesAtHeadAndTail<ArgumentOperand>();
- clearVariablesAtHeadAndTail<LocalOperand>();
+ clearVariables<ArgumentOperand>();
+ clearVariables<LocalOperand>();
// Assumes that all phi references have been removed. Assumes that things that
// should be live have a non-zero ref count, but doesn't assume that the ref
@@ -315,9 +291,7 @@ private:
// but not logicalRefCount == actualRefCount). Assumes that it can break ref
// counts.
- for (unsigned nodeIndex = 0; nodeIndex < m_block->size(); ++nodeIndex) {
- Node* node = m_block->at(nodeIndex);
-
+ for (auto* node : *m_block) {
m_graph.performSubstitution(node);
// The rules for threaded CPS form:
@@ -336,10 +310,8 @@ private:
// there ever was a SetLocal and it was followed by Flushes, then the tail
// variable will be a SetLocal and not those subsequent Flushes.
//
- // Child of GetLocal: the operation that the GetLocal keeps alive. For
- // uncaptured locals, it may be a Phi from the current block. For arguments,
- // it may be a SetArgument. For captured locals and arguments it may also be
- // a SetLocal.
+ // Child of GetLocal: the operation that the GetLocal keeps alive. It may be
+ // a Phi from the current block. For arguments, it may be a SetArgument.
//
// Child of SetLocal: must be a value producing node.
//
@@ -362,7 +334,7 @@ private:
break;
case SetLocal:
- canonicalizeSetLocal(node);
+ canonicalizeSet(node);
break;
case Flush:
@@ -374,7 +346,7 @@ private:
break;
case SetArgument:
- canonicalizeSetArgument(node);
+ canonicalizeSet(node);
break;
default:
@@ -385,21 +357,27 @@ private:
void canonicalizeLocalsInBlocks()
{
- SamplingRegion samplingRegion("DFG CPS Rethreading: canonicalizeLocalsInBlocks");
-
for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
m_block = m_graph.block(blockIndex);
canonicalizeLocalsInBlock();
}
}
+ void specialCaseArguments()
+ {
+ // Normally, a SetArgument denotes the start of a live range for a local's value on the stack.
+ // But those SetArguments used for the actual arguments to the machine CodeBlock get
+ // special-cased. We could have instead used two different node types - one for the arguments
+ // at the prologue case, and another for the other uses. But this seemed like IR overkill.
+ for (unsigned i = m_graph.m_arguments.size(); i--;)
+ m_graph.block(0)->variablesAtHead.setArgumentFirstTime(i, m_graph.m_arguments[i]);
+ }
+
template<OperandKind operandKind>
void propagatePhis()
{
Vector<PhiStackEntry, 128>& phiStack = operandKind == ArgumentOperand ? m_argumentPhiStack : m_localPhiStack;
- SamplingRegion samplingRegion("DFG CPS Rethreading: propagatePhis");
-
// Ensure that attempts to use this fail instantly.
m_block = 0;
@@ -418,7 +396,7 @@ private:
Node* variableInPrevious = predecessorBlock->variablesAtTail.atFor<operandKind>(index);
if (!variableInPrevious) {
- variableInPrevious = addPhi<operandKind>(predecessorBlock, currentPhi->codeOrigin, variable, index);
+ variableInPrevious = addPhi<operandKind>(predecessorBlock, currentPhi->origin, variable, index);
predecessorBlock->variablesAtTail.atFor<operandKind>(index) = variableInPrevious;
predecessorBlock->variablesAtHead.atFor<operandKind>(index) = variableInPrevious;
} else {
@@ -452,7 +430,7 @@ private:
continue;
}
- Node* newPhi = addPhiSilently(block, currentPhi->codeOrigin, variable);
+ Node* newPhi = addPhiSilently(block, currentPhi->origin, variable);
newPhi->children = currentPhi->children;
currentPhi->children.initialize(newPhi, variableInPrevious, 0);
}
@@ -480,14 +458,60 @@ private:
return m_localPhiStack;
}
+ void computeIsFlushed()
+ {
+ m_graph.clearFlagsOnAllNodes(NodeIsFlushed);
+
+ for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+ BasicBlock* block = m_graph.block(blockIndex);
+ if (!block)
+ continue;
+ for (unsigned nodeIndex = block->size(); nodeIndex--;) {
+ Node* node = block->at(nodeIndex);
+ if (node->op() != Flush)
+ continue;
+ addFlushedLocalOp(node);
+ }
+ }
+ while (!m_flushedLocalOpWorklist.isEmpty()) {
+ Node* node = m_flushedLocalOpWorklist.takeLast();
+ switch (node->op()) {
+ case SetLocal:
+ case SetArgument:
+ break;
+
+ case Flush:
+ case Phi:
+ ASSERT(node->flags() & NodeIsFlushed);
+ DFG_NODE_DO_TO_CHILDREN(m_graph, node, addFlushedLocalEdge);
+ break;
+
+ default:
+ DFG_CRASH(m_graph, node, "Invalid node in flush graph");
+ break;
+ }
+ }
+ }
+
+ void addFlushedLocalOp(Node* node)
+ {
+ if (node->mergeFlags(NodeIsFlushed))
+ m_flushedLocalOpWorklist.append(node);
+ }
+
+ void addFlushedLocalEdge(Node*, Edge edge)
+ {
+ addFlushedLocalOp(edge.node());
+ }
+
BasicBlock* m_block;
Vector<PhiStackEntry, 128> m_argumentPhiStack;
Vector<PhiStackEntry, 128> m_localPhiStack;
+ Vector<Node*, 128> m_flushedLocalOpWorklist;
};
bool performCPSRethreading(Graph& graph)
{
- SamplingRegion samplingRegion("DFG CPS Rethreading Phase");
return runPhase<CPSRethreadingPhase>(graph);
}