1/* 2 * Copyright (C) 2011, 2012, 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#ifndef DFGStructureAbstractValue_h 27#define DFGStructureAbstractValue_h 28 29#if ENABLE(DFG_JIT) 30 31#include "JSCell.h" 32#include "SpeculatedType.h" 33#include "DumpContext.h" 34#include "StructureSet.h" 35 36namespace JSC { namespace DFG { 37 38class StructureAbstractValue { 39public: 40 StructureAbstractValue() 41 : m_structure(0) 42 { 43 } 44 45 StructureAbstractValue(Structure* structure) 46 : m_structure(structure) 47 { 48 } 49 50 StructureAbstractValue(const StructureSet& set) 51 { 52 switch (set.size()) { 53 case 0: 54 m_structure = 0; 55 break; 56 57 case 1: 58 m_structure = set[0]; 59 break; 60 61 default: 62 m_structure = topValue(); 63 break; 64 } 65 } 66 67 void clear() 68 { 69 m_structure = 0; 70 } 71 72 void makeTop() 73 { 74 m_structure = topValue(); 75 } 76 77 static StructureAbstractValue top() 78 { 79 StructureAbstractValue value; 80 value.makeTop(); 81 return value; 82 } 83 84 void add(Structure* structure) 85 { 86 ASSERT(!contains(structure) && !isTop()); 87 if (m_structure) 88 makeTop(); 89 else 90 m_structure = structure; 91 } 92 93 bool addAll(const StructureSet& other) 94 { 95 if (isTop() || !other.size()) 96 return false; 97 if (other.size() > 1) { 98 makeTop(); 99 return true; 100 } 101 if (!m_structure) { 102 m_structure = other[0]; 103 return true; 104 } 105 if (m_structure == other[0]) 106 return false; 107 makeTop(); 108 return true; 109 } 110 111 bool addAll(const StructureAbstractValue& other) 112 { 113 if (!other.m_structure) 114 return false; 115 if (isTop()) 116 return false; 117 if (other.isTop()) { 118 makeTop(); 119 return true; 120 } 121 if (m_structure) { 122 if (m_structure == other.m_structure) 123 return false; 124 makeTop(); 125 return true; 126 } 127 m_structure = other.m_structure; 128 return true; 129 } 130 131 bool contains(Structure* structure) const 132 { 133 if (isTop()) 134 return true; 135 if (m_structure == structure) 136 return true; 137 return false; 138 } 139 140 bool isSubsetOf(const StructureSet& other) const 141 { 142 if (isTop()) 143 return false; 144 if (!m_structure) 145 return true; 146 return other.contains(m_structure); 147 } 148 149 bool doesNotContainAnyOtherThan(Structure* structure) const 150 { 151 if (isTop()) 152 return false; 153 if (!m_structure) 154 return true; 155 return m_structure == structure; 156 } 157 158 bool isSupersetOf(const StructureSet& other) const 159 { 160 if (isTop()) 161 return true; 162 if (!other.size()) 163 return true; 164 if (other.size() > 1) 165 return false; 166 return m_structure == other[0]; 167 } 168 169 bool isSubsetOf(const StructureAbstractValue& other) const 170 { 171 if (other.isTop()) 172 return true; 173 if (isTop()) 174 return false; 175 if (m_structure) { 176 if (other.m_structure) 177 return m_structure == other.m_structure; 178 return false; 179 } 180 return true; 181 } 182 183 bool isSupersetOf(const StructureAbstractValue& other) const 184 { 185 return other.isSubsetOf(*this); 186 } 187 188 void filter(const StructureSet& other) 189 { 190 if (!m_structure) 191 return; 192 193 if (isTop()) { 194 switch (other.size()) { 195 case 0: 196 m_structure = 0; 197 return; 198 199 case 1: 200 m_structure = other[0]; 201 return; 202 203 default: 204 return; 205 } 206 } 207 208 if (other.contains(m_structure)) 209 return; 210 211 m_structure = 0; 212 } 213 214 void filter(const StructureAbstractValue& other) 215 { 216 if (isTop()) { 217 m_structure = other.m_structure; 218 return; 219 } 220 if (m_structure == other.m_structure) 221 return; 222 if (other.isTop()) 223 return; 224 m_structure = 0; 225 } 226 227 void filter(SpeculatedType other) 228 { 229 if (!(other & SpecCell)) { 230 clear(); 231 return; 232 } 233 234 if (isClearOrTop()) 235 return; 236 237 if (!(speculationFromStructure(m_structure) & other)) 238 m_structure = 0; 239 } 240 241 bool isClear() const 242 { 243 return !m_structure; 244 } 245 246 bool isTop() const { return m_structure == topValue(); } 247 248 bool isClearOrTop() const { return m_structure <= topValue(); } 249 bool isNeitherClearNorTop() const { return !isClearOrTop(); } 250 251 size_t size() const 252 { 253 ASSERT(!isTop()); 254 return !!m_structure; 255 } 256 257 Structure* at(size_t i) const 258 { 259 ASSERT(!isTop()); 260 ASSERT(m_structure); 261 ASSERT_UNUSED(i, !i); 262 return m_structure; 263 } 264 265 Structure* operator[](size_t i) const 266 { 267 return at(i); 268 } 269 270 Structure* last() const 271 { 272 return at(0); 273 } 274 275 SpeculatedType speculationFromStructures() const 276 { 277 if (isTop()) 278 return SpecCell; 279 if (isClear()) 280 return SpecNone; 281 return speculationFromStructure(m_structure); 282 } 283 284 bool isValidOffset(PropertyOffset offset) 285 { 286 if (isTop()) 287 return false; 288 if (isClear()) 289 return true; 290 return m_structure->isValidOffset(offset); 291 } 292 293 bool hasSingleton() const 294 { 295 return isNeitherClearNorTop(); 296 } 297 298 Structure* singleton() const 299 { 300 ASSERT(isNeitherClearNorTop()); 301 return m_structure; 302 } 303 304 bool operator==(const StructureAbstractValue& other) const 305 { 306 return m_structure == other.m_structure; 307 } 308 309 void dumpInContext(PrintStream& out, DumpContext* context) const 310 { 311 if (isTop()) { 312 out.print("TOP"); 313 return; 314 } 315 316 out.print("["); 317 if (m_structure) 318 out.print(inContext(*m_structure, context)); 319 out.print("]"); 320 } 321 322 void dump(PrintStream& out) const 323 { 324 dumpInContext(out, 0); 325 } 326 327private: 328 static Structure* topValue() { return reinterpret_cast<Structure*>(1); } 329 330 // NB. This must have a trivial destructor. 331 332 // This can only remember one structure at a time. 333 Structure* m_structure; 334}; 335 336} } // namespace JSC::DFG 337 338#endif // ENABLE(DFG_JIT) 339 340#endif // DFGStructureAbstractValue_h 341 342 343