type-feedback-vector.h 23.2 KB
Newer Older
1 2 3 4 5 6 7
// Copyright 2014 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_TYPE_FEEDBACK_VECTOR_H_
#define V8_TYPE_FEEDBACK_VECTOR_H_

8 9
#include <vector>

10
#include "src/base/logging.h"
11 12
#include "src/elements-kind.h"
#include "src/objects.h"
13
#include "src/type-hints.h"
14
#include "src/zone/zone-containers.h"
15 16 17 18

namespace v8 {
namespace internal {

19
enum class FeedbackVectorSlotKind {
20 21 22 23 24
  // This kind means that the slot points to the middle of other slot
  // which occupies more than one feedback vector element.
  // There must be no such slots in the system.
  INVALID,

25 26
  CALL_IC,
  LOAD_IC,
27
  LOAD_GLOBAL_IC,
28 29 30
  KEYED_LOAD_IC,
  STORE_IC,
  KEYED_STORE_IC,
31 32
  INTERPRETER_BINARYOP_IC,
  INTERPRETER_COMPARE_IC,
33

34 35 36
  // This is a general purpose slot that occupies one feedback vector element.
  GENERAL,

37 38 39 40 41 42
  KINDS_NUMBER  // Last value indicating number of kinds.
};

std::ostream& operator<<(std::ostream& os, FeedbackVectorSlotKind kind);


43 44
template <typename Derived>
class FeedbackVectorSpecBase {
45
 public:
46
  inline FeedbackVectorSlot AddSlot(FeedbackVectorSlotKind kind);
47

48 49 50
  FeedbackVectorSlot AddCallICSlot() {
    return AddSlot(FeedbackVectorSlotKind::CALL_IC);
  }
51

52 53 54
  FeedbackVectorSlot AddLoadICSlot() {
    return AddSlot(FeedbackVectorSlotKind::LOAD_IC);
  }
55

56 57
  FeedbackVectorSlot AddLoadGlobalICSlot(Handle<String> name) {
    This()->append_name(name);
58 59 60
    return AddSlot(FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
  }

61 62
  FeedbackVectorSlot AddKeyedLoadICSlot() {
    return AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC);
63 64
  }

65 66 67 68 69 70 71 72
  FeedbackVectorSlot AddStoreICSlot() {
    return AddSlot(FeedbackVectorSlotKind::STORE_IC);
  }

  FeedbackVectorSlot AddKeyedStoreICSlot() {
    return AddSlot(FeedbackVectorSlotKind::KEYED_STORE_IC);
  }

73 74 75 76 77 78 79 80
  FeedbackVectorSlot AddInterpreterBinaryOpICSlot() {
    return AddSlot(FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC);
  }

  FeedbackVectorSlot AddInterpreterCompareICSlot() {
    return AddSlot(FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC);
  }

81 82 83
  FeedbackVectorSlot AddGeneralSlot() {
    return AddSlot(FeedbackVectorSlotKind::GENERAL);
  }
84 85 86 87 88 89 90 91 92 93

#ifdef OBJECT_PRINT
  // For gdb debugging.
  void Print();
#endif  // OBJECT_PRINT

  DECLARE_PRINTER(FeedbackVectorSpec)

 private:
  Derived* This() { return static_cast<Derived*>(this); }
94 95 96
};


97 98
class StaticFeedbackVectorSpec
    : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
99
 public:
100
  StaticFeedbackVectorSpec() : slot_count_(0), name_count_(0) {}
101

102
  int slots() const { return slot_count_; }
103

104
  FeedbackVectorSlotKind GetKind(int slot) const {
105
    DCHECK(slot >= 0 && slot < slot_count_);
106
    return kinds_[slot];
107 108
  }

109 110 111 112 113 114 115
  int name_count() const { return name_count_; }

  Handle<String> GetName(int index) const {
    DCHECK(index >= 0 && index < name_count_);
    return names_[index];
  }

116 117
 private:
  friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>;
118

119
  void append(FeedbackVectorSlotKind kind) {
120 121 122 123 124 125 126
    DCHECK(slot_count_ < kMaxLength);
    kinds_[slot_count_++] = kind;
  }

  void append_name(Handle<String> name) {
    DCHECK(name_count_ < kMaxLength);
    names_[name_count_++] = name;
127 128
  }

129
  static const int kMaxLength = 12;
130

131
  int slot_count_;
132
  FeedbackVectorSlotKind kinds_[kMaxLength];
133 134
  int name_count_;
  Handle<String> names_[kMaxLength];
135
};
136 137


138 139
class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
 public:
140
  explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone), names_(zone) {
141
    slot_kinds_.reserve(16);
142
    names_.reserve(8);
143 144
  }

145
  int slots() const { return static_cast<int>(slot_kinds_.size()); }
146

147 148
  FeedbackVectorSlotKind GetKind(int slot) const {
    return static_cast<FeedbackVectorSlotKind>(slot_kinds_.at(slot));
149 150
  }

151 152 153 154
  int name_count() const { return static_cast<int>(names_.size()); }

  Handle<String> GetName(int index) const { return names_.at(index); }

155 156
 private:
  friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
157

158 159
  void append(FeedbackVectorSlotKind kind) {
    slot_kinds_.push_back(static_cast<unsigned char>(kind));
160 161
  }

162 163
  void append_name(Handle<String> name) { names_.push_back(name); }

164
  ZoneVector<unsigned char> slot_kinds_;
165
  ZoneVector<Handle<String>> names_;
166 167 168
};


169
// The shape of the TypeFeedbackMetadata is an array with:
170
// 0: slot_count
171 172
// 1: names table
// 2..N: slot kinds packed into a bit vector
173 174 175 176 177 178 179
//
class TypeFeedbackMetadata : public FixedArray {
 public:
  // Casting.
  static inline TypeFeedbackMetadata* cast(Object* obj);

  static const int kSlotsCountIndex = 0;
180 181 182 183 184 185
  static const int kNamesTableIndex = 1;
  static const int kReservedIndexCount = 2;

  static const int kNameTableEntrySize = 2;
  static const int kNameTableSlotIndex = 0;
  static const int kNameTableNameIndex = 1;
186 187 188 189

  // Returns number of feedback vector elements used by given slot kind.
  static inline int GetSlotSize(FeedbackVectorSlotKind kind);

190 191 192
  // Defines if slots of given kind require "name".
  static inline bool SlotRequiresName(FeedbackVectorSlotKind kind);

193 194
  bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;

195 196 197 198
  bool DiffersFrom(const TypeFeedbackMetadata* other_metadata) const;

  inline bool is_empty() const;

199 200 201 202 203 204
  // Returns number of slots in the vector.
  inline int slot_count() const;

  // Returns slot kind for given slot.
  FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;

205 206 207
  // Returns name for given slot.
  String* GetName(FeedbackVectorSlot slot) const;

208 209 210 211 212 213 214 215 216 217 218 219 220
  template <typename Spec>
  static Handle<TypeFeedbackMetadata> New(Isolate* isolate, const Spec* spec);

#ifdef OBJECT_PRINT
  // For gdb debugging.
  void Print();
#endif  // OBJECT_PRINT

  DECLARE_PRINTER(TypeFeedbackMetadata)

  static const char* Kind2String(FeedbackVectorSlotKind kind);

 private:
221
  static const int kFeedbackVectorSlotKindBits = 5;
222 223 224 225 226 227 228 229 230 231 232 233 234 235
  STATIC_ASSERT(static_cast<int>(FeedbackVectorSlotKind::KINDS_NUMBER) <
                (1 << kFeedbackVectorSlotKindBits));

  void SetKind(FeedbackVectorSlot slot, FeedbackVectorSlotKind kind);

  typedef BitSetComputer<FeedbackVectorSlotKind, kFeedbackVectorSlotKindBits,
                         kSmiValueSize, uint32_t> VectorICComputer;

  DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackMetadata);
};


// The shape of the TypeFeedbackVector is an array with:
// 0: feedback metadata
236 237
// 1: invocation count
// 2: feedback slot #0
238
// ...
239
// 2 + slot_count - 1: feedback slot #(slot_count-1)
240
//
241 242 243
class TypeFeedbackVector : public FixedArray {
 public:
  // Casting.
244
  static inline TypeFeedbackVector* cast(Object* obj);
245

246
  static const int kMetadataIndex = 0;
247 248
  static const int kInvocationCountIndex = 1;
  static const int kReservedIndexCount = 2;
249

250
  inline void ComputeCounts(int* with_type_info, int* generic,
251
                            int* vector_ic_count, bool code_is_interpreted);
252

253 254 255
  inline bool is_empty() const;

  // Returns number of slots in the vector.
256 257 258
  inline int slot_count() const;

  inline TypeFeedbackMetadata* metadata() const;
259
  inline int invocation_count() const;
260

261
  // Conversion from a slot to an integer index to the underlying array.
262 263 264
  static int GetIndex(FeedbackVectorSlot slot) {
    return kReservedIndexCount + slot.ToInt();
  }
265 266
  static int GetIndexFromSpec(const FeedbackVectorSpec* spec,
                              FeedbackVectorSlot slot);
267

268
  // Conversion from an integer index to the underlying array to a slot.
269
  static inline FeedbackVectorSlot ToSlot(int index);
270 271 272
  inline Object* Get(FeedbackVectorSlot slot) const;
  inline void Set(FeedbackVectorSlot slot, Object* value,
                  WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
273

274
  // Returns slot kind for given slot.
275
  FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
276 277
  // Returns name corresponding to given slot or an empty string.
  String* GetName(FeedbackVectorSlot slot) const;
278

279 280
  static Handle<TypeFeedbackVector> New(Isolate* isolate,
                                        Handle<TypeFeedbackMetadata> metadata);
281

282 283 284
  static Handle<TypeFeedbackVector> Copy(Isolate* isolate,
                                         Handle<TypeFeedbackVector> vector);

285 286 287 288 289 290 291
#ifdef OBJECT_PRINT
  // For gdb debugging.
  void Print();
#endif  // OBJECT_PRINT

  DECLARE_PRINTER(TypeFeedbackVector)

292
  // Clears the vector slots.
293
  void ClearSlots(SharedFunctionInfo* shared) { ClearSlotsImpl(shared, true); }
294

295 296 297 298
  void ClearSlotsAtGCTime(SharedFunctionInfo* shared) {
    ClearSlotsImpl(shared, false);
  }

299 300 301
  static void ClearAllKeyedStoreICs(Isolate* isolate);
  void ClearKeyedStoreICs(SharedFunctionInfo* shared);

302
  // The object that indicates an uninitialized cache.
303
  static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
304 305

  // The object that indicates a megamorphic state.
306
  static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
307 308

  // The object that indicates a premonomorphic state.
309
  static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
310 311 312

  // A raw version of the uninitialized sentinel that's safe to read during
  // garbage collection (e.g., for patching the cache).
313
  static inline Symbol* RawUninitializedSentinel(Isolate* isolate);
314

315
  static const int kDummyLoadICSlot = 0;
316 317 318
  static const int kDummyKeyedLoadICSlot = 2;
  static const int kDummyStoreICSlot = 4;
  static const int kDummyKeyedStoreICSlot = 6;
319 320

  static Handle<TypeFeedbackVector> DummyVector(Isolate* isolate);
321
  static FeedbackVectorSlot DummySlot(int dummyIndex) {
322
    DCHECK(dummyIndex >= 0 && dummyIndex <= kDummyKeyedStoreICSlot);
323
    return FeedbackVectorSlot(dummyIndex);
324 325
  }

326
 private:
327
  void ClearSlotsImpl(SharedFunctionInfo* shared, bool force_clear);
328

329 330
  DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackVector);
};
331 332


333 334 335 336 337 338 339 340 341 342 343 344 345 346 347
// The following asserts protect an optimization in type feedback vector
// code that looks into the contents of a slot assuming to find a String,
// a Symbol, an AllocationSite, a WeakCell, or a FixedArray.
STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize);
STATIC_ASSERT(WeakCell::kValueOffset == AllocationSite::kTransitionInfoOffset);
STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset);
STATIC_ASSERT(WeakCell::kValueOffset == Name::kHashFieldSlot);
// Verify that an empty hash field looks like a tagged object, but can't
// possibly be confused with a pointer.
STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag);
STATIC_ASSERT(Name::kEmptyHashField == 0x3);
// Verify that a set hash field will not look like a tagged object.
STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag);


348 349
class TypeFeedbackMetadataIterator {
 public:
350
  explicit TypeFeedbackMetadataIterator(Handle<TypeFeedbackMetadata> metadata)
351
      : metadata_handle_(metadata),
352
        next_slot_(FeedbackVectorSlot(0)),
353 354
        slot_kind_(FeedbackVectorSlotKind::INVALID) {}

355
  explicit TypeFeedbackMetadataIterator(TypeFeedbackMetadata* metadata)
356
      : metadata_(metadata),
357
        next_slot_(FeedbackVectorSlot(0)),
358 359
        slot_kind_(FeedbackVectorSlotKind::INVALID) {}

360
  inline bool HasNext() const;
361

362
  inline FeedbackVectorSlot Next();
363 364 365 366 367 368 369 370 371

  // Returns slot kind of the last slot returned by Next().
  FeedbackVectorSlotKind kind() const {
    DCHECK_NE(FeedbackVectorSlotKind::INVALID, slot_kind_);
    DCHECK_NE(FeedbackVectorSlotKind::KINDS_NUMBER, slot_kind_);
    return slot_kind_;
  }

  // Returns entry size of the last slot returned by Next().
372
  inline int entry_size() const;
373

374 375 376 377 378
  String* name() const {
    DCHECK(TypeFeedbackMetadata::SlotRequiresName(kind()));
    return metadata()->GetName(cur_slot_);
  }

379
 private:
380
  TypeFeedbackMetadata* metadata() const {
381 382 383 384 385 386
    return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_;
  }

  // The reason for having a handle and a raw pointer to the meta data is
  // to have a single iterator implementation for both "handlified" and raw
  // pointer use cases.
387 388
  Handle<TypeFeedbackMetadata> metadata_handle_;
  TypeFeedbackMetadata* metadata_;
389 390
  FeedbackVectorSlot cur_slot_;
  FeedbackVectorSlot next_slot_;
391 392 393 394
  FeedbackVectorSlotKind slot_kind_;
};


395 396 397 398
// A FeedbackNexus is the combination of a TypeFeedbackVector and a slot.
// Derived classes customize the update and retrieval of feedback.
class FeedbackNexus {
 public:
399
  FeedbackNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
400
      : vector_handle_(vector), vector_(NULL), slot_(slot) {}
401
  FeedbackNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
402 403 404 405 406 407 408 409 410 411
      : vector_(vector), slot_(slot) {}
  virtual ~FeedbackNexus() {}

  Handle<TypeFeedbackVector> vector_handle() const {
    DCHECK(vector_ == NULL);
    return vector_handle_;
  }
  TypeFeedbackVector* vector() const {
    return vector_handle_.is_null() ? vector_ : *vector_handle_;
  }
412
  FeedbackVectorSlot slot() const { return slot_; }
413 414

  InlineCacheState ic_state() const { return StateFromFeedback(); }
415
  bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; }
416 417 418 419 420 421 422
  Map* FindFirstMap() const {
    MapHandleList maps;
    ExtractMaps(&maps);
    if (maps.length() > 0) return *maps.at(0);
    return NULL;
  }

423 424 425
  // TODO(mvstanton): remove FindAllMaps, it didn't survive a code review.
  void FindAllMaps(MapHandleList* maps) const { ExtractMaps(maps); }

426
  virtual InlineCacheState StateFromFeedback() const = 0;
427
  virtual int ExtractMaps(MapHandleList* maps) const;
428 429 430
  virtual MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const;
  virtual bool FindHandlers(List<Handle<Object>>* code_list,
                            int length = -1) const;
431 432
  virtual Name* FindFirstName() const { return NULL; }

433 434 435 436
  virtual void ConfigureUninitialized();
  virtual void ConfigurePremonomorphic();
  virtual void ConfigureMegamorphic();

437 438
  inline Object* GetFeedback() const;
  inline Object* GetFeedbackExtra() const;
439

440
  inline Isolate* GetIsolate() const;
441

442
 protected:
443 444 445 446
  inline void SetFeedback(Object* feedback,
                          WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
  inline void SetFeedbackExtra(Object* feedback_extra,
                               WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
447

448
  Handle<FixedArray> EnsureArrayOfSize(int length);
449 450
  Handle<FixedArray> EnsureExtraArrayOfSize(int length);
  void InstallHandlers(Handle<FixedArray> array, MapHandleList* maps,
451
                       List<Handle<Object>>* handlers);
452 453 454 455 456 457 458 459

 private:
  // The reason for having a vector handle and a raw pointer is that we can and
  // should use handles during IC miss, but not during GC when we clear ICs. If
  // you have a handle to the vector that is better because more operations can
  // be done, like allocation.
  Handle<TypeFeedbackVector> vector_handle_;
  TypeFeedbackVector* vector_;
460
  FeedbackVectorSlot slot_;
461 462 463
};


464
class CallICNexus final : public FeedbackNexus {
465
 public:
466
  CallICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
467
      : FeedbackNexus(vector, slot) {
468
    DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot));
469
  }
470
  CallICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
471
      : FeedbackNexus(vector, slot) {
472
    DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot));
473 474
  }

475 476
  void Clear(Code* host);

477
  void ConfigureUninitialized() override;
478 479
  void ConfigureMonomorphicArray();
  void ConfigureMonomorphic(Handle<JSFunction> function);
480 481
  void ConfigureMegamorphic() final;
  void ConfigureMegamorphic(int call_count);
482

483
  InlineCacheState StateFromFeedback() const final;
484

485
  int ExtractMaps(MapHandleList* maps) const final {
486 487 488
    // CallICs don't record map feedback.
    return 0;
  }
489
  MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
490 491
    return MaybeHandle<Code>();
  }
492 493
  bool FindHandlers(List<Handle<Object>>* code_list,
                    int length = -1) const final {
494 495
    return length == 0;
  }
496 497

  int ExtractCallCount();
498 499 500 501

  // Compute the call frequency based on the call count and the invocation
  // count (taken from the type feedback vector).
  float ComputeCallFrequency();
502
};
503 504 505 506


class LoadICNexus : public FeedbackNexus {
 public:
507
  LoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
508
      : FeedbackNexus(vector, slot) {
509
    DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot));
510
  }
511
  explicit LoadICNexus(Isolate* isolate)
512 513 514 515
      : FeedbackNexus(
            TypeFeedbackVector::DummyVector(isolate),
            FeedbackVectorSlot(TypeFeedbackVector::kDummyLoadICSlot)) {}
  LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
516
      : FeedbackNexus(vector, slot) {
517
    DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot));
518 519 520 521
  }

  void Clear(Code* host);

522
  void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler);
523

524 525
  void ConfigurePolymorphic(MapHandleList* maps,
                            List<Handle<Object>>* handlers);
526

527
  InlineCacheState StateFromFeedback() const override;
528 529
};

530 531 532 533 534 535 536 537 538 539 540
class LoadGlobalICNexus : public FeedbackNexus {
 public:
  LoadGlobalICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
      : FeedbackNexus(vector, slot) {
    DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, vector->GetKind(slot));
  }
  LoadGlobalICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
      : FeedbackNexus(vector, slot) {
    DCHECK_EQ(FeedbackVectorSlotKind::LOAD_GLOBAL_IC, vector->GetKind(slot));
  }

541 542 543 544
  int ExtractMaps(MapHandleList* maps) const final {
    // LoadGlobalICs don't record map feedback.
    return 0;
  }
545
  MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
546 547
    return MaybeHandle<Code>();
  }
548 549
  bool FindHandlers(List<Handle<Object>>* code_list,
                    int length = -1) const final {
550 551 552
    return length == 0;
  }

553 554 555
  void ConfigureMegamorphic() override { UNREACHABLE(); }
  void Clear(Code* host);

556 557 558 559
  void ConfigureUninitialized() override;
  void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
  void ConfigureHandlerMode(Handle<Code> handler);

560 561
  InlineCacheState StateFromFeedback() const override;
};
562 563 564

class KeyedLoadICNexus : public FeedbackNexus {
 public:
565
  KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
566
      : FeedbackNexus(vector, slot) {
567
    DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot));
568
  }
569 570 571 572
  explicit KeyedLoadICNexus(Isolate* isolate)
      : FeedbackNexus(
            TypeFeedbackVector::DummyVector(isolate),
            FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedLoadICSlot)) {}
573
  KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
574
      : FeedbackNexus(vector, slot) {
575
    DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot));
576 577 578 579
  }

  void Clear(Code* host);

580 581
  // name can be a null handle for element loads.
  void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
582
                            Handle<Object> handler);
583 584
  // name can be null.
  void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
585
                            List<Handle<Object>>* handlers);
586

587 588 589
  void ConfigureMegamorphicKeyed(IcCheckType property_type);

  IcCheckType GetKeyType() const;
590 591 592 593 594 595 596
  InlineCacheState StateFromFeedback() const override;
  Name* FindFirstName() const override;
};


class StoreICNexus : public FeedbackNexus {
 public:
597
  StoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
598
      : FeedbackNexus(vector, slot) {
599
    DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot));
600
  }
601
  explicit StoreICNexus(Isolate* isolate)
602 603 604 605
      : FeedbackNexus(
            TypeFeedbackVector::DummyVector(isolate),
            FeedbackVectorSlot(TypeFeedbackVector::kDummyStoreICSlot)) {}
  StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
606
      : FeedbackNexus(vector, slot) {
607
    DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot));
608 609 610 611 612 613
  }

  void Clear(Code* host);

  void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Code> handler);

614 615
  void ConfigurePolymorphic(MapHandleList* maps,
                            List<Handle<Object>>* handlers);
616 617 618 619 620 621 622

  InlineCacheState StateFromFeedback() const override;
};


class KeyedStoreICNexus : public FeedbackNexus {
 public:
623
  KeyedStoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
624
      : FeedbackNexus(vector, slot) {
625
    DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot));
626
  }
627
  explicit KeyedStoreICNexus(Isolate* isolate)
628 629 630 631
      : FeedbackNexus(
            TypeFeedbackVector::DummyVector(isolate),
            FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)) {}
  KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
632
      : FeedbackNexus(vector, slot) {
633
    DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot));
634 635 636 637
  }

  void Clear(Code* host);

638
  // name can be a null handle for element loads.
639
  void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
640 641
                            Handle<Code> handler);
  // name can be null.
642
  void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
643
                            List<Handle<Object>>* handlers);
644 645 646
  void ConfigurePolymorphic(MapHandleList* maps,
                            MapHandleList* transitioned_maps,
                            CodeHandleList* handlers);
647
  void ConfigureMegamorphicKeyed(IcCheckType property_type);
648 649 650

  KeyedAccessStoreMode GetKeyedAccessStoreMode() const;
  IcCheckType GetKeyType() const;
651

652 653
  InlineCacheState StateFromFeedback() const override;
  Name* FindFirstName() const override;
654
};
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720

class BinaryOpICNexus final : public FeedbackNexus {
 public:
  BinaryOpICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
      : FeedbackNexus(vector, slot) {
    DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC,
              vector->GetKind(slot));
  }
  BinaryOpICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
      : FeedbackNexus(vector, slot) {
    DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_BINARYOP_IC,
              vector->GetKind(slot));
  }

  void Clear(Code* host);

  InlineCacheState StateFromFeedback() const final;
  BinaryOperationHint GetBinaryOperationFeedback() const;

  int ExtractMaps(MapHandleList* maps) const final {
    // BinaryOpICs don't record map feedback.
    return 0;
  }
  MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
    return MaybeHandle<Code>();
  }
  bool FindHandlers(List<Handle<Object>>* code_list,
                    int length = -1) const final {
    return length == 0;
  }
};

class CompareICNexus final : public FeedbackNexus {
 public:
  CompareICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
      : FeedbackNexus(vector, slot) {
    DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC,
              vector->GetKind(slot));
  }
  CompareICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
      : FeedbackNexus(vector, slot) {
    DCHECK_EQ(FeedbackVectorSlotKind::INTERPRETER_COMPARE_IC,
              vector->GetKind(slot));
  }

  void Clear(Code* host);

  InlineCacheState StateFromFeedback() const final;
  CompareOperationHint GetCompareOperationFeedback() const;

  int ExtractMaps(MapHandleList* maps) const final {
    // BinaryOpICs don't record map feedback.
    return 0;
  }
  MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
    return MaybeHandle<Code>();
  }
  bool FindHandlers(List<Handle<Object>>* code_list,
                    int length = -1) const final {
    return length == 0;
  }
};

inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback);
inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback);

721 722
}  // namespace internal
}  // namespace v8
723 724

#endif  // V8_TRANSITIONS_H_