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