type-feedback-vector.h 20.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/zone-containers.h"
14 15 16 17

namespace v8 {
namespace internal {

18
enum class FeedbackVectorSlotKind {
19 20 21 22 23
  // 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,

24 25
  CALL_IC,
  LOAD_IC,
26
  LOAD_GLOBAL_IC,
27 28 29 30
  KEYED_LOAD_IC,
  STORE_IC,
  KEYED_STORE_IC,

31 32 33
  // This is a general purpose slot that occupies one feedback vector element.
  GENERAL,

34 35 36 37 38 39
  KINDS_NUMBER  // Last value indicating number of kinds.
};

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


40 41
template <typename Derived>
class FeedbackVectorSpecBase {
42
 public:
43
  inline FeedbackVectorSlot AddSlot(FeedbackVectorSlotKind kind);
44

45 46 47
  FeedbackVectorSlot AddCallICSlot() {
    return AddSlot(FeedbackVectorSlotKind::CALL_IC);
  }
48

49 50 51
  FeedbackVectorSlot AddLoadICSlot() {
    return AddSlot(FeedbackVectorSlotKind::LOAD_IC);
  }
52

53 54
  FeedbackVectorSlot AddLoadGlobalICSlot(Handle<String> name) {
    This()->append_name(name);
55 56 57
    return AddSlot(FeedbackVectorSlotKind::LOAD_GLOBAL_IC);
  }

58 59
  FeedbackVectorSlot AddKeyedLoadICSlot() {
    return AddSlot(FeedbackVectorSlotKind::KEYED_LOAD_IC);
60 61
  }

62 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);
  }

  FeedbackVectorSlot AddGeneralSlot() {
    return AddSlot(FeedbackVectorSlotKind::GENERAL);
  }
73 74 75 76 77 78 79 80 81 82

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

  DECLARE_PRINTER(FeedbackVectorSpec)

 private:
  Derived* This() { return static_cast<Derived*>(this); }
83 84 85
};


86 87
class StaticFeedbackVectorSpec
    : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> {
88
 public:
89
  StaticFeedbackVectorSpec() : slot_count_(0), name_count_(0) {}
90

91
  int slots() const { return slot_count_; }
92

93
  FeedbackVectorSlotKind GetKind(int slot) const {
94
    DCHECK(slot >= 0 && slot < slot_count_);
95
    return kinds_[slot];
96 97
  }

98 99 100 101 102 103 104
  int name_count() const { return name_count_; }

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

105 106
 private:
  friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>;
107

108
  void append(FeedbackVectorSlotKind kind) {
109 110 111 112 113 114 115
    DCHECK(slot_count_ < kMaxLength);
    kinds_[slot_count_++] = kind;
  }

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

118
  static const int kMaxLength = 12;
119

120
  int slot_count_;
121
  FeedbackVectorSlotKind kinds_[kMaxLength];
122 123
  int name_count_;
  Handle<String> names_[kMaxLength];
124
};
125 126


127 128
class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> {
 public:
129
  explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone), names_(zone) {
130
    slot_kinds_.reserve(16);
131
    names_.reserve(8);
132 133
  }

134
  int slots() const { return static_cast<int>(slot_kinds_.size()); }
135

136 137
  FeedbackVectorSlotKind GetKind(int slot) const {
    return static_cast<FeedbackVectorSlotKind>(slot_kinds_.at(slot));
138 139
  }

140 141 142 143
  int name_count() const { return static_cast<int>(names_.size()); }

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

144 145
 private:
  friend class FeedbackVectorSpecBase<FeedbackVectorSpec>;
146

147 148
  void append(FeedbackVectorSlotKind kind) {
    slot_kinds_.push_back(static_cast<unsigned char>(kind));
149 150
  }

151 152
  void append_name(Handle<String> name) { names_.push_back(name); }

153
  ZoneVector<unsigned char> slot_kinds_;
154
  ZoneVector<Handle<String>> names_;
155 156 157
};


158
// The shape of the TypeFeedbackMetadata is an array with:
159
// 0: slot_count
160 161
// 1: names table
// 2..N: slot kinds packed into a bit vector
162 163 164 165 166 167 168
//
class TypeFeedbackMetadata : public FixedArray {
 public:
  // Casting.
  static inline TypeFeedbackMetadata* cast(Object* obj);

  static const int kSlotsCountIndex = 0;
169 170 171 172 173 174
  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;
175 176 177 178

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

179 180 181
  // Defines if slots of given kind require "name".
  static inline bool SlotRequiresName(FeedbackVectorSlotKind kind);

182 183
  bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const;

184 185 186 187
  bool DiffersFrom(const TypeFeedbackMetadata* other_metadata) const;

  inline bool is_empty() const;

188 189 190 191 192 193
  // Returns number of slots in the vector.
  inline int slot_count() const;

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

194 195 196
  // Returns name for given slot.
  String* GetName(FeedbackVectorSlot slot) const;

197 198 199 200 201 202 203 204 205 206 207 208 209
  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:
210
  static const int kFeedbackVectorSlotKindBits = 4;
211 212 213 214 215 216 217 218 219 220 221 222 223 224
  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
225 226
// 1: ics_with_types
// 2: ics_with_generic_info
227
// 3: feedback slot #0
228
// ...
229
// 3 + slot_count - 1: feedback slot #(slot_count-1)
230
//
231 232 233
class TypeFeedbackVector : public FixedArray {
 public:
  // Casting.
234
  static inline TypeFeedbackVector* cast(Object* obj);
235

236
  static const int kMetadataIndex = 0;
237 238 239
  static const int kReservedIndexCount = 1;

  inline void ComputeCounts(int* with_type_info, int* generic);
240

241 242 243
  inline bool is_empty() const;

  // Returns number of slots in the vector.
244 245 246
  inline int slot_count() const;

  inline TypeFeedbackMetadata* metadata() const;
247

248
  // Conversion from a slot to an integer index to the underlying array.
249 250 251
  static int GetIndex(FeedbackVectorSlot slot) {
    return kReservedIndexCount + slot.ToInt();
  }
252 253
  static int GetIndexFromSpec(const FeedbackVectorSpec* spec,
                              FeedbackVectorSlot slot);
254

255
  // Conversion from an integer index to the underlying array to a slot.
256
  static inline FeedbackVectorSlot ToSlot(int index);
257 258 259
  inline Object* Get(FeedbackVectorSlot slot) const;
  inline void Set(FeedbackVectorSlot slot, Object* value,
                  WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
260

261
  // Returns slot kind for given slot.
262
  FeedbackVectorSlotKind GetKind(FeedbackVectorSlot slot) const;
263 264
  // Returns name corresponding to given slot or an empty string.
  String* GetName(FeedbackVectorSlot slot) const;
265

266 267
  static Handle<TypeFeedbackVector> New(Isolate* isolate,
                                        Handle<TypeFeedbackMetadata> metadata);
268

269 270 271
  static Handle<TypeFeedbackVector> Copy(Isolate* isolate,
                                         Handle<TypeFeedbackVector> vector);

272 273 274 275 276 277 278
#ifdef OBJECT_PRINT
  // For gdb debugging.
  void Print();
#endif  // OBJECT_PRINT

  DECLARE_PRINTER(TypeFeedbackVector)

279
  // Clears the vector slots.
280
  void ClearSlots(SharedFunctionInfo* shared) { ClearSlotsImpl(shared, true); }
281

282 283 284 285
  void ClearSlotsAtGCTime(SharedFunctionInfo* shared) {
    ClearSlotsImpl(shared, false);
  }

286 287 288
  static void ClearAllKeyedStoreICs(Isolate* isolate);
  void ClearKeyedStoreICs(SharedFunctionInfo* shared);

289
  // The object that indicates an uninitialized cache.
290
  static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate);
291 292

  // The object that indicates a megamorphic state.
293
  static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate);
294 295

  // The object that indicates a premonomorphic state.
296
  static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate);
297 298 299

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

302
  static const int kDummyLoadICSlot = 0;
303 304 305
  static const int kDummyKeyedLoadICSlot = 2;
  static const int kDummyStoreICSlot = 4;
  static const int kDummyKeyedStoreICSlot = 6;
306 307

  static Handle<TypeFeedbackVector> DummyVector(Isolate* isolate);
308
  static FeedbackVectorSlot DummySlot(int dummyIndex) {
309
    DCHECK(dummyIndex >= 0 && dummyIndex <= kDummyKeyedStoreICSlot);
310
    return FeedbackVectorSlot(dummyIndex);
311 312
  }

313
 private:
314
  void ClearSlotsImpl(SharedFunctionInfo* shared, bool force_clear);
315

316 317
  DISALLOW_IMPLICIT_CONSTRUCTORS(TypeFeedbackVector);
};
318 319


320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
// 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);


335 336
class TypeFeedbackMetadataIterator {
 public:
337
  explicit TypeFeedbackMetadataIterator(Handle<TypeFeedbackMetadata> metadata)
338
      : metadata_handle_(metadata),
339
        next_slot_(FeedbackVectorSlot(0)),
340 341
        slot_kind_(FeedbackVectorSlotKind::INVALID) {}

342
  explicit TypeFeedbackMetadataIterator(TypeFeedbackMetadata* metadata)
343
      : metadata_(metadata),
344
        next_slot_(FeedbackVectorSlot(0)),
345 346
        slot_kind_(FeedbackVectorSlotKind::INVALID) {}

347
  inline bool HasNext() const;
348

349
  inline FeedbackVectorSlot Next();
350 351 352 353 354 355 356 357 358

  // 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().
359
  inline int entry_size() const;
360

361 362 363 364 365
  String* name() const {
    DCHECK(TypeFeedbackMetadata::SlotRequiresName(kind()));
    return metadata()->GetName(cur_slot_);
  }

366
 private:
367
  TypeFeedbackMetadata* metadata() const {
368 369 370 371 372 373
    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.
374 375
  Handle<TypeFeedbackMetadata> metadata_handle_;
  TypeFeedbackMetadata* metadata_;
376 377
  FeedbackVectorSlot cur_slot_;
  FeedbackVectorSlot next_slot_;
378 379 380 381
  FeedbackVectorSlotKind slot_kind_;
};


382 383 384 385
// A FeedbackNexus is the combination of a TypeFeedbackVector and a slot.
// Derived classes customize the update and retrieval of feedback.
class FeedbackNexus {
 public:
386
  FeedbackNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
387
      : vector_handle_(vector), vector_(NULL), slot_(slot) {}
388
  FeedbackNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
389 390 391 392 393 394 395 396 397 398
      : 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_;
  }
399
  FeedbackVectorSlot slot() const { return slot_; }
400 401

  InlineCacheState ic_state() const { return StateFromFeedback(); }
402
  bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; }
403 404 405 406 407 408 409
  Map* FindFirstMap() const {
    MapHandleList maps;
    ExtractMaps(&maps);
    if (maps.length() > 0) return *maps.at(0);
    return NULL;
  }

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

413
  virtual InlineCacheState StateFromFeedback() const = 0;
414
  virtual int ExtractMaps(MapHandleList* maps) const;
415 416 417
  virtual MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const;
  virtual bool FindHandlers(List<Handle<Object>>* code_list,
                            int length = -1) const;
418 419
  virtual Name* FindFirstName() const { return NULL; }

420 421 422 423
  virtual void ConfigureUninitialized();
  virtual void ConfigurePremonomorphic();
  virtual void ConfigureMegamorphic();

424 425
  inline Object* GetFeedback() const;
  inline Object* GetFeedbackExtra() const;
426

427
  inline Isolate* GetIsolate() const;
428

429
 protected:
430 431 432 433
  inline void SetFeedback(Object* feedback,
                          WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
  inline void SetFeedbackExtra(Object* feedback_extra,
                               WriteBarrierMode mode = UPDATE_WRITE_BARRIER);
434

435
  Handle<FixedArray> EnsureArrayOfSize(int length);
436 437
  Handle<FixedArray> EnsureExtraArrayOfSize(int length);
  void InstallHandlers(Handle<FixedArray> array, MapHandleList* maps,
438
                       List<Handle<Object>>* handlers);
439 440 441 442 443 444 445 446

 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_;
447
  FeedbackVectorSlot slot_;
448 449 450
};


451
class CallICNexus final : public FeedbackNexus {
452
 public:
453
  CallICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
454
      : FeedbackNexus(vector, slot) {
455
    DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot));
456
  }
457
  CallICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
458
      : FeedbackNexus(vector, slot) {
459
    DCHECK_EQ(FeedbackVectorSlotKind::CALL_IC, vector->GetKind(slot));
460 461
  }

462 463
  void Clear(Code* host);

464 465
  void ConfigureMonomorphicArray();
  void ConfigureMonomorphic(Handle<JSFunction> function);
466 467
  void ConfigureMegamorphic() final;
  void ConfigureMegamorphic(int call_count);
468

469
  InlineCacheState StateFromFeedback() const final;
470

471
  int ExtractMaps(MapHandleList* maps) const final {
472 473 474
    // CallICs don't record map feedback.
    return 0;
  }
475
  MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
476 477
    return MaybeHandle<Code>();
  }
478 479
  bool FindHandlers(List<Handle<Object>>* code_list,
                    int length = -1) const final {
480 481
    return length == 0;
  }
482 483

  int ExtractCallCount();
484
};
485 486 487 488


class LoadICNexus : public FeedbackNexus {
 public:
489
  LoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
490
      : FeedbackNexus(vector, slot) {
491
    DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot));
492
  }
493
  explicit LoadICNexus(Isolate* isolate)
494 495 496 497
      : FeedbackNexus(
            TypeFeedbackVector::DummyVector(isolate),
            FeedbackVectorSlot(TypeFeedbackVector::kDummyLoadICSlot)) {}
  LoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
498
      : FeedbackNexus(vector, slot) {
499
    DCHECK_EQ(FeedbackVectorSlotKind::LOAD_IC, vector->GetKind(slot));
500 501 502 503
  }

  void Clear(Code* host);

504
  void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler);
505

506 507
  void ConfigurePolymorphic(MapHandleList* maps,
                            List<Handle<Object>>* handlers);
508

509
  InlineCacheState StateFromFeedback() const override;
510 511
};

512 513 514 515 516 517 518 519 520 521 522
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));
  }

523 524 525 526
  int ExtractMaps(MapHandleList* maps) const final {
    // LoadGlobalICs don't record map feedback.
    return 0;
  }
527
  MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final {
528 529
    return MaybeHandle<Code>();
  }
530 531
  bool FindHandlers(List<Handle<Object>>* code_list,
                    int length = -1) const final {
532 533 534
    return length == 0;
  }

535 536 537
  void ConfigureMegamorphic() override { UNREACHABLE(); }
  void Clear(Code* host);

538 539 540 541
  void ConfigureUninitialized() override;
  void ConfigurePropertyCellMode(Handle<PropertyCell> cell);
  void ConfigureHandlerMode(Handle<Code> handler);

542 543
  InlineCacheState StateFromFeedback() const override;
};
544 545 546

class KeyedLoadICNexus : public FeedbackNexus {
 public:
547
  KeyedLoadICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
548
      : FeedbackNexus(vector, slot) {
549
    DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot));
550
  }
551
  KeyedLoadICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
552
      : FeedbackNexus(vector, slot) {
553
    DCHECK_EQ(FeedbackVectorSlotKind::KEYED_LOAD_IC, vector->GetKind(slot));
554 555 556 557
  }

  void Clear(Code* host);

558 559 560 561 562
  // name can be a null handle for element loads.
  void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
                            Handle<Code> handler);
  // name can be null.
  void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
563
                            List<Handle<Object>>* handlers);
564

565 566 567
  void ConfigureMegamorphicKeyed(IcCheckType property_type);

  IcCheckType GetKeyType() const;
568 569 570 571 572 573 574
  InlineCacheState StateFromFeedback() const override;
  Name* FindFirstName() const override;
};


class StoreICNexus : public FeedbackNexus {
 public:
575
  StoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
576
      : FeedbackNexus(vector, slot) {
577
    DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot));
578
  }
579
  explicit StoreICNexus(Isolate* isolate)
580 581 582 583
      : FeedbackNexus(
            TypeFeedbackVector::DummyVector(isolate),
            FeedbackVectorSlot(TypeFeedbackVector::kDummyStoreICSlot)) {}
  StoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
584
      : FeedbackNexus(vector, slot) {
585
    DCHECK_EQ(FeedbackVectorSlotKind::STORE_IC, vector->GetKind(slot));
586 587 588 589 590 591
  }

  void Clear(Code* host);

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

592 593
  void ConfigurePolymorphic(MapHandleList* maps,
                            List<Handle<Object>>* handlers);
594 595 596 597 598 599 600

  InlineCacheState StateFromFeedback() const override;
};


class KeyedStoreICNexus : public FeedbackNexus {
 public:
601
  KeyedStoreICNexus(Handle<TypeFeedbackVector> vector, FeedbackVectorSlot slot)
602
      : FeedbackNexus(vector, slot) {
603
    DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot));
604
  }
605
  explicit KeyedStoreICNexus(Isolate* isolate)
606 607 608 609
      : FeedbackNexus(
            TypeFeedbackVector::DummyVector(isolate),
            FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)) {}
  KeyedStoreICNexus(TypeFeedbackVector* vector, FeedbackVectorSlot slot)
610
      : FeedbackNexus(vector, slot) {
611
    DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, vector->GetKind(slot));
612 613 614 615
  }

  void Clear(Code* host);

616
  // name can be a null handle for element loads.
617
  void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map,
618 619
                            Handle<Code> handler);
  // name can be null.
620
  void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps,
621
                            List<Handle<Object>>* handlers);
622 623 624
  void ConfigurePolymorphic(MapHandleList* maps,
                            MapHandleList* transitioned_maps,
                            CodeHandleList* handlers);
625
  void ConfigureMegamorphicKeyed(IcCheckType property_type);
626 627 628

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

630 631
  InlineCacheState StateFromFeedback() const override;
  Name* FindFirstName() const override;
632
};
633 634
}  // namespace internal
}  // namespace v8
635 636

#endif  // V8_TRANSITIONS_H_