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 11namespace v8 { 12namespace internal { 13namespace compiler { 14 15class BinaryOperationFeedback; 16class CallFeedback; 17class CompareOperationFeedback; 18class ElementAccessFeedback; 19class ForInFeedback; 20class GlobalAccessFeedback; 21class InstanceOfFeedback; 22class LiteralFeedback; 23class NamedAccessFeedback; 24class RegExpLiteralFeedback; 25class TemplateObjectFeedback; 26 27class 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 }; 43 Kind kind() const { return kind_; } 44 45 FeedbackSlotKind slot_kind() const { return slot_kind_; } 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 68class InsufficientFeedback final : public ProcessedFeedback { 69 public: 70 explicit InsufficientFeedback(FeedbackSlotKind slot_kind); 71}; 72 73class 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 97class 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 120class 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 159class NamedAccessFeedback : public ProcessedFeedback { 160 public: 161 NamedAccessFeedback(NameRef const& name, ZoneVector<MapRef> const& maps, 162 FeedbackSlotKind slot_kind); 163 164 NameRef const& name() const { return name_; } 165 ZoneVector<MapRef> const& maps() const { return maps_; } 166 167 private: 168 NameRef const name_; 169 ZoneVector<MapRef> const maps_; 170}; 171 172class CallFeedback : public ProcessedFeedback { 173 public: 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 183 base::Optional<HeapObjectRef> target() const { return target_; } 184 float frequency() const { return frequency_; } 185 SpeculationMode speculation_mode() const { return mode_; } 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 195template <class T, ProcessedFeedback::Kind K> 196class SingleValueFeedback : public ProcessedFeedback { 197 public: 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 209 T value() const { return value_; } 210 211 private: 212 T const value_; 213}; 214 215class InstanceOfFeedback 216 : public SingleValueFeedback<base::Optional<JSObjectRef>, 217 ProcessedFeedback::kInstanceOf> { 218 using SingleValueFeedback::SingleValueFeedback; 219}; 220 221class LiteralFeedback 222 : public SingleValueFeedback<AllocationSiteRef, 223 ProcessedFeedback::kLiteral> { 224 using SingleValueFeedback::SingleValueFeedback; 225}; 226 227class RegExpLiteralFeedback 228 : public SingleValueFeedback<RegExpBoilerplateDescriptionRef, 229 ProcessedFeedback::kRegExpLiteral> { 230 using SingleValueFeedback::SingleValueFeedback; 231}; 232 233class TemplateObjectFeedback 234 : public SingleValueFeedback<JSArrayRef, 235 ProcessedFeedback::kTemplateObject> { 236 using SingleValueFeedback::SingleValueFeedback; 237}; 238 239class BinaryOperationFeedback 240 : public SingleValueFeedback<BinaryOperationHint, 241 ProcessedFeedback::kBinaryOperation> { 242 using SingleValueFeedback::SingleValueFeedback; 243}; 244 245class CompareOperationFeedback 246 : public SingleValueFeedback<CompareOperationHint, 247 ProcessedFeedback::kCompareOperation> { 248 using SingleValueFeedback::SingleValueFeedback; 249}; 250 251class 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