summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp151
1 files changed, 59 insertions, 92 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp b/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
index 09dbf328b..5f646f3a0 100644
--- a/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
+++ b/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 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 "JSCInlines.h"
+#include "Operations.h"
namespace JSC { namespace DFG {
@@ -44,8 +44,6 @@ public:
bool run()
{
- RELEASE_ASSERT(m_graph.m_refCountState == EverythingIsLive);
-
if (m_graph.m_form == ThreadedCPS)
return false;
@@ -53,10 +51,8 @@ public:
freeUnnecessaryNodes();
m_graph.clearReplacements();
canonicalizeLocalsInBlocks();
- specialCaseArguments();
propagatePhis<LocalOperand>();
propagatePhis<ArgumentOperand>();
- computeIsFlushed();
m_graph.m_form = ThreadedCPS;
return true;
@@ -91,15 +87,13 @@ private:
node->children.setChild1(Edge());
break;
case Phantom:
- if (!node->child1()) {
- m_graph.m_allocator.free(node);
+ if (!node->child1())
continue;
- }
switch (node->child1()->op()) {
case Phi:
case SetArgument:
case SetLocal:
- node->convertPhantomToPhantomLocal();
+ node->convertToPhantomLocal();
break;
default:
ASSERT(node->child1()->hasResult());
@@ -120,37 +114,37 @@ private:
}
template<OperandKind operandKind>
- void clearVariables()
+ void clearVariablesAtHeadAndTail()
{
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) = nullptr;
- m_block->variablesAtTail.atFor<operandKind>(i) = nullptr;
+ m_block->variablesAtHead.atFor<operandKind>(i) = 0;
+ m_block->variablesAtTail.atFor<operandKind>(i) = 0;
}
}
- ALWAYS_INLINE Node* addPhiSilently(BasicBlock* block, const NodeOrigin& origin, VariableAccessData* variable)
+ ALWAYS_INLINE Node* addPhiSilently(BasicBlock* block, const CodeOrigin& codeOrigin, VariableAccessData* variable)
{
- Node* result = m_graph.addNode(SpecNone, Phi, origin, OpInfo(variable));
+ Node* result = m_graph.addNode(SpecNone, Phi, codeOrigin, OpInfo(variable));
block->phis.append(result);
return result;
}
template<OperandKind operandKind>
- ALWAYS_INLINE Node* addPhi(BasicBlock* block, const NodeOrigin& origin, VariableAccessData* variable, size_t index)
+ ALWAYS_INLINE Node* addPhi(BasicBlock* block, const CodeOrigin& codeOrigin, VariableAccessData* variable, size_t index)
{
- Node* result = addPhiSilently(block, origin, variable);
+ Node* result = addPhiSilently(block, codeOrigin, variable);
phiStackFor<operandKind>().append(PhiStackEntry(block, index, result));
return result;
}
template<OperandKind operandKind>
- ALWAYS_INLINE Node* addPhi(const NodeOrigin& origin, VariableAccessData* variable, size_t index)
+ ALWAYS_INLINE Node* addPhi(const CodeOrigin& codeOrigin, VariableAccessData* variable, size_t index)
{
- return addPhi<operandKind>(m_block, origin, variable, index);
+ return addPhi<operandKind>(m_block, codeOrigin, variable, index);
}
template<OperandKind operandKind>
@@ -187,19 +181,34 @@ 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->replaceWith(otherNode);
+ node->misc.replacement = otherNode;
return;
}
ASSERT(otherNode->op() == SetLocal);
- node->replaceWith(otherNode->child1().node());
+ node->misc.replacement = otherNode->child1().node();
return;
}
variable->setIsLoadedFrom(true);
- Node* phi = addPhi<operandKind>(node->origin, variable, idx);
+ Node* phi = addPhi<operandKind>(node->codeOrigin, variable, idx);
node->children.setChild1(Edge(phi));
m_block->variablesAtHead.atFor<operandKind>(idx) = phi;
m_block->variablesAtTail.atFor<operandKind>(idx) = node;
@@ -214,6 +223,11 @@ 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)
{
@@ -240,9 +254,13 @@ 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
- // keep the last MovHinted value of that local alive.
+ // be keeping the operand to the SetLocal alive. The SetLocal may die, and
+ // we'll be fine because OSR tracks dead SetLocals.
+
+ // So we turn this into a Phantom on the child of the SetLocal.
- node->remove();
+ node->convertToPhantom();
+ node->children.setChild1(otherNode->child1());
return;
}
@@ -258,7 +276,7 @@ private:
}
variable->setIsLoadedFrom(true);
- node->children.setChild1(Edge(addPhi<operandKind>(node->origin, variable, idx)));
+ node->children.setChild1(Edge(addPhi<operandKind>(node->codeOrigin, variable, idx)));
m_block->variablesAtHead.atFor<operandKind>(idx) = node;
m_block->variablesAtTail.atFor<operandKind>(idx) = node;
}
@@ -273,9 +291,13 @@ private:
canonicalizeFlushOrPhantomLocalFor<nodeType, LocalOperand>(node, variable, variable->local().toLocal());
}
- void canonicalizeSet(Node* node)
+ void canonicalizeSetArgument(Node* node)
{
- m_block->variablesAtTail.setOperand(node->local(), node);
+ VirtualRegister local = node->local();
+ ASSERT(local.isArgument());
+ int argument = local.toArgument();
+ m_block->variablesAtHead.setArgumentFirstTime(argument, node);
+ m_block->variablesAtTail.setArgumentFirstTime(argument, node);
}
void canonicalizeLocalsInBlock()
@@ -284,8 +306,8 @@ private:
return;
ASSERT(m_block->isReachable);
- clearVariables<ArgumentOperand>();
- clearVariables<LocalOperand>();
+ clearVariablesAtHeadAndTail<ArgumentOperand>();
+ clearVariablesAtHeadAndTail<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
@@ -314,8 +336,10 @@ 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. It may be
- // a Phi from the current block. For arguments, it may be a SetArgument.
+ // 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 SetLocal: must be a value producing node.
//
@@ -338,7 +362,7 @@ private:
break;
case SetLocal:
- canonicalizeSet(node);
+ canonicalizeSetLocal(node);
break;
case Flush:
@@ -350,7 +374,7 @@ private:
break;
case SetArgument:
- canonicalizeSet(node);
+ canonicalizeSetArgument(node);
break;
default:
@@ -369,16 +393,6 @@ private:
}
}
- 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()
{
@@ -404,7 +418,7 @@ private:
Node* variableInPrevious = predecessorBlock->variablesAtTail.atFor<operandKind>(index);
if (!variableInPrevious) {
- variableInPrevious = addPhi<operandKind>(predecessorBlock, currentPhi->origin, variable, index);
+ variableInPrevious = addPhi<operandKind>(predecessorBlock, currentPhi->codeOrigin, variable, index);
predecessorBlock->variablesAtTail.atFor<operandKind>(index) = variableInPrevious;
predecessorBlock->variablesAtHead.atFor<operandKind>(index) = variableInPrevious;
} else {
@@ -438,7 +452,7 @@ private:
continue;
}
- Node* newPhi = addPhiSilently(block, currentPhi->origin, variable);
+ Node* newPhi = addPhiSilently(block, currentPhi->codeOrigin, variable);
newPhi->children = currentPhi->children;
currentPhi->children.initialize(newPhi, variableInPrevious, 0);
}
@@ -466,56 +480,9 @@ 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)