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 "DFGClobberize.h" 33#include "DFGGraph.h" 34#include "DFGPhase.h" 35#include "JSCInlines.h" 36#include <wtf/HashSet.h> 37 38namespace JSC { namespace DFG { 39 40class StoreBarrierElisionPhase : public Phase { 41public: 42 StoreBarrierElisionPhase(Graph& graph) 43 : Phase(graph, "store barrier elision") 44 , m_currentBlock(0) 45 , m_currentIndex(0) 46 { 47 } 48 49 bool run() 50 { 51 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { 52 m_currentBlock = m_graph.block(blockIndex); 53 if (!m_currentBlock) 54 continue; 55 handleBlock(m_currentBlock); 56 } 57 return true; 58 } 59 60private: 61 bool couldCauseGC(Node* node) 62 { 63 return writesOverlap(m_graph, node, GCState); 64 } 65 66 bool allocatesFreshObject(Node* node) 67 { 68 switch (node->op()) { 69 case NewObject: 70 case NewArray: 71 case NewArrayWithSize: 72 case NewArrayBuffer: 73 case NewTypedArray: 74 case NewRegexp: 75 return true; 76 default: 77 return false; 78 } 79 } 80 81 void noticeFreshObject(HashSet<Node*>& dontNeedBarriers, Node* node) 82 { 83 ASSERT(allocatesFreshObject(node)); 84 dontNeedBarriers.add(node); 85 } 86 87 Node* getBaseOfStore(Node* barrierNode) 88 { 89 ASSERT(barrierNode->isStoreBarrier()); 90 return barrierNode->child1().node(); 91 } 92 93 bool shouldBeElided(HashSet<Node*>& dontNeedBarriers, Node* node) 94 { 95 ASSERT(node->isStoreBarrier()); 96 return dontNeedBarriers.contains(node->child1().node()); 97 } 98 99 void elideBarrier(Node* node) 100 { 101 ASSERT(node->isStoreBarrier()); 102 node->convertToPhantom(); 103 } 104 105 void handleNode(HashSet<Node*>& dontNeedBarriers, Node* node) 106 { 107 if (couldCauseGC(node)) 108 dontNeedBarriers.clear(); 109 110 if (allocatesFreshObject(node)) 111 noticeFreshObject(dontNeedBarriers, node); 112 113 if (!node->isStoreBarrier()) 114 return; 115 116 if (shouldBeElided(dontNeedBarriers, node)) { 117 elideBarrier(node); 118 return; 119 } 120 121 Node* base = getBaseOfStore(node); 122 if (!base) 123 return; 124 125 if (dontNeedBarriers.contains(base)) 126 return; 127 dontNeedBarriers.add(base); 128 } 129 130 bool handleBlock(BasicBlock* block) 131 { 132 HashSet<Node*> dontNeedBarriers; 133 for (unsigned indexInBlock = 0; indexInBlock < block->size(); ++indexInBlock) { 134 m_currentIndex = indexInBlock; 135 Node* node = block->at(indexInBlock); 136 handleNode(dontNeedBarriers, node); 137 } 138 return true; 139 } 140 141 BasicBlock* m_currentBlock; 142 unsigned m_currentIndex; 143}; 144 145bool performStoreBarrierElision(Graph& graph) 146{ 147 SamplingRegion samplingRegion("DFG Store Barrier Elision Phase"); 148 return runPhase<StoreBarrierElisionPhase>(graph); 149} 150 151 152} } // namespace JSC::DFG 153 154#endif // ENABLE(DFG_JIT) 155