Move back primary header includes next to config.h
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGStoreBarrierElisionPhase.cpp
1 /*
2  * Copyright (C) 2013 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "DFGStoreBarrierElisionPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGBasicBlock.h"
32 #include "DFGClobberSet.h"
33 #include "DFGGraph.h"
34 #include "DFGPhase.h"
35 #include "JSCInlines.h"
36 #include <wtf/HashSet.h>
37
38 namespace JSC { namespace DFG {
39
40 class StoreBarrierElisionPhase : public Phase {
41 public:
42     StoreBarrierElisionPhase(Graph& graph)
43         : Phase(graph, "store barrier elision")
44         , m_currentBlock(0)
45         , m_currentIndex(0)
46     {
47         m_gcClobberSet.add(GCState);
48     }
49
50     bool run()
51     {
52         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
53             m_currentBlock = m_graph.block(blockIndex);
54             if (!m_currentBlock)
55                 continue;
56             handleBlock(m_currentBlock);
57         }
58         return true;
59     }
60
61 private:
62     bool couldCauseGC(Node* node)
63     {
64         return writesOverlap(m_graph, node, m_gcClobberSet);
65     }
66
67     bool allocatesFreshObject(Node* node)
68     {
69         switch (node->op()) {
70         case NewObject:
71         case NewArray:
72         case NewArrayWithSize:
73         case NewArrayBuffer:
74         case NewTypedArray:
75         case NewRegexp:
76             return true;
77         default:
78             return false;
79         }
80     }
81
82     void noticeFreshObject(HashSet<Node*>& dontNeedBarriers, Node* node)
83     {
84         ASSERT(allocatesFreshObject(node));
85         dontNeedBarriers.add(node);
86     }
87
88     Node* getBaseOfStore(Node* barrierNode)
89     {
90         ASSERT(barrierNode->isStoreBarrier());
91         return barrierNode->child1().node();
92     }
93
94     bool shouldBeElided(HashSet<Node*>& dontNeedBarriers, Node* node)
95     {
96         ASSERT(node->isStoreBarrier());
97         return dontNeedBarriers.contains(node->child1().node());
98     }
99
100     void elideBarrier(Node* node)
101     {
102         ASSERT(node->isStoreBarrier());
103         node->convertToPhantom();
104     }
105
106     void handleNode(HashSet<Node*>& dontNeedBarriers, Node* node)
107     {
108         if (couldCauseGC(node))
109             dontNeedBarriers.clear();
110
111         if (allocatesFreshObject(node))
112             noticeFreshObject(dontNeedBarriers, node);
113
114         if (!node->isStoreBarrier())
115             return;
116
117         if (shouldBeElided(dontNeedBarriers, node)) {
118             elideBarrier(node);
119             return;
120         }
121
122         Node* base = getBaseOfStore(node);
123         if (!base)
124             return;
125
126         if (dontNeedBarriers.contains(base))
127             return;
128         dontNeedBarriers.add(base);
129     }
130
131     bool handleBlock(BasicBlock* block)
132     {
133         HashSet<Node*> dontNeedBarriers;
134         for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) {
135             m_currentIndex = indexInBlock;
136             Node* node = block->at(indexInBlock);
137             handleNode(dontNeedBarriers, node);
138         }
139         return true;
140     }
141
142     ClobberSet m_gcClobberSet;
143     BasicBlock* m_currentBlock;
144     unsigned m_currentIndex;
145 };
146     
147 bool performStoreBarrierElision(Graph& graph)
148 {
149     SamplingRegion samplingRegion("DFG Store Barrier Elision Phase");
150     return runPhase<StoreBarrierElisionPhase>(graph);
151 }
152
153
154 } } // namespace JSC::DFG
155
156 #endif // ENABLE(DFG_JIT)