1 // Copyright 2019 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_PROCESSED_FEEDBACK_H_ 6 #define V8_COMPILER_PROCESSED_FEEDBACK_H_ 7 8 #include "src/compiler/feedback-source.h" 9 #include "src/compiler/heap-refs.h" 10 11 namespace v8 { 12 namespace internal { 13 namespace compiler { 14 15 class BinaryOperationFeedback; 16 class CallFeedback; 17 class CompareOperationFeedback; 18 class ElementAccessFeedback; 19 class ForInFeedback; 20 class GlobalAccessFeedback; 21 class InstanceOfFeedback; 22 class LiteralFeedback; 23 class MinimorphicLoadPropertyAccessFeedback; 24 class NamedAccessFeedback; 25 class RegExpLiteralFeedback; 26 class TemplateObjectFeedback; 27 28 class ProcessedFeedback : public ZoneObject { 29 public: 30 enum Kind { 31 kInsufficient, 32 kBinaryOperation, 33 kCall, 34 kCompareOperation, 35 kElementAccess, 36 kForIn, 37 kGlobalAccess, 38 kInstanceOf, 39 kLiteral, 40 kMinimorphicPropertyAccess, 41 kNamedAccess, 42 kRegExpLiteral, 43 kTemplateObject, 44 }; kind()45 Kind kind() const { return kind_; } 46 slot_kind()47 FeedbackSlotKind slot_kind() const { return slot_kind_; } IsInsufficient()48 bool IsInsufficient() const { return kind() == kInsufficient; } 49 50 BinaryOperationFeedback const& AsBinaryOperation() const; 51 CallFeedback const& AsCall() const; 52 CompareOperationFeedback const& AsCompareOperation() const; 53 ElementAccessFeedback const& AsElementAccess() const; 54 ForInFeedback const& AsForIn() const; 55 GlobalAccessFeedback const& AsGlobalAccess() const; 56 InstanceOfFeedback const& AsInstanceOf() const; 57 NamedAccessFeedback const& AsNamedAccess() const; 58 MinimorphicLoadPropertyAccessFeedback const& AsMinimorphicPropertyAccess() 59 const; 60 LiteralFeedback const& AsLiteral() const; 61 RegExpLiteralFeedback const& AsRegExpLiteral() const; 62 TemplateObjectFeedback const& AsTemplateObject() const; 63 64 protected: 65 ProcessedFeedback(Kind kind, FeedbackSlotKind slot_kind); 66 67 private: 68 Kind const kind_; 69 FeedbackSlotKind const slot_kind_; 70 }; 71 72 class InsufficientFeedback final : public ProcessedFeedback { 73 public: 74 explicit InsufficientFeedback(FeedbackSlotKind slot_kind); 75 }; 76 77 class GlobalAccessFeedback : public ProcessedFeedback { 78 public: 79 GlobalAccessFeedback(PropertyCellRef cell, FeedbackSlotKind slot_kind); 80 GlobalAccessFeedback(ContextRef script_context, int slot_index, 81 bool immutable, FeedbackSlotKind slot_kind); 82 explicit GlobalAccessFeedback(FeedbackSlotKind slot_kind); // Megamorphic 83 84 bool IsMegamorphic() const; 85 86 bool IsPropertyCell() const; 87 PropertyCellRef property_cell() const; 88 89 bool IsScriptContextSlot() const; 90 ContextRef script_context() const; 91 int slot_index() const; 92 bool immutable() const; 93 94 base::Optional<ObjectRef> GetConstantHint() const; 95 96 private: 97 base::Optional<ObjectRef> const cell_or_context_; 98 int const index_and_immutable_; 99 }; 100 101 class KeyedAccessMode { 102 public: 103 static KeyedAccessMode FromNexus(FeedbackNexus const& nexus); 104 105 AccessMode access_mode() const; 106 bool IsLoad() const; 107 bool IsStore() const; 108 KeyedAccessLoadMode load_mode() const; 109 KeyedAccessStoreMode store_mode() const; 110 111 private: 112 AccessMode const access_mode_; 113 union LoadStoreMode { 114 LoadStoreMode(KeyedAccessLoadMode load_mode); 115 LoadStoreMode(KeyedAccessStoreMode store_mode); 116 KeyedAccessLoadMode load_mode; 117 KeyedAccessStoreMode store_mode; 118 } const load_store_mode_; 119 120 KeyedAccessMode(AccessMode access_mode, KeyedAccessLoadMode load_mode); 121 KeyedAccessMode(AccessMode access_mode, KeyedAccessStoreMode store_mode); 122 }; 123 124 class ElementAccessFeedback : public ProcessedFeedback { 125 public: 126 ElementAccessFeedback(Zone* zone, KeyedAccessMode const& keyed_mode, 127 FeedbackSlotKind slot_kind); 128 129 KeyedAccessMode keyed_mode() const; 130 131 // A transition group is a target and a possibly empty set of sources that can 132 // transition to the target. It is represented as a non-empty vector with the 133 // target at index 0. 134 using TransitionGroup = ZoneVector<Handle<Map>>; 135 ZoneVector<TransitionGroup> const& transition_groups() const; 136 137 bool HasOnlyStringMaps(JSHeapBroker* broker) const; 138 139 void AddGroup(TransitionGroup&& group); 140 141 // Refine {this} by trying to restrict it to the maps in {inferred_maps}. A 142 // transition group's target is kept iff it is in {inferred_maps} or if more 143 // than one of its sources is in {inferred_maps}. Here's an (unrealistic) 144 // example showing all the possible situations: 145 // 146 // inferred_maps = [a0, a2, c1, c2, d1, e0, e1] 147 // 148 // Groups before: Groups after: 149 // [a0, a1, a2] [a0, a2] 150 // [b0] 151 // [c0, c1, c2, c3] [c0, c1, c2] 152 // [d0, d1] [d1] 153 // [e0, e1] [e0, e1] 154 // 155 ElementAccessFeedback const& Refine( 156 ZoneVector<Handle<Map>> const& inferred_maps, Zone* zone) const; 157 158 private: 159 KeyedAccessMode const keyed_mode_; 160 ZoneVector<TransitionGroup> transition_groups_; 161 }; 162 163 class NamedAccessFeedback : public ProcessedFeedback { 164 public: 165 NamedAccessFeedback(NameRef const& name, ZoneVector<Handle<Map>> const& maps, 166 FeedbackSlotKind slot_kind); 167 name()168 NameRef const& name() const { return name_; } maps()169 ZoneVector<Handle<Map>> const& maps() const { return maps_; } 170 171 private: 172 NameRef const name_; 173 ZoneVector<Handle<Map>> const maps_; 174 }; 175 176 class MinimorphicLoadPropertyAccessFeedback : public ProcessedFeedback { 177 public: 178 MinimorphicLoadPropertyAccessFeedback(NameRef const& name, 179 FeedbackSlotKind slot_kind, 180 Handle<Object> handler, 181 ZoneVector<Handle<Map>> const& maps, 182 bool has_migration_target_maps); 183 name()184 NameRef const& name() const { return name_; } is_monomorphic()185 bool is_monomorphic() const { return maps_.size() == 1; } handler()186 Handle<Object> handler() const { return handler_; } maps()187 ZoneVector<Handle<Map>> const& maps() const { return maps_; } has_migration_target_maps()188 bool has_migration_target_maps() const { return has_migration_target_maps_; } 189 190 private: 191 NameRef const name_; 192 Handle<Object> const handler_; 193 ZoneVector<Handle<Map>> const maps_; 194 bool const has_migration_target_maps_; 195 }; 196 197 class CallFeedback : public ProcessedFeedback { 198 public: CallFeedback(base::Optional<HeapObjectRef> target,float frequency,SpeculationMode mode,FeedbackSlotKind slot_kind)199 CallFeedback(base::Optional<HeapObjectRef> target, float frequency, 200 SpeculationMode mode, FeedbackSlotKind slot_kind) 201 : ProcessedFeedback(kCall, slot_kind), 202 target_(target), 203 frequency_(frequency), 204 mode_(mode) {} 205 target()206 base::Optional<HeapObjectRef> target() const { return target_; } frequency()207 float frequency() const { return frequency_; } speculation_mode()208 SpeculationMode speculation_mode() const { return mode_; } 209 210 private: 211 base::Optional<HeapObjectRef> const target_; 212 float const frequency_; 213 SpeculationMode const mode_; 214 }; 215 216 template <class T, ProcessedFeedback::Kind K> 217 class SingleValueFeedback : public ProcessedFeedback { 218 public: SingleValueFeedback(T value,FeedbackSlotKind slot_kind)219 explicit SingleValueFeedback(T value, FeedbackSlotKind slot_kind) 220 : ProcessedFeedback(K, slot_kind), value_(value) { 221 DCHECK( 222 (K == kBinaryOperation && slot_kind == FeedbackSlotKind::kBinaryOp) || 223 (K == kCompareOperation && slot_kind == FeedbackSlotKind::kCompareOp) || 224 (K == kForIn && slot_kind == FeedbackSlotKind::kForIn) || 225 (K == kInstanceOf && slot_kind == FeedbackSlotKind::kInstanceOf) || 226 ((K == kLiteral || K == kRegExpLiteral || K == kTemplateObject) && 227 slot_kind == FeedbackSlotKind::kLiteral)); 228 } 229 value()230 T value() const { return value_; } 231 232 private: 233 T const value_; 234 }; 235 236 class InstanceOfFeedback 237 : public SingleValueFeedback<base::Optional<JSObjectRef>, 238 ProcessedFeedback::kInstanceOf> { 239 using SingleValueFeedback::SingleValueFeedback; 240 }; 241 242 class LiteralFeedback 243 : public SingleValueFeedback<AllocationSiteRef, 244 ProcessedFeedback::kLiteral> { 245 using SingleValueFeedback::SingleValueFeedback; 246 }; 247 248 class RegExpLiteralFeedback 249 : public SingleValueFeedback<JSRegExpRef, 250 ProcessedFeedback::kRegExpLiteral> { 251 using SingleValueFeedback::SingleValueFeedback; 252 }; 253 254 class TemplateObjectFeedback 255 : public SingleValueFeedback<JSArrayRef, 256 ProcessedFeedback::kTemplateObject> { 257 using SingleValueFeedback::SingleValueFeedback; 258 }; 259 260 class BinaryOperationFeedback 261 : public SingleValueFeedback<BinaryOperationHint, 262 ProcessedFeedback::kBinaryOperation> { 263 using SingleValueFeedback::SingleValueFeedback; 264 }; 265 266 class CompareOperationFeedback 267 : public SingleValueFeedback<CompareOperationHint, 268 ProcessedFeedback::kCompareOperation> { 269 using SingleValueFeedback::SingleValueFeedback; 270 }; 271 272 class ForInFeedback 273 : public SingleValueFeedback<ForInHint, ProcessedFeedback::kForIn> { 274 using SingleValueFeedback::SingleValueFeedback; 275 }; 276 277 } // namespace compiler 278 } // namespace internal 279 } // namespace v8 280 281 #endif // V8_COMPILER_PROCESSED_FEEDBACK_H_ 282