processed-feedback.h 8.84 KB
Newer Older
1 2 3 4 5 6 7
// 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_

8
#include "src/compiler/feedback-source.h"
9 10 11 12 13 14 15 16 17 18 19 20 21
#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;
22
class LiteralFeedback;
23
class MinimorphicLoadPropertyAccessFeedback;
24
class NamedAccessFeedback;
25 26
class RegExpLiteralFeedback;
class TemplateObjectFeedback;
27 28 29 30 31 32 33 34 35 36 37 38

class ProcessedFeedback : public ZoneObject {
 public:
  enum Kind {
    kInsufficient,
    kBinaryOperation,
    kCall,
    kCompareOperation,
    kElementAccess,
    kForIn,
    kGlobalAccess,
    kInstanceOf,
39
    kLiteral,
40
    kMinimorphicPropertyAccess,
41
    kNamedAccess,
42 43
    kRegExpLiteral,
    kTemplateObject,
44 45 46
  };
  Kind kind() const { return kind_; }

47
  FeedbackSlotKind slot_kind() const { return slot_kind_; }
48 49 50 51 52 53 54 55 56 57
  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;
58 59
  MinimorphicLoadPropertyAccessFeedback const& AsMinimorphicPropertyAccess()
      const;
60 61 62
  LiteralFeedback const& AsLiteral() const;
  RegExpLiteralFeedback const& AsRegExpLiteral() const;
  TemplateObjectFeedback const& AsTemplateObject() const;
63 64

 protected:
65
  ProcessedFeedback(Kind kind, FeedbackSlotKind slot_kind);
66 67 68

 private:
  Kind const kind_;
69
  FeedbackSlotKind const slot_kind_;
70 71 72 73
};

class InsufficientFeedback final : public ProcessedFeedback {
 public:
74
  explicit InsufficientFeedback(FeedbackSlotKind slot_kind);
75 76 77 78
};

class GlobalAccessFeedback : public ProcessedFeedback {
 public:
79
  GlobalAccessFeedback(PropertyCellRef cell, FeedbackSlotKind slot_kind);
80
  GlobalAccessFeedback(ContextRef script_context, int slot_index,
81 82
                       bool immutable, FeedbackSlotKind slot_kind);
  explicit GlobalAccessFeedback(FeedbackSlotKind slot_kind);  // Megamorphic
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

  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:
126 127
  ElementAccessFeedback(Zone* zone, KeyedAccessMode const& keyed_mode,
                        FeedbackSlotKind slot_kind);
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

  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:
165 166
  NamedAccessFeedback(NameRef const& name, ZoneVector<Handle<Map>> const& maps,
                      FeedbackSlotKind slot_kind);
167 168 169 170 171 172 173 174 175

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

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

176 177 178 179 180
class MinimorphicLoadPropertyAccessFeedback : public ProcessedFeedback {
 public:
  MinimorphicLoadPropertyAccessFeedback(NameRef const& name,
                                        FeedbackSlotKind slot_kind,
                                        bool is_monomorphic,
181 182
                                        Handle<Object> handler,
                                        bool has_migration_target_maps);
183 184 185 186

  NameRef const& name() const { return name_; }
  bool is_monomorphic() const { return is_monomorphic_; }
  Handle<Object> handler() const { return handler_; }
187
  bool has_migration_target_maps() const { return has_migration_target_maps_; }
188 189 190

 private:
  NameRef const name_;
191 192 193
  bool const is_monomorphic_;
  Handle<Object> const handler_;
  bool const has_migration_target_maps_;
194 195
};

196 197 198
class CallFeedback : public ProcessedFeedback {
 public:
  CallFeedback(base::Optional<HeapObjectRef> target, float frequency,
199 200
               SpeculationMode mode, FeedbackSlotKind slot_kind)
      : ProcessedFeedback(kCall, slot_kind),
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
        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:
218 219 220 221 222 223
  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) ||
224 225 226
        (K == kInstanceOf && slot_kind == FeedbackSlotKind::kInstanceOf) ||
        ((K == kLiteral || K == kRegExpLiteral || K == kTemplateObject) &&
         slot_kind == FeedbackSlotKind::kLiteral));
227
  }
228 229 230 231 232 233 234 235 236 237 238 239 240

  T value() const { return value_; }

 private:
  T const value_;
};

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

241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
class LiteralFeedback
    : public SingleValueFeedback<AllocationSiteRef,
                                 ProcessedFeedback::kLiteral> {
  using SingleValueFeedback::SingleValueFeedback;
};

class RegExpLiteralFeedback
    : public SingleValueFeedback<JSRegExpRef,
                                 ProcessedFeedback::kRegExpLiteral> {
  using SingleValueFeedback::SingleValueFeedback;
};

class TemplateObjectFeedback
    : public SingleValueFeedback<JSArrayRef,
                                 ProcessedFeedback::kTemplateObject> {
  using SingleValueFeedback::SingleValueFeedback;
};

259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
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_