1 // Copyright 2015 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_COMPILER_COMPILATION_DEPENDENCIES_H_ 6 #define V8_COMPILER_COMPILATION_DEPENDENCIES_H_ 7 8 #include "src/compiler/js-heap-broker.h" 9 #include "src/objects/objects.h" 10 #include "src/zone/zone-containers.h" 11 12 namespace v8 { 13 namespace internal { 14 namespace compiler { 15 16 class SlackTrackingPrediction { 17 public: 18 SlackTrackingPrediction(MapRef initial_map, int instance_size); 19 inobject_property_count()20 int inobject_property_count() const { return inobject_property_count_; } instance_size()21 int instance_size() const { return instance_size_; } 22 23 private: 24 int instance_size_; 25 int inobject_property_count_; 26 }; 27 28 class CompilationDependency; 29 30 // Collects and installs dependencies of the code that is being generated. 31 class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject { 32 public: 33 CompilationDependencies(JSHeapBroker* broker, Zone* zone); 34 35 V8_WARN_UNUSED_RESULT bool Commit(Handle<Code> code); 36 37 // Return the initial map of {function} and record the assumption that it 38 // stays the initial map. 39 MapRef DependOnInitialMap(const JSFunctionRef& function); 40 41 // Return the "prototype" property of the given function and record the 42 // assumption that it doesn't change. 43 ObjectRef DependOnPrototypeProperty(const JSFunctionRef& function); 44 45 // Record the assumption that {map} stays stable. 46 void DependOnStableMap(const MapRef& map); 47 48 // Record the assumption that {target_map} can be transitioned to, i.e., that 49 // it does not become deprecated. 50 void DependOnTransition(const MapRef& target_map); 51 52 // Return the pretenure mode of {site} and record the assumption that it does 53 // not change. 54 AllocationType DependOnPretenureMode(const AllocationSiteRef& site); 55 56 // Record the assumption that the field representation of a field does not 57 // change. The field is identified by the arguments. 58 void DependOnFieldRepresentation(const MapRef& map, InternalIndex descriptor); 59 60 // Record the assumption that the field type of a field does not change. The 61 // field is identified by the arguments. 62 void DependOnFieldType(const MapRef& map, InternalIndex descriptor); 63 64 // Return a field's constness and, if kConst, record the assumption that it 65 // remains kConst. The field is identified by the arguments. 66 // 67 // For arrays, arguments objects and value wrappers, only consider the field 68 // kConst if the map is stable (and register stability dependency in that 69 // case). This is to ensure that fast elements kind transitions cannot be 70 // used to mutate fields without deoptimization of the dependent code. 71 PropertyConstness DependOnFieldConstness(const MapRef& map, 72 InternalIndex descriptor); 73 74 // Record the assumption that neither {cell}'s {CellType} changes, nor the 75 // {IsReadOnly()} flag of {cell}'s {PropertyDetails}. 76 void DependOnGlobalProperty(const PropertyCellRef& cell); 77 78 // Return the validity of the given protector and, if true, record the 79 // assumption that the protector remains valid. 80 bool DependOnProtector(const PropertyCellRef& cell); 81 82 // Convenience wrappers around {DependOnProtector}. 83 bool DependOnArrayBufferDetachingProtector(); 84 bool DependOnArrayIteratorProtector(); 85 bool DependOnArraySpeciesProtector(); 86 bool DependOnNoElementsProtector(); 87 bool DependOnPromiseHookProtector(); 88 bool DependOnPromiseSpeciesProtector(); 89 bool DependOnPromiseThenProtector(); 90 91 // Record the assumption that {site}'s {ElementsKind} doesn't change. 92 void DependOnElementsKind(const AllocationSiteRef& site); 93 94 // For each given map, depend on the stability of (the maps of) all prototypes 95 // up to (and including) the {last_prototype}. 96 template <class MapContainer> 97 void DependOnStablePrototypeChains( 98 MapContainer const& receiver_maps, WhereToStart start, 99 base::Optional<JSObjectRef> last_prototype = 100 base::Optional<JSObjectRef>()); 101 102 // Like DependOnElementsKind but also applies to all nested allocation sites. 103 void DependOnElementsKinds(const AllocationSiteRef& site); 104 105 // Predict the final instance size for {function}'s initial map and record 106 // the assumption that this prediction is correct. In addition, register 107 // the initial map dependency. This method returns the {function}'s the 108 // predicted minimum slack instance size count (wrapped together with 109 // the corresponding in-object property count for convenience). 110 SlackTrackingPrediction DependOnInitialMapInstanceSizePrediction( 111 const JSFunctionRef& function); 112 113 // The methods below allow for gathering dependencies without actually 114 // recording them. They can be recorded at a later time (or they can be 115 // ignored). For example, 116 // DependOnTransition(map); 117 // is equivalent to: 118 // RecordDependency(TransitionDependencyOffTheRecord(map)); 119 void RecordDependency(CompilationDependency const* dependency); 120 CompilationDependency const* TransitionDependencyOffTheRecord( 121 const MapRef& target_map) const; 122 CompilationDependency const* FieldRepresentationDependencyOffTheRecord( 123 const MapRef& map, InternalIndex descriptor) const; 124 CompilationDependency const* FieldTypeDependencyOffTheRecord( 125 const MapRef& map, InternalIndex descriptor) const; 126 127 // Exposed only for testing purposes. 128 bool AreValid() const; 129 130 private: 131 Zone* const zone_; 132 JSHeapBroker* const broker_; 133 ZoneForwardList<CompilationDependency const*> dependencies_; 134 }; 135 136 } // namespace compiler 137 } // namespace internal 138 } // namespace v8 139 140 #endif // V8_COMPILER_COMPILATION_DEPENDENCIES_H_ 141