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_ACCESS_INFO_H_ 6 #define V8_COMPILER_ACCESS_INFO_H_ 7 8 #include <iosfwd> 9 10 #include "src/codegen/machine-type.h" 11 #include "src/compiler/types.h" 12 #include "src/objects/feedback-vector.h" 13 #include "src/objects/field-index.h" 14 #include "src/objects/map.h" 15 #include "src/objects/objects.h" 16 #include "src/zone/zone-containers.h" 17 18 namespace v8 { 19 namespace internal { 20 21 // Forward declarations. 22 class Factory; 23 24 namespace compiler { 25 26 // Forward declarations. 27 class CompilationDependencies; 28 class CompilationDependency; 29 class ElementAccessFeedback; 30 class JSHeapBroker; 31 class MinimorphicLoadPropertyAccessFeedback; 32 class TypeCache; 33 struct ConstFieldInfo; 34 35 std::ostream& operator<<(std::ostream&, AccessMode); 36 37 // This class encapsulates all information required to access a certain element. 38 class ElementAccessInfo final { 39 public: 40 ElementAccessInfo(ZoneVector<Handle<Map>>&& lookup_start_object_maps, 41 ElementsKind elements_kind, Zone* zone); 42 elements_kind()43 ElementsKind elements_kind() const { return elements_kind_; } lookup_start_object_maps()44 ZoneVector<Handle<Map>> const& lookup_start_object_maps() const { 45 return lookup_start_object_maps_; 46 } transition_sources()47 ZoneVector<Handle<Map>> const& transition_sources() const { 48 return transition_sources_; 49 } 50 AddTransitionSource(Handle<Map> map)51 void AddTransitionSource(Handle<Map> map) { 52 CHECK_EQ(lookup_start_object_maps_.size(), 1); 53 transition_sources_.push_back(map); 54 } 55 56 private: 57 ElementsKind elements_kind_; 58 ZoneVector<Handle<Map>> lookup_start_object_maps_; 59 ZoneVector<Handle<Map>> transition_sources_; 60 }; 61 62 // This class encapsulates all information required to access a certain 63 // object property, either on the object itself or on the prototype chain. 64 class PropertyAccessInfo final { 65 public: 66 enum Kind { 67 kInvalid, 68 kNotFound, 69 kDataField, 70 kDataConstant, 71 kAccessorConstant, 72 kModuleExport, 73 kStringLength 74 }; 75 76 static PropertyAccessInfo NotFound(Zone* zone, Handle<Map> receiver_map, 77 MaybeHandle<JSObject> holder); 78 static PropertyAccessInfo DataField( 79 Zone* zone, Handle<Map> receiver_map, 80 ZoneVector<CompilationDependency const*>&& unrecorded_dependencies, 81 FieldIndex field_index, Representation field_representation, 82 Type field_type, Handle<Map> field_owner_map, 83 MaybeHandle<Map> field_map = MaybeHandle<Map>(), 84 MaybeHandle<JSObject> holder = MaybeHandle<JSObject>(), 85 MaybeHandle<Map> transition_map = MaybeHandle<Map>()); 86 static PropertyAccessInfo DataConstant( 87 Zone* zone, Handle<Map> receiver_map, 88 ZoneVector<CompilationDependency const*>&& unrecorded_dependencies, 89 FieldIndex field_index, Representation field_representation, 90 Type field_type, Handle<Map> field_owner_map, MaybeHandle<Map> field_map, 91 MaybeHandle<JSObject> holder, 92 MaybeHandle<Map> transition_map = MaybeHandle<Map>()); 93 static PropertyAccessInfo AccessorConstant(Zone* zone, 94 Handle<Map> receiver_map, 95 Handle<Object> constant, 96 MaybeHandle<JSObject> holder); 97 static PropertyAccessInfo ModuleExport(Zone* zone, Handle<Map> receiver_map, 98 Handle<Cell> cell); 99 static PropertyAccessInfo StringLength(Zone* zone, Handle<Map> receiver_map); 100 static PropertyAccessInfo Invalid(Zone* zone); 101 102 bool Merge(PropertyAccessInfo const* that, AccessMode access_mode, 103 Zone* zone) V8_WARN_UNUSED_RESULT; 104 105 void RecordDependencies(CompilationDependencies* dependencies); 106 IsInvalid()107 bool IsInvalid() const { return kind() == kInvalid; } IsNotFound()108 bool IsNotFound() const { return kind() == kNotFound; } IsDataField()109 bool IsDataField() const { return kind() == kDataField; } IsDataConstant()110 bool IsDataConstant() const { return kind() == kDataConstant; } IsAccessorConstant()111 bool IsAccessorConstant() const { return kind() == kAccessorConstant; } IsModuleExport()112 bool IsModuleExport() const { return kind() == kModuleExport; } IsStringLength()113 bool IsStringLength() const { return kind() == kStringLength; } 114 HasTransitionMap()115 bool HasTransitionMap() const { return !transition_map().is_null(); } 116 ConstFieldInfo GetConstFieldInfo() const; 117 kind()118 Kind kind() const { return kind_; } holder()119 MaybeHandle<JSObject> holder() const { 120 // TODO(neis): There was a CHECK here that tries to protect against 121 // using the access info without recording its dependencies first. 122 // Find a more suitable place for it. 123 return holder_; 124 } transition_map()125 MaybeHandle<Map> transition_map() const { return transition_map_; } constant()126 Handle<Object> constant() const { return constant_; } field_index()127 FieldIndex field_index() const { return field_index_; } field_type()128 Type field_type() const { return field_type_; } field_representation()129 Representation field_representation() const { return field_representation_; } field_map()130 MaybeHandle<Map> field_map() const { return field_map_; } lookup_start_object_maps()131 ZoneVector<Handle<Map>> const& lookup_start_object_maps() const { 132 return lookup_start_object_maps_; 133 } 134 135 private: 136 explicit PropertyAccessInfo(Zone* zone); 137 PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder, 138 ZoneVector<Handle<Map>>&& lookup_start_object_maps); 139 PropertyAccessInfo(Zone* zone, Kind kind, MaybeHandle<JSObject> holder, 140 Handle<Object> constant, 141 ZoneVector<Handle<Map>>&& lookup_start_object_maps); 142 PropertyAccessInfo(Kind kind, MaybeHandle<JSObject> holder, 143 MaybeHandle<Map> transition_map, FieldIndex field_index, 144 Representation field_representation, Type field_type, 145 Handle<Map> field_owner_map, MaybeHandle<Map> field_map, 146 ZoneVector<Handle<Map>>&& lookup_start_object_maps, 147 ZoneVector<CompilationDependency const*>&& dependencies); 148 149 Kind kind_; 150 ZoneVector<Handle<Map>> lookup_start_object_maps_; 151 ZoneVector<CompilationDependency const*> unrecorded_dependencies_; 152 Handle<Object> constant_; 153 MaybeHandle<Map> transition_map_; 154 MaybeHandle<JSObject> holder_; 155 FieldIndex field_index_; 156 Representation field_representation_; 157 Type field_type_; 158 MaybeHandle<Map> field_owner_map_; 159 MaybeHandle<Map> field_map_; 160 }; 161 162 // This class encapsulates information required to generate load properties 163 // by only using the information from handlers. This information is used with 164 // dynamic map checks. 165 class MinimorphicLoadPropertyAccessInfo final { 166 public: 167 enum Kind { kInvalid, kDataField }; 168 static MinimorphicLoadPropertyAccessInfo DataField( 169 int offset, bool is_inobject, Representation field_representation, 170 Type field_type); 171 static MinimorphicLoadPropertyAccessInfo Invalid(); 172 IsInvalid()173 bool IsInvalid() const { return kind_ == kInvalid; } IsDataField()174 bool IsDataField() const { return kind_ == kDataField; } offset()175 int offset() const { return offset_; } is_inobject()176 int is_inobject() const { return is_inobject_; } field_type()177 Type field_type() const { return field_type_; } field_representation()178 Representation field_representation() const { return field_representation_; } 179 180 private: 181 MinimorphicLoadPropertyAccessInfo(Kind kind, int offset, bool is_inobject, 182 Representation field_representation, 183 Type field_type); 184 185 Kind kind_; 186 bool is_inobject_; 187 int offset_; 188 Representation field_representation_; 189 Type field_type_; 190 }; 191 192 // Factory class for {ElementAccessInfo}s and {PropertyAccessInfo}s. 193 class AccessInfoFactory final { 194 public: 195 AccessInfoFactory(JSHeapBroker* broker, CompilationDependencies* dependencies, 196 Zone* zone); 197 198 base::Optional<ElementAccessInfo> ComputeElementAccessInfo( 199 Handle<Map> map, AccessMode access_mode) const; 200 bool ComputeElementAccessInfos( 201 ElementAccessFeedback const& feedback, 202 ZoneVector<ElementAccessInfo>* access_infos) const; 203 204 PropertyAccessInfo ComputePropertyAccessInfo(Handle<Map> map, 205 Handle<Name> name, 206 AccessMode access_mode) const; 207 208 MinimorphicLoadPropertyAccessInfo ComputePropertyAccessInfo( 209 MinimorphicLoadPropertyAccessFeedback const& feedback) const; 210 211 // Convenience wrapper around {ComputePropertyAccessInfo} for multiple maps. 212 void ComputePropertyAccessInfos( 213 MapHandles const& maps, Handle<Name> name, AccessMode access_mode, 214 ZoneVector<PropertyAccessInfo>* access_infos) const; 215 216 // Merge as many of the given {infos} as possible and record any dependencies. 217 // Return false iff any of them was invalid, in which case no dependencies are 218 // recorded. 219 // TODO(neis): Make access_mode part of access info? 220 bool FinalizePropertyAccessInfos( 221 ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode, 222 ZoneVector<PropertyAccessInfo>* result) const; 223 224 // Merge the given {infos} to a single one and record any dependencies. If the 225 // merge is not possible, the result has kind {kInvalid} and no dependencies 226 // are recorded. 227 PropertyAccessInfo FinalizePropertyAccessInfosAsOne( 228 ZoneVector<PropertyAccessInfo> infos, AccessMode access_mode) const; 229 230 private: 231 base::Optional<ElementAccessInfo> ConsolidateElementLoad( 232 ElementAccessFeedback const& feedback) const; 233 PropertyAccessInfo LookupSpecialFieldAccessor(Handle<Map> map, 234 Handle<Name> name) const; 235 PropertyAccessInfo LookupTransition(Handle<Map> map, Handle<Name> name, 236 MaybeHandle<JSObject> holder) const; 237 PropertyAccessInfo ComputeDataFieldAccessInfo(Handle<Map> receiver_map, 238 Handle<Map> map, 239 MaybeHandle<JSObject> holder, 240 InternalIndex descriptor, 241 AccessMode access_mode) const; 242 PropertyAccessInfo ComputeAccessorDescriptorAccessInfo( 243 Handle<Map> receiver_map, Handle<Name> name, Handle<Map> map, 244 MaybeHandle<JSObject> holder, InternalIndex descriptor, 245 AccessMode access_mode) const; 246 247 void MergePropertyAccessInfos(ZoneVector<PropertyAccessInfo> infos, 248 AccessMode access_mode, 249 ZoneVector<PropertyAccessInfo>* result) const; 250 dependencies()251 CompilationDependencies* dependencies() const { return dependencies_; } broker()252 JSHeapBroker* broker() const { return broker_; } 253 Isolate* isolate() const; zone()254 Zone* zone() const { return zone_; } 255 256 JSHeapBroker* const broker_; 257 CompilationDependencies* const dependencies_; 258 TypeCache const* const type_cache_; 259 Zone* const zone_; 260 261 // TODO(nicohartmann@): Move to public 262 AccessInfoFactory(const AccessInfoFactory&) = delete; 263 AccessInfoFactory& operator=(const AccessInfoFactory&) = delete; 264 }; 265 266 } // namespace compiler 267 } // namespace internal 268 } // namespace v8 269 270 #endif // V8_COMPILER_ACCESS_INFO_H_ 271