summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2016-04-10 09:28:39 +0000
commit32761a6cee1d0dee366b885b7b9c777e67885688 (patch)
treed6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/dfg/DFGVarargsForwardingPhase.cpp
parenta4e969f4965059196ca948db781e52f7cfebf19e (diff)
downloadWebKitGtk-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.cpp335
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)
-