• 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 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