1 // Copyright 2014 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_FEEDBACK_VECTOR_H_ 6 #define V8_FEEDBACK_VECTOR_H_ 7 8 #include <vector> 9 10 #include "src/base/logging.h" 11 #include "src/elements-kind.h" 12 #include "src/objects.h" 13 #include "src/type-hints.h" 14 #include "src/zone/zone-containers.h" 15 16 namespace v8 { 17 namespace internal { 18 19 enum class FeedbackSlotKind { 20 // This kind means that the slot points to the middle of other slot 21 // which occupies more than one feedback vector element. 22 // There must be no such slots in the system. 23 kInvalid, 24 25 kCall, 26 kLoadProperty, 27 kLoadGlobalNotInsideTypeof, 28 kLoadGlobalInsideTypeof, 29 kLoadKeyed, 30 kStoreNamedSloppy, 31 kStoreNamedStrict, 32 kStoreOwnNamed, 33 kStoreKeyedSloppy, 34 kStoreKeyedStrict, 35 kBinaryOp, 36 kCompareOp, 37 kToBoolean, 38 kStoreDataPropertyInLiteral, 39 kCreateClosure, 40 kLiteral, 41 // This is a general purpose slot that occupies one feedback vector element. 42 kGeneral, 43 44 kKindsNumber // Last value indicating number of kinds. 45 }; 46 47 inline bool IsCallICKind(FeedbackSlotKind kind) { 48 return kind == FeedbackSlotKind::kCall; 49 } 50 51 inline bool IsLoadICKind(FeedbackSlotKind kind) { 52 return kind == FeedbackSlotKind::kLoadProperty; 53 } 54 55 inline bool IsLoadGlobalICKind(FeedbackSlotKind kind) { 56 return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof || 57 kind == FeedbackSlotKind::kLoadGlobalInsideTypeof; 58 } 59 60 inline bool IsKeyedLoadICKind(FeedbackSlotKind kind) { 61 return kind == FeedbackSlotKind::kLoadKeyed; 62 } 63 64 inline bool IsStoreICKind(FeedbackSlotKind kind) { 65 return kind == FeedbackSlotKind::kStoreNamedSloppy || 66 kind == FeedbackSlotKind::kStoreNamedStrict; 67 } 68 69 inline bool IsStoreOwnICKind(FeedbackSlotKind kind) { 70 return kind == FeedbackSlotKind::kStoreOwnNamed; 71 } 72 73 inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) { 74 return kind == FeedbackSlotKind::kStoreKeyedSloppy || 75 kind == FeedbackSlotKind::kStoreKeyedStrict; 76 } 77 78 inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) { 79 DCHECK(IsLoadGlobalICKind(kind)); 80 return (kind == FeedbackSlotKind::kLoadGlobalInsideTypeof) 81 ? INSIDE_TYPEOF 82 : NOT_INSIDE_TYPEOF; 83 } 84 85 inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) { 86 DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind) || 87 IsKeyedStoreICKind(kind)); 88 return (kind == FeedbackSlotKind::kStoreNamedSloppy || 89 kind == FeedbackSlotKind::kStoreKeyedSloppy) 90 ? SLOPPY 91 : STRICT; 92 } 93 94 std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind); 95 96 template <typename Derived> 97 class FeedbackVectorSpecBase { 98 public: 99 FeedbackSlot AddCallICSlot() { return AddSlot(FeedbackSlotKind::kCall); } 100 101 FeedbackSlot AddLoadICSlot() { 102 return AddSlot(FeedbackSlotKind::kLoadProperty); 103 } 104 105 FeedbackSlot AddLoadGlobalICSlot(TypeofMode typeof_mode) { 106 return AddSlot(typeof_mode == INSIDE_TYPEOF 107 ? FeedbackSlotKind::kLoadGlobalInsideTypeof 108 : FeedbackSlotKind::kLoadGlobalNotInsideTypeof); 109 } 110 111 FeedbackSlot AddCreateClosureSlot() { 112 return AddSlot(FeedbackSlotKind::kCreateClosure); 113 } 114 115 FeedbackSlot AddKeyedLoadICSlot() { 116 return AddSlot(FeedbackSlotKind::kLoadKeyed); 117 } 118 119 FeedbackSlot AddStoreICSlot(LanguageMode language_mode) { 120 STATIC_ASSERT(LANGUAGE_END == 2); 121 return AddSlot(is_strict(language_mode) 122 ? FeedbackSlotKind::kStoreNamedStrict 123 : FeedbackSlotKind::kStoreNamedSloppy); 124 } 125 126 FeedbackSlot AddStoreOwnICSlot() { 127 return AddSlot(FeedbackSlotKind::kStoreOwnNamed); 128 } 129 130 FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) { 131 STATIC_ASSERT(LANGUAGE_END == 2); 132 return AddSlot(is_strict(language_mode) 133 ? FeedbackSlotKind::kStoreKeyedStrict 134 : FeedbackSlotKind::kStoreKeyedSloppy); 135 } 136 137 FeedbackSlot AddInterpreterBinaryOpICSlot() { 138 return AddSlot(FeedbackSlotKind::kBinaryOp); 139 } 140 141 FeedbackSlot AddInterpreterCompareICSlot() { 142 return AddSlot(FeedbackSlotKind::kCompareOp); 143 } 144 145 FeedbackSlot AddGeneralSlot() { return AddSlot(FeedbackSlotKind::kGeneral); } 146 147 FeedbackSlot AddLiteralSlot() { return AddSlot(FeedbackSlotKind::kLiteral); } 148 149 FeedbackSlot AddStoreDataPropertyInLiteralICSlot() { 150 return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral); 151 } 152 153 #ifdef OBJECT_PRINT 154 // For gdb debugging. 155 void Print(); 156 #endif // OBJECT_PRINT 157 158 DECLARE_PRINTER(FeedbackVectorSpec) 159 160 private: 161 inline FeedbackSlot AddSlot(FeedbackSlotKind kind); 162 163 Derived* This() { return static_cast<Derived*>(this); } 164 }; 165 166 class StaticFeedbackVectorSpec 167 : public FeedbackVectorSpecBase<StaticFeedbackVectorSpec> { 168 public: 169 StaticFeedbackVectorSpec() : slot_count_(0) {} 170 171 int slots() const { return slot_count_; } 172 173 FeedbackSlotKind GetKind(FeedbackSlot slot) const { 174 DCHECK(slot.ToInt() >= 0 && slot.ToInt() < slot_count_); 175 return kinds_[slot.ToInt()]; 176 } 177 178 private: 179 friend class FeedbackVectorSpecBase<StaticFeedbackVectorSpec>; 180 181 void append(FeedbackSlotKind kind) { 182 DCHECK(slot_count_ < kMaxLength); 183 kinds_[slot_count_++] = kind; 184 } 185 186 static const int kMaxLength = 12; 187 188 int slot_count_; 189 FeedbackSlotKind kinds_[kMaxLength]; 190 }; 191 192 class FeedbackVectorSpec : public FeedbackVectorSpecBase<FeedbackVectorSpec> { 193 public: 194 explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) { 195 slot_kinds_.reserve(16); 196 } 197 198 int slots() const { return static_cast<int>(slot_kinds_.size()); } 199 200 FeedbackSlotKind GetKind(FeedbackSlot slot) const { 201 return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt())); 202 } 203 204 private: 205 friend class FeedbackVectorSpecBase<FeedbackVectorSpec>; 206 207 void append(FeedbackSlotKind kind) { 208 slot_kinds_.push_back(static_cast<unsigned char>(kind)); 209 } 210 211 ZoneVector<unsigned char> slot_kinds_; 212 }; 213 214 // The shape of the FeedbackMetadata is an array with: 215 // 0: slot_count 216 // 1: names table 217 // 2: parameters table 218 // 3..N: slot kinds packed into a bit vector 219 // 220 class FeedbackMetadata : public FixedArray { 221 public: 222 // Casting. 223 static inline FeedbackMetadata* cast(Object* obj); 224 225 static const int kSlotsCountIndex = 0; 226 static const int kReservedIndexCount = 1; 227 228 // Returns number of feedback vector elements used by given slot kind. 229 static inline int GetSlotSize(FeedbackSlotKind kind); 230 231 bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const; 232 233 inline bool is_empty() const; 234 235 // Returns number of slots in the vector. 236 inline int slot_count() const; 237 238 // Returns slot kind for given slot. 239 FeedbackSlotKind GetKind(FeedbackSlot slot) const; 240 241 template <typename Spec> 242 static Handle<FeedbackMetadata> New(Isolate* isolate, const Spec* spec); 243 244 #ifdef OBJECT_PRINT 245 // For gdb debugging. 246 void Print(); 247 #endif // OBJECT_PRINT 248 249 DECLARE_PRINTER(FeedbackMetadata) 250 251 static const char* Kind2String(FeedbackSlotKind kind); 252 253 private: 254 static const int kFeedbackSlotKindBits = 5; 255 STATIC_ASSERT(static_cast<int>(FeedbackSlotKind::kKindsNumber) < 256 (1 << kFeedbackSlotKindBits)); 257 258 void SetKind(FeedbackSlot slot, FeedbackSlotKind kind); 259 260 typedef BitSetComputer<FeedbackSlotKind, kFeedbackSlotKindBits, kSmiValueSize, 261 uint32_t> 262 VectorICComputer; 263 264 DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackMetadata); 265 }; 266 267 // The shape of the FeedbackVector is an array with: 268 // 0: feedback metadata 269 // 1: invocation count 270 // 2: feedback slot #0 271 // ... 272 // 2 + slot_count - 1: feedback slot #(slot_count-1) 273 // 274 class FeedbackVector : public FixedArray { 275 public: 276 // Casting. 277 static inline FeedbackVector* cast(Object* obj); 278 279 static const int kSharedFunctionInfoIndex = 0; 280 static const int kInvocationCountIndex = 1; 281 static const int kReservedIndexCount = 2; 282 283 inline void ComputeCounts(int* with_type_info, int* generic, 284 int* vector_ic_count, bool code_is_interpreted); 285 286 inline bool is_empty() const; 287 288 // Returns number of slots in the vector. 289 inline int slot_count() const; 290 291 inline FeedbackMetadata* metadata() const; 292 inline SharedFunctionInfo* shared_function_info() const; 293 inline int invocation_count() const; 294 inline void clear_invocation_count(); 295 296 // Conversion from a slot to an integer index to the underlying array. 297 static int GetIndex(FeedbackSlot slot) { 298 return kReservedIndexCount + slot.ToInt(); 299 } 300 301 // Conversion from an integer index to the underlying array to a slot. 302 static inline FeedbackSlot ToSlot(int index); 303 inline Object* Get(FeedbackSlot slot) const; 304 inline void Set(FeedbackSlot slot, Object* value, 305 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 306 307 // Returns slot kind for given slot. 308 FeedbackSlotKind GetKind(FeedbackSlot slot) const; 309 310 static Handle<FeedbackVector> New(Isolate* isolate, 311 Handle<SharedFunctionInfo> shared); 312 313 static Handle<FeedbackVector> Copy(Isolate* isolate, 314 Handle<FeedbackVector> vector); 315 316 #define DEFINE_SLOT_KIND_PREDICATE(Name) \ 317 bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); } 318 319 DEFINE_SLOT_KIND_PREDICATE(IsCallIC) 320 DEFINE_SLOT_KIND_PREDICATE(IsLoadIC) 321 DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC) 322 DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC) 323 DEFINE_SLOT_KIND_PREDICATE(IsStoreIC) 324 DEFINE_SLOT_KIND_PREDICATE(IsStoreOwnIC) 325 DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC) 326 #undef DEFINE_SLOT_KIND_PREDICATE 327 328 // Returns typeof mode encoded into kind of given slot. 329 inline TypeofMode GetTypeofMode(FeedbackSlot slot) const { 330 return GetTypeofModeFromSlotKind(GetKind(slot)); 331 } 332 333 // Returns language mode encoded into kind of given slot. 334 inline LanguageMode GetLanguageMode(FeedbackSlot slot) const { 335 return GetLanguageModeFromSlotKind(GetKind(slot)); 336 } 337 338 #ifdef OBJECT_PRINT 339 // For gdb debugging. 340 void Print(); 341 #endif // OBJECT_PRINT 342 343 DECLARE_PRINTER(FeedbackVector) 344 345 // Clears the vector slots. 346 void ClearSlots(JSFunction* host_function); 347 348 // The object that indicates an uninitialized cache. 349 static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate); 350 351 // The object that indicates a megamorphic state. 352 static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate); 353 354 // The object that indicates a premonomorphic state. 355 static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate); 356 357 // A raw version of the uninitialized sentinel that's safe to read during 358 // garbage collection (e.g., for patching the cache). 359 static inline Symbol* RawUninitializedSentinel(Isolate* isolate); 360 361 private: 362 static void AddToCodeCoverageList(Isolate* isolate, 363 Handle<FeedbackVector> vector); 364 365 DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackVector); 366 }; 367 368 // The following asserts protect an optimization in type feedback vector 369 // code that looks into the contents of a slot assuming to find a String, 370 // a Symbol, an AllocationSite, a WeakCell, or a FixedArray. 371 STATIC_ASSERT(WeakCell::kSize >= 2 * kPointerSize); 372 STATIC_ASSERT(WeakCell::kValueOffset == AllocationSite::kTransitionInfoOffset); 373 STATIC_ASSERT(WeakCell::kValueOffset == FixedArray::kLengthOffset); 374 STATIC_ASSERT(WeakCell::kValueOffset == Name::kHashFieldSlot); 375 // Verify that an empty hash field looks like a tagged object, but can't 376 // possibly be confused with a pointer. 377 STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag); 378 STATIC_ASSERT(Name::kEmptyHashField == 0x3); 379 // Verify that a set hash field will not look like a tagged object. 380 STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag); 381 382 class FeedbackMetadataIterator { 383 public: 384 explicit FeedbackMetadataIterator(Handle<FeedbackMetadata> metadata) 385 : metadata_handle_(metadata), 386 next_slot_(FeedbackSlot(0)), 387 slot_kind_(FeedbackSlotKind::kInvalid) {} 388 389 explicit FeedbackMetadataIterator(FeedbackMetadata* metadata) 390 : metadata_(metadata), 391 next_slot_(FeedbackSlot(0)), 392 slot_kind_(FeedbackSlotKind::kInvalid) {} 393 394 inline bool HasNext() const; 395 396 inline FeedbackSlot Next(); 397 398 // Returns slot kind of the last slot returned by Next(). 399 FeedbackSlotKind kind() const { 400 DCHECK_NE(FeedbackSlotKind::kInvalid, slot_kind_); 401 DCHECK_NE(FeedbackSlotKind::kKindsNumber, slot_kind_); 402 return slot_kind_; 403 } 404 405 // Returns entry size of the last slot returned by Next(). 406 inline int entry_size() const; 407 408 private: 409 FeedbackMetadata* metadata() const { 410 return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_; 411 } 412 413 // The reason for having a handle and a raw pointer to the meta data is 414 // to have a single iterator implementation for both "handlified" and raw 415 // pointer use cases. 416 Handle<FeedbackMetadata> metadata_handle_; 417 FeedbackMetadata* metadata_; 418 FeedbackSlot cur_slot_; 419 FeedbackSlot next_slot_; 420 FeedbackSlotKind slot_kind_; 421 }; 422 423 // A FeedbackNexus is the combination of a FeedbackVector and a slot. 424 // Derived classes customize the update and retrieval of feedback. 425 class FeedbackNexus { 426 public: 427 FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) 428 : vector_handle_(vector), vector_(NULL), slot_(slot) {} 429 FeedbackNexus(FeedbackVector* vector, FeedbackSlot slot) 430 : vector_(vector), slot_(slot) {} 431 virtual ~FeedbackNexus() {} 432 433 Handle<FeedbackVector> vector_handle() const { 434 DCHECK(vector_ == NULL); 435 return vector_handle_; 436 } 437 FeedbackVector* vector() const { 438 return vector_handle_.is_null() ? vector_ : *vector_handle_; 439 } 440 FeedbackSlot slot() const { return slot_; } 441 FeedbackSlotKind kind() const { return vector()->GetKind(slot()); } 442 443 InlineCacheState ic_state() const { return StateFromFeedback(); } 444 bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; } 445 Map* FindFirstMap() const { 446 MapHandleList maps; 447 ExtractMaps(&maps); 448 if (maps.length() > 0) return *maps.at(0); 449 return NULL; 450 } 451 452 // TODO(mvstanton): remove FindAllMaps, it didn't survive a code review. 453 void FindAllMaps(MapHandleList* maps) const { ExtractMaps(maps); } 454 455 virtual InlineCacheState StateFromFeedback() const = 0; 456 virtual int ExtractMaps(MapHandleList* maps) const; 457 virtual MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const; 458 virtual bool FindHandlers(List<Handle<Object>>* code_list, 459 int length = -1) const; 460 virtual Name* FindFirstName() const { return NULL; } 461 462 bool IsCleared() { 463 InlineCacheState state = StateFromFeedback(); 464 return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC; 465 } 466 467 virtual void Clear() { ConfigureUninitialized(); } 468 virtual void ConfigureUninitialized(); 469 virtual void ConfigurePremonomorphic(); 470 virtual void ConfigureMegamorphic(); 471 472 inline Object* GetFeedback() const; 473 inline Object* GetFeedbackExtra() const; 474 475 inline Isolate* GetIsolate() const; 476 477 protected: 478 inline void SetFeedback(Object* feedback, 479 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 480 inline void SetFeedbackExtra(Object* feedback_extra, 481 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 482 483 Handle<FixedArray> EnsureArrayOfSize(int length); 484 Handle<FixedArray> EnsureExtraArrayOfSize(int length); 485 void InstallHandlers(Handle<FixedArray> array, MapHandleList* maps, 486 List<Handle<Object>>* handlers); 487 488 private: 489 // The reason for having a vector handle and a raw pointer is that we can and 490 // should use handles during IC miss, but not during GC when we clear ICs. If 491 // you have a handle to the vector that is better because more operations can 492 // be done, like allocation. 493 Handle<FeedbackVector> vector_handle_; 494 FeedbackVector* vector_; 495 FeedbackSlot slot_; 496 }; 497 498 class CallICNexus final : public FeedbackNexus { 499 public: 500 CallICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) 501 : FeedbackNexus(vector, slot) { 502 DCHECK(vector->IsCallIC(slot)); 503 } 504 CallICNexus(FeedbackVector* vector, FeedbackSlot slot) 505 : FeedbackNexus(vector, slot) { 506 DCHECK(vector->IsCallIC(slot)); 507 } 508 509 void ConfigureUninitialized() override; 510 void ConfigureMonomorphicArray(); 511 void ConfigureMonomorphic(Handle<JSFunction> function); 512 void ConfigureMegamorphic() final; 513 void ConfigureMegamorphic(int call_count); 514 515 InlineCacheState StateFromFeedback() const final; 516 517 int ExtractMaps(MapHandleList* maps) const final { 518 // CallICs don't record map feedback. 519 return 0; 520 } 521 MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final { 522 return MaybeHandle<Code>(); 523 } 524 bool FindHandlers(List<Handle<Object>>* code_list, 525 int length = -1) const final { 526 return length == 0; 527 } 528 529 int ExtractCallCount(); 530 531 // Compute the call frequency based on the call count and the invocation 532 // count (taken from the type feedback vector). 533 float ComputeCallFrequency(); 534 }; 535 536 class LoadICNexus : public FeedbackNexus { 537 public: 538 LoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) 539 : FeedbackNexus(vector, slot) { 540 DCHECK(vector->IsLoadIC(slot)); 541 } 542 LoadICNexus(FeedbackVector* vector, FeedbackSlot slot) 543 : FeedbackNexus(vector, slot) { 544 DCHECK(vector->IsLoadIC(slot)); 545 } 546 547 void Clear() override { ConfigurePremonomorphic(); } 548 549 void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler); 550 551 void ConfigurePolymorphic(MapHandleList* maps, 552 List<Handle<Object>>* handlers); 553 554 InlineCacheState StateFromFeedback() const override; 555 }; 556 557 class LoadGlobalICNexus : public FeedbackNexus { 558 public: 559 LoadGlobalICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) 560 : FeedbackNexus(vector, slot) { 561 DCHECK(vector->IsLoadGlobalIC(slot)); 562 } 563 LoadGlobalICNexus(FeedbackVector* vector, FeedbackSlot slot) 564 : FeedbackNexus(vector, slot) { 565 DCHECK(vector->IsLoadGlobalIC(slot)); 566 } 567 568 int ExtractMaps(MapHandleList* maps) const final { 569 // LoadGlobalICs don't record map feedback. 570 return 0; 571 } 572 MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final { 573 return MaybeHandle<Code>(); 574 } 575 bool FindHandlers(List<Handle<Object>>* code_list, 576 int length = -1) const final { 577 return length == 0; 578 } 579 580 void ConfigureMegamorphic() override { UNREACHABLE(); } 581 582 void ConfigureUninitialized() override; 583 void ConfigurePropertyCellMode(Handle<PropertyCell> cell); 584 void ConfigureHandlerMode(Handle<Object> handler); 585 586 InlineCacheState StateFromFeedback() const override; 587 }; 588 589 class KeyedLoadICNexus : public FeedbackNexus { 590 public: 591 KeyedLoadICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) 592 : FeedbackNexus(vector, slot) { 593 DCHECK(vector->IsKeyedLoadIC(slot)); 594 } 595 KeyedLoadICNexus(FeedbackVector* vector, FeedbackSlot slot) 596 : FeedbackNexus(vector, slot) { 597 DCHECK(vector->IsKeyedLoadIC(slot)); 598 } 599 600 void Clear() override { ConfigurePremonomorphic(); } 601 602 // name can be a null handle for element loads. 603 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map, 604 Handle<Object> handler); 605 // name can be null. 606 void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps, 607 List<Handle<Object>>* handlers); 608 609 void ConfigureMegamorphicKeyed(IcCheckType property_type); 610 611 IcCheckType GetKeyType() const; 612 InlineCacheState StateFromFeedback() const override; 613 Name* FindFirstName() const override; 614 }; 615 616 class StoreICNexus : public FeedbackNexus { 617 public: 618 StoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) 619 : FeedbackNexus(vector, slot) { 620 DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot)); 621 } 622 StoreICNexus(FeedbackVector* vector, FeedbackSlot slot) 623 : FeedbackNexus(vector, slot) { 624 DCHECK(vector->IsStoreIC(slot) || vector->IsStoreOwnIC(slot)); 625 } 626 627 void Clear() override { ConfigurePremonomorphic(); } 628 629 void ConfigureMonomorphic(Handle<Map> receiver_map, Handle<Object> handler); 630 631 void ConfigurePolymorphic(MapHandleList* maps, 632 List<Handle<Object>>* handlers); 633 634 InlineCacheState StateFromFeedback() const override; 635 }; 636 637 // TODO(ishell): Currently we use StoreOwnIC only for storing properties that 638 // already exist in the boilerplate therefore we can use StoreIC. 639 typedef StoreICNexus StoreOwnICNexus; 640 641 class KeyedStoreICNexus : public FeedbackNexus { 642 public: 643 KeyedStoreICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) 644 : FeedbackNexus(vector, slot) { 645 DCHECK(vector->IsKeyedStoreIC(slot)); 646 } 647 KeyedStoreICNexus(FeedbackVector* vector, FeedbackSlot slot) 648 : FeedbackNexus(vector, slot) { 649 DCHECK(vector->IsKeyedStoreIC(slot)); 650 } 651 652 void Clear() override { ConfigurePremonomorphic(); } 653 654 // name can be a null handle for element loads. 655 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map, 656 Handle<Object> handler); 657 // name can be null. 658 void ConfigurePolymorphic(Handle<Name> name, MapHandleList* maps, 659 List<Handle<Object>>* handlers); 660 void ConfigurePolymorphic(MapHandleList* maps, 661 MapHandleList* transitioned_maps, 662 List<Handle<Object>>* handlers); 663 void ConfigureMegamorphicKeyed(IcCheckType property_type); 664 665 KeyedAccessStoreMode GetKeyedAccessStoreMode() const; 666 IcCheckType GetKeyType() const; 667 668 InlineCacheState StateFromFeedback() const override; 669 Name* FindFirstName() const override; 670 }; 671 672 class BinaryOpICNexus final : public FeedbackNexus { 673 public: 674 BinaryOpICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) 675 : FeedbackNexus(vector, slot) { 676 DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot)); 677 } 678 BinaryOpICNexus(FeedbackVector* vector, FeedbackSlot slot) 679 : FeedbackNexus(vector, slot) { 680 DCHECK_EQ(FeedbackSlotKind::kBinaryOp, vector->GetKind(slot)); 681 } 682 683 InlineCacheState StateFromFeedback() const final; 684 BinaryOperationHint GetBinaryOperationFeedback() const; 685 686 int ExtractMaps(MapHandleList* maps) const final { 687 // BinaryOpICs don't record map feedback. 688 return 0; 689 } 690 MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final { 691 return MaybeHandle<Code>(); 692 } 693 bool FindHandlers(List<Handle<Object>>* code_list, 694 int length = -1) const final { 695 return length == 0; 696 } 697 }; 698 699 class CompareICNexus final : public FeedbackNexus { 700 public: 701 CompareICNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) 702 : FeedbackNexus(vector, slot) { 703 DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot)); 704 } 705 CompareICNexus(FeedbackVector* vector, FeedbackSlot slot) 706 : FeedbackNexus(vector, slot) { 707 DCHECK_EQ(FeedbackSlotKind::kCompareOp, vector->GetKind(slot)); 708 } 709 710 InlineCacheState StateFromFeedback() const final; 711 CompareOperationHint GetCompareOperationFeedback() const; 712 713 int ExtractMaps(MapHandleList* maps) const final { 714 // BinaryOpICs don't record map feedback. 715 return 0; 716 } 717 MaybeHandle<Object> FindHandlerForMap(Handle<Map> map) const final { 718 return MaybeHandle<Code>(); 719 } 720 bool FindHandlers(List<Handle<Object>>* code_list, 721 int length = -1) const final { 722 return length == 0; 723 } 724 }; 725 726 class StoreDataPropertyInLiteralICNexus : public FeedbackNexus { 727 public: 728 StoreDataPropertyInLiteralICNexus(Handle<FeedbackVector> vector, 729 FeedbackSlot slot) 730 : FeedbackNexus(vector, slot) { 731 DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral, 732 vector->GetKind(slot)); 733 } 734 StoreDataPropertyInLiteralICNexus(FeedbackVector* vector, FeedbackSlot slot) 735 : FeedbackNexus(vector, slot) { 736 DCHECK_EQ(FeedbackSlotKind::kStoreDataPropertyInLiteral, 737 vector->GetKind(slot)); 738 } 739 740 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map); 741 742 InlineCacheState StateFromFeedback() const override; 743 }; 744 745 inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback); 746 inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback); 747 748 } // namespace internal 749 } // namespace v8 750 751 #endif // V8_FEEDBACK_VECTOR_H_ 752