diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp | 335 |
1 files changed, 0 insertions, 335 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp b/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp deleted file mode 100644 index d04677093..000000000 --- a/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 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 - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "config.h" -#include "DFGVarargsForwardingPhase.h" - -#if ENABLE(DFG_JIT) - -#include "DFGArgumentsUtilities.h" -#include "DFGClobberize.h" -#include "DFGForAllKills.h" -#include "DFGGraph.h" -#include "DFGPhase.h" -#include "JSCInlines.h" -#include <wtf/ListDump.h> - -namespace JSC { namespace DFG { - -namespace { - -bool verbose = false; - -class VarargsForwardingPhase : public Phase { -public: - VarargsForwardingPhase(Graph& graph) - : Phase(graph, "varargs forwarding") - { - } - - bool run() - { - DFG_ASSERT(m_graph, nullptr, m_graph.m_form != SSA); - - if (verbose) { - dataLog("Graph before varargs forwarding:\n"); - m_graph.dump(); - } - - m_changed = false; - for (BasicBlock* block : m_graph.blocksInNaturalOrder()) - handleBlock(block); - return m_changed; - } - -private: - void handleBlock(BasicBlock* block) - { - for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { - Node* node = block->at(nodeIndex); - switch (node->op()) { - case CreateDirectArguments: - case CreateClonedArguments: - handleCandidate(block, nodeIndex); - break; - default: - break; - } - } - } - - void handleCandidate(BasicBlock* block, unsigned candidateNodeIndex) - { - // We expect calls into this function to be rare. So, this is written in a simple O(n) manner. - - Node* candidate = block->at(candidateNodeIndex); - if (verbose) - dataLog("Handling candidate ", candidate, "\n"); - - // Find the index of the last node in this block to use the candidate, and look for escaping - // sites. - unsigned lastUserIndex = candidateNodeIndex; - Vector<VirtualRegister, 2> relevantLocals; // This is a set. We expect it to be a small set. - for (unsigned nodeIndex = candidateNodeIndex + 1; nodeIndex < block->size(); ++nodeIndex) { - Node* node = block->at(nodeIndex); - - switch (node->op()) { - case MovHint: - if (node->child1() != candidate) - break; - lastUserIndex = nodeIndex; - if (!relevantLocals.contains(node->unlinkedLocal())) - relevantLocals.append(node->unlinkedLocal()); - break; - - case Check: { - bool sawEscape = false; - m_graph.doToChildren( - node, - [&] (Edge edge) { - if (edge == candidate) - lastUserIndex = nodeIndex; - - if (edge.willNotHaveCheck()) - return; - - if (alreadyChecked(edge.useKind(), SpecObject)) - return; - - sawEscape = true; - }); - if (sawEscape) { - if (verbose) - dataLog(" Escape at ", node, "\n"); - return; - } - break; - } - - case LoadVarargs: - if (m_graph.uses(node, candidate)) - lastUserIndex = nodeIndex; - break; - - case CallVarargs: - case ConstructVarargs: - case TailCallVarargs: - case TailCallVarargsInlinedCaller: - if (node->child1() == candidate || node->child3() == candidate) { - if (verbose) - dataLog(" Escape at ", node, "\n"); - return; - } - if (node->child2() == candidate) - lastUserIndex = nodeIndex; - break; - - case SetLocal: - if (node->child1() == candidate && node->variableAccessData()->isLoadedFrom()) { - if (verbose) - dataLog(" Escape at ", node, "\n"); - return; - } - break; - - default: - if (m_graph.uses(node, candidate)) { - if (verbose) - dataLog(" Escape at ", node, "\n"); - return; - } - } - - forAllKilledOperands( - m_graph, node, block->tryAt(nodeIndex + 1), - [&] (VirtualRegister reg) { - if (verbose) - dataLog(" Killing ", reg, " while we are interested in ", listDump(relevantLocals), "\n"); - for (unsigned i = 0; i < relevantLocals.size(); ++i) { - if (relevantLocals[i] == reg) { - relevantLocals[i--] = relevantLocals.last(); - relevantLocals.removeLast(); - lastUserIndex = nodeIndex; - } - } - }); - } - if (verbose) - dataLog("Selected lastUserIndex = ", lastUserIndex, ", ", block->at(lastUserIndex), "\n"); - - // We're still in business. Determine if between the candidate and the last user there is any - // effect that could interfere with sinking. - for (unsigned nodeIndex = candidateNodeIndex + 1; nodeIndex <= lastUserIndex; ++nodeIndex) { - Node* node = block->at(nodeIndex); - - // We have our own custom switch to detect some interferences that clobberize() wouldn't know - // about, and also some of the common ones, too. In particular, clobberize() doesn't know - // that Flush, MovHint, ZombieHint, and KillStack are bad because it's not worried about - // what gets read on OSR exit. - switch (node->op()) { - case MovHint: - case ZombieHint: - case KillStack: - if (argumentsInvolveStackSlot(candidate, node->unlinkedLocal())) { - if (verbose) - dataLog(" Interference at ", node, "\n"); - return; - } - break; - - case PutStack: - if (argumentsInvolveStackSlot(candidate, node->stackAccessData()->local)) { - if (verbose) - dataLog(" Interference at ", node, "\n"); - return; - } - break; - - case SetLocal: - case Flush: - if (argumentsInvolveStackSlot(candidate, node->local())) { - if (verbose) - dataLog(" Interference at ", node, "\n"); - return; - } - break; - - default: { - bool doesInterfere = false; - clobberize( - m_graph, node, NoOpClobberize(), - [&] (AbstractHeap heap) { - if (heap.kind() != Stack) { - ASSERT(!heap.overlaps(Stack)); - return; - } - ASSERT(!heap.payload().isTop()); - VirtualRegister reg(heap.payload().value32()); - if (argumentsInvolveStackSlot(candidate, reg)) - doesInterfere = true; - }, - NoOpClobberize()); - if (doesInterfere) { - if (verbose) - dataLog(" Interference at ", node, "\n"); - return; - } - } } - } - - // We can make this work. - if (verbose) - dataLog(" Will do forwarding!\n"); - m_changed = true; - - // Transform the program. - switch (candidate->op()) { - case CreateDirectArguments: - candidate->setOpAndDefaultFlags(PhantomDirectArguments); - break; - - case CreateClonedArguments: - candidate->setOpAndDefaultFlags(PhantomClonedArguments); - break; - - default: - DFG_CRASH(m_graph, candidate, "bad node type"); - break; - } - for (unsigned nodeIndex = candidateNodeIndex + 1; nodeIndex <= lastUserIndex; ++nodeIndex) { - Node* node = block->at(nodeIndex); - switch (node->op()) { - case Check: - case MovHint: - case PutHint: - // We don't need to change anything with these. - break; - - case LoadVarargs: - if (node->child1() != candidate) - break; - node->setOpAndDefaultFlags(ForwardVarargs); - break; - - case CallVarargs: - if (node->child2() != candidate) - break; - node->setOpAndDefaultFlags(CallForwardVarargs); - break; - - case ConstructVarargs: - if (node->child2() != candidate) - break; - node->setOpAndDefaultFlags(ConstructForwardVarargs); - break; - - case TailCallVarargs: - if (node->child2() != candidate) - break; - node->setOpAndDefaultFlags(TailCallForwardVarargs); - break; - - case TailCallVarargsInlinedCaller: - if (node->child2() != candidate) - break; - node->setOpAndDefaultFlags(TailCallForwardVarargsInlinedCaller); - break; - - case SetLocal: - // This is super odd. We don't have to do anything here, since in DFG IR, the phantom - // arguments nodes do produce a JSValue. Also, we know that if this SetLocal referenecs a - // candidate then the SetLocal - along with all of its references - will die off pretty - // soon, since it has no real users. DCE will surely kill it. If we make it to SSA, then - // SSA conversion will kill it. - break; - - default: - if (ASSERT_DISABLED) - break; - m_graph.doToChildren( - node, - [&] (Edge edge) { - DFG_ASSERT(m_graph, node, edge != candidate); - }); - break; - } - } - } - - bool m_changed; -}; - -} // anonymous namespace - -bool performVarargsForwarding(Graph& graph) -{ - SamplingRegion samplingRegion("DFG Varargs Forwarding Phase"); - return runPhase<VarargsForwardingPhase>(graph); -} - -} } // namespace JSC::DFG - -#endif // ENABLE(DFG_JIT) - |