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