ObjectPropertyConditionSet.h
1 /* 2 * Copyright (C) 2015-2018 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 #pragma once 27 28 #include "ObjectPropertyCondition.h" 29 #include <wtf/FastMalloc.h> 30 #include <wtf/Vector.h> 31 32 namespace JSC { 33 34 // An object property condition set is used to represent the set of additional conditions 35 // that need to be met for some heap access to be valid. The set can have the following 36 // interesting states: 37 // 38 // Empty: There are no special conditions that need to be met. 39 // Invalid: The heap access is never valid. 40 // Non-empty: The heap access is valid if all the ObjectPropertyConditions in the set are valid. 41 42 class ObjectPropertyConditionSet { 43 public: 44 ObjectPropertyConditionSet() { } 45 46 static ObjectPropertyConditionSet invalid() 47 { 48 ObjectPropertyConditionSet result; 49 result.m_data = adoptRef(new Data()); 50 return result; 51 } 52 53 static ObjectPropertyConditionSet create(const Vector<ObjectPropertyCondition>& vector) 54 { 55 if (vector.isEmpty()) 56 return ObjectPropertyConditionSet(); 57 58 ObjectPropertyConditionSet result; 59 result.m_data = adoptRef(new Data()); 60 result.m_data->vector = vector; 61 return result; 62 } 63 64 bool isValid() const 65 { 66 return !m_data || !m_data->vector.isEmpty(); 67 } 68 69 bool isValidAndWatchable() const; 70 71 size_t size() const { return m_data ? m_data->vector.size() : 0; } 72 bool isEmpty() const 73 { 74 return !m_data; 75 } 76 77 typedef const ObjectPropertyCondition* iterator; 78 79 iterator begin() const 80 { 81 if (!m_data) 82 return nullptr; 83 return m_data->vector.begin(); 84 } 85 iterator end() const 86 { 87 if (!m_data) 88 return nullptr; 89 return m_data->vector.end(); 90 } 91 92 ObjectPropertyCondition forObject(JSObject*) const; 93 ObjectPropertyCondition forConditionKind(PropertyCondition::Kind) const; 94 95 unsigned numberOfConditionsWithKind(PropertyCondition::Kind) const; 96 97 bool hasOneSlotBaseCondition() const; 98 99 // If this is a condition set for a prototype hit, then this is guaranteed to return the 100 // condition on the prototype itself. This allows you to get the object, offset, and 101 // attributes for the prototype. This will RELEASE_ASSERT that there is exactly one Presence 102 // in the set, and it will return that presence. 103 ObjectPropertyCondition slotBaseCondition() const; 104 105 // Attempt to create a new condition set by merging this one with the other one. This will 106 // fail if any of the conditions are incompatible with each other. When if fails, it returns 107 // invalid(). 108 ObjectPropertyConditionSet mergedWith(const ObjectPropertyConditionSet& other) const; 109 110 bool structuresEnsureValidity() const; 111 bool structuresEnsureValidityAssumingImpurePropertyWatchpoint() const; 112 113 bool needImpurePropertyWatchpoint() const; 114 115 template<typename Functor> 116 void forEachDependentCell(const Functor& functor) const 117 { 118 for (const ObjectPropertyCondition& condition : *this) 119 condition.forEachDependentCell(functor); 120 } 121 122 bool areStillLive(VM&) const; 123 124 void dumpInContext(PrintStream&, DumpContext*) const; 125 void dump(PrintStream&) const; 126 127 // Helpers for using this in a union. 128 void* releaseRawPointer() 129 { 130 return static_cast<void*>(m_data.leakRef()); 131 } 132 static ObjectPropertyConditionSet adoptRawPointer(void* rawPointer) 133 { 134 ObjectPropertyConditionSet result; 135 result.m_data = adoptRef(static_cast<Data*>(rawPointer)); 136 return result; 137 } 138 static ObjectPropertyConditionSet fromRawPointer(void* rawPointer) 139 { 140 ObjectPropertyConditionSet result; 141 result.m_data = static_cast<Data*>(rawPointer); 142 return result; 143 } 144 145 // FIXME: Everything below here should be private, but cannot be because of a bug in VS. 146 147 // Internally, this represents Invalid using a pointer to a Data that has an empty vector. 148 149 // FIXME: This could be made more compact by having it internally use a vector that just has 150 // the non-uid portion of ObjectPropertyCondition, and then requiring that the callers of all 151 // of the APIs supply the uid. 152 153 class Data : public ThreadSafeRefCounted<Data> { 154 WTF_MAKE_NONCOPYABLE(Data); 155 WTF_MAKE_FAST_ALLOCATED; 156 157 public: 158 Data() { } 159 160 Vector<ObjectPropertyCondition> vector; 161 }; 162 163 private: 164 RefPtr<Data> m_data; 165 }; 166 167 ObjectPropertyCondition generateConditionForSelfEquivalence( 168 VM&, JSCell* owner, JSObject* object, UniquedStringImpl* uid); 169 170 ObjectPropertyConditionSet generateConditionsForPropertyMiss( 171 VM&, JSCell* owner, JSGlobalObject*, Structure* headStructure, UniquedStringImpl* uid); 172 ObjectPropertyConditionSet generateConditionsForPropertySetterMiss( 173 VM&, JSCell* owner, JSGlobalObject*, Structure* headStructure, UniquedStringImpl* uid); 174 ObjectPropertyConditionSet generateConditionsForPrototypePropertyHit( 175 VM&, JSCell* owner, JSGlobalObject*, Structure* headStructure, JSObject* prototype, 176 UniquedStringImpl* uid); 177 ObjectPropertyConditionSet generateConditionsForPrototypePropertyHitCustom( 178 VM&, JSCell* owner, JSGlobalObject*, Structure* headStructure, JSObject* prototype, 179 UniquedStringImpl* uid, unsigned attributes); 180 181 ObjectPropertyConditionSet generateConditionsForInstanceOf( 182 VM&, JSCell* owner, JSGlobalObject*, Structure* headStructure, JSObject* prototype, bool shouldHit); 183 184 ObjectPropertyConditionSet generateConditionsForPrototypeEquivalenceConcurrently( 185 VM&, JSGlobalObject*, Structure* headStructure, JSObject* prototype, 186 UniquedStringImpl* uid); 187 ObjectPropertyConditionSet generateConditionsForPropertyMissConcurrently( 188 VM&, JSGlobalObject*, Structure* headStructure, UniquedStringImpl* uid); 189 ObjectPropertyConditionSet generateConditionsForPropertySetterMissConcurrently( 190 VM&, JSGlobalObject*, Structure* headStructure, UniquedStringImpl* uid); 191 192 struct PrototypeChainCachingStatus { 193 bool usesPolyProto; 194 bool flattenedDictionary; 195 }; 196 197 Optional<PrototypeChainCachingStatus> prepareChainForCaching(JSGlobalObject*, JSCell* base, const PropertySlot&); 198 Optional<PrototypeChainCachingStatus> prepareChainForCaching(JSGlobalObject*, JSCell* base, JSObject* target); 199 Optional<PrototypeChainCachingStatus> prepareChainForCaching(JSGlobalObject*, Structure* base, JSObject* target); 200 201 } // namespace JSC