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. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "DFGWatchpointCollectionPhase.h" 28 29#if ENABLE(DFG_JIT) 30 31#include "ArrayPrototype.h" 32#include "DFGClobberize.h" 33#include "DFGGraph.h" 34#include "DFGPhase.h" 35#include "JSCInlines.h" 36 37namespace JSC { namespace DFG { 38 39class WatchpointCollectionPhase : public Phase { 40 static const bool verbose = false; 41 42public: 43 WatchpointCollectionPhase(Graph& graph) 44 : Phase(graph, "watchpoint collection") 45 { 46 } 47 48 bool run() 49 { 50 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) { 51 BasicBlock* block = m_graph.block(blockIndex); 52 if (!block) 53 continue; 54 55 for (unsigned nodeIndex = block->size(); nodeIndex--;) { 56 m_node = block->at(nodeIndex); 57 handle(); 58 } 59 } 60 61 return true; 62 } 63 64private: 65 void handle() 66 { 67 DFG_NODE_DO_TO_CHILDREN(m_graph, m_node, handleEdge); 68 69 switch (m_node->op()) { 70 case CompareEqConstant: 71 case IsUndefined: 72 handleMasqueradesAsUndefined(); 73 break; 74 75 case CompareEq: 76 if (m_node->isBinaryUseKind(ObjectUse) 77 || (m_node->child1().useKind() == ObjectUse && m_node->child2().useKind() == ObjectOrOtherUse) 78 || (m_node->child1().useKind() == ObjectOrOtherUse && m_node->child2().useKind() == ObjectUse)) 79 handleMasqueradesAsUndefined(); 80 break; 81 82 case LogicalNot: 83 case Branch: 84 if (m_node->child1().useKind() == ObjectOrOtherUse) 85 handleMasqueradesAsUndefined(); 86 break; 87 88 case GetByVal: 89 if (m_node->arrayMode().type() == Array::Double 90 && m_node->arrayMode().isSaneChain()) { 91 addLazily(globalObject()->arrayPrototype()->structure()->transitionWatchpointSet()); 92 addLazily(globalObject()->objectPrototype()->structure()->transitionWatchpointSet()); 93 } 94 95 if (m_node->arrayMode().type() == Array::String) 96 handleStringGetByVal(); 97 98 if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node)) 99 addLazily(view); 100 break; 101 102 case PutByVal: 103 if (JSArrayBufferView* view = m_graph.tryGetFoldableViewForChild1(m_node)) 104 addLazily(view); 105 break; 106 107 case StringCharAt: 108 handleStringGetByVal(); 109 break; 110 111 case NewArray: 112 case NewArrayWithSize: 113 case NewArrayBuffer: 114 if (!globalObject()->isHavingABadTime() && !hasAnyArrayStorage(m_node->indexingType())) 115 addLazily(globalObject()->havingABadTimeWatchpoint()); 116 break; 117 118 case AllocationProfileWatchpoint: 119 addLazily(jsCast<JSFunction*>(m_node->function())->allocationProfileWatchpointSet()); 120 break; 121 122 case StructureTransitionWatchpoint: 123 m_graph.watchpoints().addLazily( 124 m_node->origin.semantic, 125 m_node->child1()->op() == WeakJSConstant ? BadWeakConstantCacheWatchpoint : BadCacheWatchpoint, 126 m_node->structure()->transitionWatchpointSet()); 127 break; 128 129 case VariableWatchpoint: 130 addLazily(m_node->variableWatchpointSet()); 131 break; 132 133 case VarInjectionWatchpoint: 134 addLazily(globalObject()->varInjectionWatchpoint()); 135 break; 136 137 case FunctionReentryWatchpoint: 138 addLazily(m_node->symbolTable()->m_functionEnteredOnce); 139 break; 140 141 case TypedArrayWatchpoint: 142 addLazily(m_node->typedArray()); 143 break; 144 145 default: 146 break; 147 } 148 } 149 150 void handleEdge(Node*, Edge edge) 151 { 152 switch (edge.useKind()) { 153 case StringObjectUse: 154 case StringOrStringObjectUse: { 155 Structure* stringObjectStructure = globalObject()->stringObjectStructure(); 156 Structure* stringPrototypeStructure = stringObjectStructure->storedPrototype().asCell()->structure(); 157 ASSERT(m_graph.watchpoints().isValidOrMixed(stringPrototypeStructure->transitionWatchpointSet())); 158 159 m_graph.watchpoints().addLazily( 160 m_node->origin.semantic, NotStringObject, 161 stringPrototypeStructure->transitionWatchpointSet()); 162 break; 163 } 164 165 default: 166 break; 167 } 168 } 169 170 void handleMasqueradesAsUndefined() 171 { 172 if (m_graph.masqueradesAsUndefinedWatchpointIsStillValid(m_node->origin.semantic)) 173 addLazily(globalObject()->masqueradesAsUndefinedWatchpoint()); 174 } 175 176 void handleStringGetByVal() 177 { 178 if (!m_node->arrayMode().isOutOfBounds()) 179 return; 180 if (!globalObject()->stringPrototypeChainIsSane()) 181 return; 182 addLazily(globalObject()->stringPrototype()->structure()->transitionWatchpointSet()); 183 addLazily(globalObject()->objectPrototype()->structure()->transitionWatchpointSet()); 184 } 185 186 void addLazily(WatchpointSet* set) 187 { 188 m_graph.watchpoints().addLazily(set); 189 } 190 void addLazily(InlineWatchpointSet& set) 191 { 192 m_graph.watchpoints().addLazily(set); 193 } 194 void addLazily(JSArrayBufferView* view) 195 { 196 m_graph.watchpoints().addLazily(view); 197 } 198 199 JSGlobalObject* globalObject() 200 { 201 return m_graph.globalObjectFor(m_node->origin.semantic); 202 } 203 204 Node* m_node; 205}; 206 207bool performWatchpointCollection(Graph& graph) 208{ 209 SamplingRegion samplingRegion("DFG Watchpoint Collection Phase"); 210 return runPhase<WatchpointCollectionPhase>(graph); 211} 212 213} } // namespace JSC::DFG 214 215#endif // ENABLE(DFG_JIT) 216 217