• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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