/ bytecode / ObjectPropertyConditionSet.h
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