diff options
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp')
| -rw-r--r-- | Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp | 151 |
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) |
