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