diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2015-05-20 09:56:07 +0000 |
commit | 41386e9cb918eed93b3f13648cbef387e371e451 (patch) | |
tree | a97f9d7bd1d9d091833286085f72da9d83fd0606 /Source/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp | |
parent | e15dd966d523731101f70ccf768bba12435a0208 (diff) | |
download | WebKitGtk-tarball-41386e9cb918eed93b3f13648cbef387e371e451.tar.gz |
webkitgtk-2.4.9webkitgtk-2.4.9
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp | 404 |
1 files changed, 0 insertions, 404 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp b/Source/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp deleted file mode 100644 index 5ddda089d..000000000 --- a/Source/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (C) 2014 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 "DFGIntegerCheckCombiningPhase.h" - -#if ENABLE(DFG_JIT) - -#include "DFGGraph.h" -#include "DFGInsertionSet.h" -#include "DFGPhase.h" -#include "DFGPredictionPropagationPhase.h" -#include "DFGVariableAccessDataDump.h" -#include "JSCInlines.h" -#include <unordered_map> -#include <wtf/HashMethod.h> - -namespace JSC { namespace DFG { - -namespace { - -static const bool verbose = false; - -enum RangeKind { - InvalidRangeKind, - - // This means we did ArithAdd with CheckOverflow. - Addition, - - // This means we did CheckInBounds on some length. - ArrayBounds -}; - -struct RangeKey { - RangeKey() - : m_kind(InvalidRangeKind) - , m_key(nullptr) - { - } - - static RangeKey addition(Edge edge) - { - RangeKey result; - result.m_kind = Addition; - result.m_source = edge.sanitized(); - result.m_key = 0; - return result; - } - - static RangeKey arrayBounds(Edge edge, Node* key) - { - RangeKey result; - result.m_kind = ArrayBounds; - result.m_source = edge.sanitized(); - result.m_key = key; - return result; - } - - bool operator!() const { return m_kind == InvalidRangeKind; } - - unsigned hash() const - { - return m_kind + m_source.hash() + PtrHash<Node*>::hash(m_key); - } - - bool operator==(const RangeKey& other) const - { - return m_kind == other.m_kind - && m_source == other.m_source - && m_key == other.m_key; - } - - void dump(PrintStream& out) const - { - switch (m_kind) { - case InvalidRangeKind: - out.print("InvalidRangeKind("); - break; - case Addition: - out.print("Addition("); - break; - case ArrayBounds: - out.print("ArrayBounds("); - break; - } - out.print(m_source, ", ", m_key, ")"); - } - - RangeKind m_kind; - Edge m_source; - Node* m_key; -}; - -struct RangeKeyAndAddend { - RangeKeyAndAddend() - : m_addend(0) - { - } - - RangeKeyAndAddend(RangeKey key, int32_t addend) - : m_key(key) - , m_addend(addend) - { - } - - bool operator!() const { return !m_key && !m_addend; } - - void dump(PrintStream& out) const - { - out.print(m_key, " + ", m_addend); - } - - RangeKey m_key; - int32_t m_addend; -}; - -struct Range { - Range() - : m_minBound(0) - , m_maxBound(0) - , m_count(0) - , m_hoisted(false) - { - } - - void dump(PrintStream& out) const - { - out.print("(", m_minBound, " @", m_minOrigin, ") .. (", m_maxBound, " @", m_maxOrigin, "), count = ", m_count, ", hoisted = ", m_hoisted); - } - - int32_t m_minBound; - CodeOrigin m_minOrigin; - int32_t m_maxBound; - CodeOrigin m_maxOrigin; - unsigned m_count; // If this is zero then the bounds won't necessarily make sense. - bool m_hoisted; -}; - -} // anonymous namespace - -class IntegerCheckCombiningPhase : public Phase { -public: - IntegerCheckCombiningPhase(Graph& graph) - : Phase(graph, "integer check combining") - , m_insertionSet(graph) - { - } - - bool run() - { - ASSERT(m_graph.m_form == SSA); - - m_changed = false; - - for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) - handleBlock(blockIndex); - - return m_changed; - } - -private: - void handleBlock(BlockIndex blockIndex) - { - BasicBlock* block = m_graph.block(blockIndex); - if (!block) - return; - - m_map.clear(); - - // First we collect Ranges. If operations within the range have enough redundancy, - // we hoist. And then we remove additions and checks that fall within the max range. - - for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { - Node* node = block->at(nodeIndex); - RangeKeyAndAddend data = rangeKeyAndAddend(node); - if (verbose) - dataLog("For ", node, ": ", data, "\n"); - if (!data) - continue; - - Range& range = m_map[data.m_key]; - if (verbose) - dataLog(" Range: ", range, "\n"); - if (range.m_count) { - if (data.m_addend > range.m_maxBound) { - range.m_maxBound = data.m_addend; - range.m_maxOrigin = node->origin.semantic; - } else if (data.m_addend < range.m_minBound) { - range.m_minBound = data.m_addend; - range.m_minOrigin = node->origin.semantic; - } - } else { - range.m_maxBound = data.m_addend; - range.m_minBound = data.m_addend; - range.m_minOrigin = node->origin.semantic; - range.m_maxOrigin = node->origin.semantic; - } - range.m_count++; - if (verbose) - dataLog(" New range: ", range, "\n"); - } - - for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) { - Node* node = block->at(nodeIndex); - RangeKeyAndAddend data = rangeKeyAndAddend(node); - if (!data) - continue; - Range range = m_map[data.m_key]; - if (!isValid(data.m_key, range)) - continue; - - // Do the hoisting. - if (!range.m_hoisted) { - switch (data.m_key.m_kind) { - case Addition: { - if (range.m_minBound < 0) { - insertAdd( - nodeIndex, NodeOrigin(range.m_minOrigin, node->origin.forExit), - data.m_key.m_source, range.m_minBound); - } - if (range.m_maxBound > 0) { - insertAdd( - nodeIndex, NodeOrigin(range.m_maxOrigin, node->origin.forExit), - data.m_key.m_source, range.m_maxBound); - } - break; - } - - case ArrayBounds: { - Node* minNode; - Node* maxNode; - - if (!data.m_key.m_source) { - minNode = 0; - maxNode = m_insertionSet.insertConstant( - nodeIndex, range.m_maxOrigin, jsNumber(range.m_maxBound)); - } else { - minNode = insertAdd( - nodeIndex, NodeOrigin(range.m_minOrigin, node->origin.forExit), - data.m_key.m_source, range.m_minBound, Arith::Unchecked); - maxNode = insertAdd( - nodeIndex, NodeOrigin(range.m_maxOrigin, node->origin.forExit), - data.m_key.m_source, range.m_maxBound, Arith::Unchecked); - } - - if (minNode) { - m_insertionSet.insertNode( - nodeIndex, SpecNone, CheckInBounds, node->origin, - Edge(minNode, Int32Use), Edge(data.m_key.m_key, Int32Use)); - } - m_insertionSet.insertNode( - nodeIndex, SpecNone, CheckInBounds, node->origin, - Edge(maxNode, Int32Use), Edge(data.m_key.m_key, Int32Use)); - break; - } - - default: - RELEASE_ASSERT_NOT_REACHED(); - } - - m_changed = true; - m_map[data.m_key].m_hoisted = true; - } - - // Do the elimination. - switch (data.m_key.m_kind) { - case Addition: - node->setArithMode(Arith::Unchecked); - m_changed = true; - break; - - case ArrayBounds: - node->remove(); - m_changed = true; - break; - - default: - RELEASE_ASSERT_NOT_REACHED(); - } - } - - m_insertionSet.execute(block); - } - - RangeKeyAndAddend rangeKeyAndAddend(Node* node) - { - switch (node->op()) { - case ArithAdd: { - if (node->arithMode() != Arith::CheckOverflow - && node->arithMode() != Arith::CheckOverflowAndNegativeZero) - break; - if (!node->child2()->isInt32Constant()) - break; - return RangeKeyAndAddend( - RangeKey::addition(node->child1()), - node->child2()->asInt32()); - } - - case CheckInBounds: { - Edge source; - int32_t addend; - Node* key = node->child2().node(); - - Edge index = node->child1(); - - if (index->isInt32Constant()) { - source = Edge(); - addend = index->asInt32(); - } else if ( - index->op() == ArithAdd - && index->isBinaryUseKind(Int32Use) - && index->child2()->isInt32Constant()) { - source = index->child1(); - addend = index->child2()->asInt32(); - } else { - source = index; - addend = 0; - } - - return RangeKeyAndAddend(RangeKey::arrayBounds(source, key), addend); - } - - default: - break; - } - - return RangeKeyAndAddend(); - } - - bool isValid(const RangeKey& key, const Range& range) - { - if (range.m_count < 2) - return false; - - switch (key.m_kind) { - case ArrayBounds: { - // Have to do this carefully because C++ compilers are too smart. But all we're really doing is detecting if - // the difference between the bounds is 2^31 or more. If it was, then we'd have to worry about wrap-around. - // The way we'd like to write this expression is (range.m_maxBound - range.m_minBound) >= 0, but that is a - // signed subtraction and compare, which allows the C++ compiler to do anything it wants in case of - // wrap-around. - uint32_t maxBound = range.m_maxBound; - uint32_t minBound = range.m_minBound; - uint32_t unsignedDifference = maxBound - minBound; - return !(unsignedDifference >> 31); - } - - default: - return true; - } - } - - Node* insertAdd( - unsigned nodeIndex, NodeOrigin origin, Edge source, int32_t addend, - Arith::Mode arithMode = Arith::CheckOverflow) - { - if (!addend) - return source.node(); - return m_insertionSet.insertNode( - nodeIndex, source->prediction(), source->result(), - ArithAdd, origin, OpInfo(arithMode), source, - m_insertionSet.insertConstantForUse( - nodeIndex, origin, jsNumber(addend), source.useKind())); - } - - typedef std::unordered_map<RangeKey, Range, HashMethod<RangeKey>> RangeMap; - RangeMap m_map; - - InsertionSet m_insertionSet; - bool m_changed; -}; - -bool performIntegerCheckCombining(Graph& graph) -{ - SamplingRegion samplingRegion("DFG Integer Check Combining Phase"); - return runPhase<IntegerCheckCombiningPhase>(graph); -} - -} } // namespace JSC::DFG - -#endif // ENABLE(DFG_JIT) - |