summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/processed-feedback.h
blob: 17829863de1a091b6f228d94c4dfe659e71cfec0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// Copyright 2019 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_COMPILER_PROCESSED_FEEDBACK_H_
#define V8_COMPILER_PROCESSED_FEEDBACK_H_

#include "src/compiler/heap-refs.h"

namespace v8 {
namespace internal {
namespace compiler {

class BinaryOperationFeedback;
class CallFeedback;
class CompareOperationFeedback;
class ElementAccessFeedback;
class ForInFeedback;
class GlobalAccessFeedback;
class InstanceOfFeedback;
class NamedAccessFeedback;

class ProcessedFeedback : public ZoneObject {
 public:
  enum Kind {
    kInsufficient,
    kBinaryOperation,
    kCall,
    kCompareOperation,
    kElementAccess,
    kForIn,
    kGlobalAccess,
    kInstanceOf,
    kNamedAccess,
  };
  Kind kind() const { return kind_; }

  FeedbackSlotKind slot_kind() const { return slot_kind_; }
  bool IsInsufficient() const { return kind() == kInsufficient; }

  BinaryOperationFeedback const& AsBinaryOperation() const;
  CallFeedback const& AsCall() const;
  CompareOperationFeedback const& AsCompareOperation() const;
  ElementAccessFeedback const& AsElementAccess() const;
  ForInFeedback const& AsForIn() const;
  GlobalAccessFeedback const& AsGlobalAccess() const;
  InstanceOfFeedback const& AsInstanceOf() const;
  NamedAccessFeedback const& AsNamedAccess() const;

 protected:
  ProcessedFeedback(Kind kind, FeedbackSlotKind slot_kind);

 private:
  Kind const kind_;
  FeedbackSlotKind const slot_kind_;
};

class InsufficientFeedback final : public ProcessedFeedback {
 public:
  explicit InsufficientFeedback(FeedbackSlotKind slot_kind);
};

class GlobalAccessFeedback : public ProcessedFeedback {
 public:
  GlobalAccessFeedback(PropertyCellRef cell, FeedbackSlotKind slot_kind);
  GlobalAccessFeedback(ContextRef script_context, int slot_index,
                       bool immutable, FeedbackSlotKind slot_kind);
  explicit GlobalAccessFeedback(FeedbackSlotKind slot_kind);  // Megamorphic

  bool IsMegamorphic() const;

  bool IsPropertyCell() const;
  PropertyCellRef property_cell() const;

  bool IsScriptContextSlot() const;
  ContextRef script_context() const;
  int slot_index() const;
  bool immutable() const;

  base::Optional<ObjectRef> GetConstantHint() const;

 private:
  base::Optional<ObjectRef> const cell_or_context_;
  int const index_and_immutable_;
};

class KeyedAccessMode {
 public:
  static KeyedAccessMode FromNexus(FeedbackNexus const& nexus);

  AccessMode access_mode() const;
  bool IsLoad() const;
  bool IsStore() const;
  KeyedAccessLoadMode load_mode() const;
  KeyedAccessStoreMode store_mode() const;

 private:
  AccessMode const access_mode_;
  union LoadStoreMode {
    LoadStoreMode(KeyedAccessLoadMode load_mode);
    LoadStoreMode(KeyedAccessStoreMode store_mode);
    KeyedAccessLoadMode load_mode;
    KeyedAccessStoreMode store_mode;
  } const load_store_mode_;

  KeyedAccessMode(AccessMode access_mode, KeyedAccessLoadMode load_mode);
  KeyedAccessMode(AccessMode access_mode, KeyedAccessStoreMode store_mode);
};

class ElementAccessFeedback : public ProcessedFeedback {
 public:
  ElementAccessFeedback(Zone* zone, KeyedAccessMode const& keyed_mode,
                        FeedbackSlotKind slot_kind);

  KeyedAccessMode keyed_mode() const;

  // A transition group is a target and a possibly empty set of sources that can
  // transition to the target. It is represented as a non-empty vector with the
  // target at index 0.
  using TransitionGroup = ZoneVector<Handle<Map>>;
  ZoneVector<TransitionGroup> const& transition_groups() const;

  bool HasOnlyStringMaps(JSHeapBroker* broker) const;

  void AddGroup(TransitionGroup&& group);

  // Refine {this} by trying to restrict it to the maps in {inferred_maps}. A
  // transition group's target is kept iff it is in {inferred_maps} or if more
  // than one of its sources is in {inferred_maps}. Here's an (unrealistic)
  // example showing all the possible situations:
  //
  // inferred_maps = [a0, a2, c1, c2, d1, e0, e1]
  //
  // Groups before:                     Groups after:
  // [a0, a1, a2]                       [a0, a2]
  // [b0]
  // [c0, c1, c2, c3]                   [c0, c1, c2]
  // [d0, d1]                           [d1]
  // [e0, e1]                           [e0, e1]
  //
  ElementAccessFeedback const& Refine(
      ZoneVector<Handle<Map>> const& inferred_maps, Zone* zone) const;

 private:
  KeyedAccessMode const keyed_mode_;
  ZoneVector<TransitionGroup> transition_groups_;
};

class NamedAccessFeedback : public ProcessedFeedback {
 public:
  NamedAccessFeedback(NameRef const& name, ZoneVector<Handle<Map>> const& maps,
                      FeedbackSlotKind slot_kind);

  NameRef const& name() const { return name_; }
  ZoneVector<Handle<Map>> const& maps() const { return maps_; }

 private:
  NameRef const name_;
  ZoneVector<Handle<Map>> const maps_;
};

class CallFeedback : public ProcessedFeedback {
 public:
  CallFeedback(base::Optional<HeapObjectRef> target, float frequency,
               SpeculationMode mode, FeedbackSlotKind slot_kind)
      : ProcessedFeedback(kCall, slot_kind),
        target_(target),
        frequency_(frequency),
        mode_(mode) {}

  base::Optional<HeapObjectRef> target() const { return target_; }
  float frequency() const { return frequency_; }
  SpeculationMode speculation_mode() const { return mode_; }

 private:
  base::Optional<HeapObjectRef> const target_;
  float const frequency_;
  SpeculationMode const mode_;
};

template <class T, ProcessedFeedback::Kind K>
class SingleValueFeedback : public ProcessedFeedback {
 public:
  explicit SingleValueFeedback(T value, FeedbackSlotKind slot_kind)
      : ProcessedFeedback(K, slot_kind), value_(value) {
    DCHECK(
        (K == kBinaryOperation && slot_kind == FeedbackSlotKind::kBinaryOp) ||
        (K == kCompareOperation && slot_kind == FeedbackSlotKind::kCompareOp) ||
        (K == kForIn && slot_kind == FeedbackSlotKind::kForIn) ||
        (K == kInstanceOf && slot_kind == FeedbackSlotKind::kInstanceOf));
  }

  T value() const { return value_; }

 private:
  T const value_;
};

class InstanceOfFeedback
    : public SingleValueFeedback<base::Optional<JSObjectRef>,
                                 ProcessedFeedback::kInstanceOf> {
  using SingleValueFeedback::SingleValueFeedback;
};

class BinaryOperationFeedback
    : public SingleValueFeedback<BinaryOperationHint,
                                 ProcessedFeedback::kBinaryOperation> {
  using SingleValueFeedback::SingleValueFeedback;
};

class CompareOperationFeedback
    : public SingleValueFeedback<CompareOperationHint,
                                 ProcessedFeedback::kCompareOperation> {
  using SingleValueFeedback::SingleValueFeedback;
};

class ForInFeedback
    : public SingleValueFeedback<ForInHint, ProcessedFeedback::kForIn> {
  using SingleValueFeedback::SingleValueFeedback;
};

}  // namespace compiler
}  // namespace internal
}  // namespace v8

#endif  // V8_COMPILER_PROCESSED_FEEDBACK_H_