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/base/macros.h" 12 #include "src/elements-kind.h" 13 #include "src/globals.h" 14 #include "src/objects/map.h" 15 #include "src/objects/name.h" 16 #include "src/objects/object-macros.h" 17 #include "src/type-hints.h" 18 #include "src/zone/zone-containers.h" 19 20 namespace v8 { 21 namespace internal { 22 23 enum class FeedbackSlotKind { 24 // This kind means that the slot points to the middle of other slot 25 // which occupies more than one feedback vector element. 26 // There must be no such slots in the system. 27 kInvalid, 28 29 // Sloppy kinds come first, for easy language mode testing. 30 kStoreGlobalSloppy, 31 kStoreNamedSloppy, 32 kStoreKeyedSloppy, 33 kLastSloppyKind = kStoreKeyedSloppy, 34 35 // Strict and language mode unaware kinds. 36 kCall, 37 kLoadProperty, 38 kLoadGlobalNotInsideTypeof, 39 kLoadGlobalInsideTypeof, 40 kLoadKeyed, 41 kStoreGlobalStrict, 42 kStoreNamedStrict, 43 kStoreOwnNamed, 44 kStoreKeyedStrict, 45 kStoreInArrayLiteral, 46 kBinaryOp, 47 kCompareOp, 48 kStoreDataPropertyInLiteral, 49 kTypeProfile, 50 kCreateClosure, 51 kLiteral, 52 kForIn, 53 kInstanceOf, 54 kCloneObject, 55 56 kKindsNumber // Last value indicating number of kinds. 57 }; 58 59 inline bool IsCallICKind(FeedbackSlotKind kind) { 60 return kind == FeedbackSlotKind::kCall; 61 } 62 63 inline bool IsLoadICKind(FeedbackSlotKind kind) { 64 return kind == FeedbackSlotKind::kLoadProperty; 65 } 66 67 inline bool IsLoadGlobalICKind(FeedbackSlotKind kind) { 68 return kind == FeedbackSlotKind::kLoadGlobalNotInsideTypeof || 69 kind == FeedbackSlotKind::kLoadGlobalInsideTypeof; 70 } 71 72 inline bool IsKeyedLoadICKind(FeedbackSlotKind kind) { 73 return kind == FeedbackSlotKind::kLoadKeyed; 74 } 75 76 inline bool IsStoreGlobalICKind(FeedbackSlotKind kind) { 77 return kind == FeedbackSlotKind::kStoreGlobalSloppy || 78 kind == FeedbackSlotKind::kStoreGlobalStrict; 79 } 80 81 inline bool IsStoreICKind(FeedbackSlotKind kind) { 82 return kind == FeedbackSlotKind::kStoreNamedSloppy || 83 kind == FeedbackSlotKind::kStoreNamedStrict; 84 } 85 86 inline bool IsStoreOwnICKind(FeedbackSlotKind kind) { 87 return kind == FeedbackSlotKind::kStoreOwnNamed; 88 } 89 90 inline bool IsStoreDataPropertyInLiteralKind(FeedbackSlotKind kind) { 91 return kind == FeedbackSlotKind::kStoreDataPropertyInLiteral; 92 } 93 94 inline bool IsKeyedStoreICKind(FeedbackSlotKind kind) { 95 return kind == FeedbackSlotKind::kStoreKeyedSloppy || 96 kind == FeedbackSlotKind::kStoreKeyedStrict; 97 } 98 99 inline bool IsStoreInArrayLiteralICKind(FeedbackSlotKind kind) { 100 return kind == FeedbackSlotKind::kStoreInArrayLiteral; 101 } 102 103 inline bool IsGlobalICKind(FeedbackSlotKind kind) { 104 return IsLoadGlobalICKind(kind) || IsStoreGlobalICKind(kind); 105 } 106 107 inline bool IsTypeProfileKind(FeedbackSlotKind kind) { 108 return kind == FeedbackSlotKind::kTypeProfile; 109 } 110 111 inline bool IsCloneObjectKind(FeedbackSlotKind kind) { 112 return kind == FeedbackSlotKind::kCloneObject; 113 } 114 115 inline TypeofMode GetTypeofModeFromSlotKind(FeedbackSlotKind kind) { 116 DCHECK(IsLoadGlobalICKind(kind)); 117 return (kind == FeedbackSlotKind::kLoadGlobalInsideTypeof) 118 ? INSIDE_TYPEOF 119 : NOT_INSIDE_TYPEOF; 120 } 121 122 inline LanguageMode GetLanguageModeFromSlotKind(FeedbackSlotKind kind) { 123 DCHECK(IsStoreICKind(kind) || IsStoreOwnICKind(kind) || 124 IsStoreGlobalICKind(kind) || IsKeyedStoreICKind(kind)); 125 STATIC_ASSERT(FeedbackSlotKind::kStoreGlobalSloppy <= 126 FeedbackSlotKind::kLastSloppyKind); 127 STATIC_ASSERT(FeedbackSlotKind::kStoreKeyedSloppy <= 128 FeedbackSlotKind::kLastSloppyKind); 129 STATIC_ASSERT(FeedbackSlotKind::kStoreNamedSloppy <= 130 FeedbackSlotKind::kLastSloppyKind); 131 return (kind <= FeedbackSlotKind::kLastSloppyKind) ? LanguageMode::kSloppy 132 : LanguageMode::kStrict; 133 } 134 135 std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind); 136 137 typedef std::vector<MaybeObjectHandle> MaybeObjectHandles; 138 139 class FeedbackMetadata; 140 141 // A FeedbackVector has a fixed header with: 142 // - shared function info (which includes feedback metadata) 143 // - invocation count 144 // - runtime profiler ticks 145 // - optimized code cell (weak cell or Smi marker) 146 // followed by an array of feedback slots, of length determined by the feedback 147 // metadata. 148 class FeedbackVector : public HeapObject, public NeverReadOnlySpaceObject { 149 public: 150 // Use the mixin methods over the HeapObject methods. 151 // TODO(v8:7786) Remove once the HeapObject methods are gone. 152 using NeverReadOnlySpaceObject::GetHeap; 153 using NeverReadOnlySpaceObject::GetIsolate; 154 155 // Casting. 156 static inline FeedbackVector* cast(Object* obj); 157 158 inline void ComputeCounts(int* with_type_info, int* generic, 159 int* vector_ic_count); 160 161 inline bool is_empty() const; 162 163 inline FeedbackMetadata* metadata() const; 164 165 // [shared_function_info]: The shared function info for the function with this 166 // feedback vector. 167 DECL_ACCESSORS(shared_function_info, SharedFunctionInfo) 168 169 // [optimized_code_weak_or_smi]: weak reference to optimized code or a Smi 170 // marker defining optimization behaviour. 171 DECL_ACCESSORS(optimized_code_weak_or_smi, MaybeObject) 172 173 // [length]: The length of the feedback vector (not including the header, i.e. 174 // the number of feedback slots). 175 DECL_INT32_ACCESSORS(length) 176 177 // [invocation_count]: The number of times this function has been invoked. 178 DECL_INT32_ACCESSORS(invocation_count) 179 180 // [invocation_count]: The number of times this function has been seen by the 181 // runtime profiler. 182 DECL_INT32_ACCESSORS(profiler_ticks) 183 184 // [deopt_count]: The number of times this function has deoptimized. 185 DECL_INT32_ACCESSORS(deopt_count) 186 187 inline void clear_invocation_count(); 188 inline void increment_deopt_count(); 189 190 inline Code* optimized_code() const; 191 inline OptimizationMarker optimization_marker() const; 192 inline bool has_optimized_code() const; 193 inline bool has_optimization_marker() const; 194 void ClearOptimizedCode(); 195 void EvictOptimizedCodeMarkedForDeoptimization(SharedFunctionInfo* shared, 196 const char* reason); 197 static void SetOptimizedCode(Handle<FeedbackVector> vector, 198 Handle<Code> code); 199 void SetOptimizationMarker(OptimizationMarker marker); 200 201 // Clears the optimization marker in the feedback vector. 202 void ClearOptimizationMarker(); 203 204 // Conversion from a slot to an integer index to the underlying array. 205 static int GetIndex(FeedbackSlot slot) { return slot.ToInt(); } 206 207 // Conversion from an integer index to the underlying array to a slot. 208 static inline FeedbackSlot ToSlot(int index); 209 inline MaybeObject* Get(FeedbackSlot slot) const; 210 inline MaybeObject* get(int index) const; 211 inline void Set(FeedbackSlot slot, MaybeObject* value, 212 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 213 inline void set(int index, MaybeObject* value, 214 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 215 inline void Set(FeedbackSlot slot, Object* value, 216 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 217 inline void set(int index, Object* value, 218 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 219 220 // Gives access to raw memory which stores the array's data. 221 inline MaybeObject** slots_start(); 222 223 // Returns slot kind for given slot. 224 FeedbackSlotKind GetKind(FeedbackSlot slot) const; 225 226 FeedbackSlot GetTypeProfileSlot() const; 227 228 V8_EXPORT_PRIVATE static Handle<FeedbackVector> New( 229 Isolate* isolate, Handle<SharedFunctionInfo> shared); 230 231 #define DEFINE_SLOT_KIND_PREDICATE(Name) \ 232 bool Name(FeedbackSlot slot) const { return Name##Kind(GetKind(slot)); } 233 234 DEFINE_SLOT_KIND_PREDICATE(IsCallIC) 235 DEFINE_SLOT_KIND_PREDICATE(IsGlobalIC) 236 DEFINE_SLOT_KIND_PREDICATE(IsLoadIC) 237 DEFINE_SLOT_KIND_PREDICATE(IsLoadGlobalIC) 238 DEFINE_SLOT_KIND_PREDICATE(IsKeyedLoadIC) 239 DEFINE_SLOT_KIND_PREDICATE(IsStoreIC) 240 DEFINE_SLOT_KIND_PREDICATE(IsStoreOwnIC) 241 DEFINE_SLOT_KIND_PREDICATE(IsStoreGlobalIC) 242 DEFINE_SLOT_KIND_PREDICATE(IsKeyedStoreIC) 243 DEFINE_SLOT_KIND_PREDICATE(IsTypeProfile) 244 #undef DEFINE_SLOT_KIND_PREDICATE 245 246 // Returns typeof mode encoded into kind of given slot. 247 inline TypeofMode GetTypeofMode(FeedbackSlot slot) const { 248 return GetTypeofModeFromSlotKind(GetKind(slot)); 249 } 250 251 // Returns language mode encoded into kind of given slot. 252 inline LanguageMode GetLanguageMode(FeedbackSlot slot) const { 253 return GetLanguageModeFromSlotKind(GetKind(slot)); 254 } 255 256 static void AssertNoLegacyTypes(MaybeObject* object); 257 258 DECL_PRINTER(FeedbackVector) 259 DECL_VERIFIER(FeedbackVector) 260 261 void FeedbackSlotPrint(std::ostream& os, FeedbackSlot slot); // NOLINT 262 263 // Clears the vector slots. Return true if feedback has changed. 264 bool ClearSlots(Isolate* isolate); 265 266 // The object that indicates an uninitialized cache. 267 static inline Handle<Symbol> UninitializedSentinel(Isolate* isolate); 268 269 // The object that indicates a generic state. 270 static inline Handle<Symbol> GenericSentinel(Isolate* isolate); 271 272 // The object that indicates a megamorphic state. 273 static inline Handle<Symbol> MegamorphicSentinel(Isolate* isolate); 274 275 // The object that indicates a premonomorphic state. 276 static inline Handle<Symbol> PremonomorphicSentinel(Isolate* isolate); 277 278 // A raw version of the uninitialized sentinel that's safe to read during 279 // garbage collection (e.g., for patching the cache). 280 static inline Symbol* RawUninitializedSentinel(Isolate* isolate); 281 282 // Layout description. 283 #define FEEDBACK_VECTOR_FIELDS(V) \ 284 /* Header fields. */ \ 285 V(kSharedFunctionInfoOffset, kPointerSize) \ 286 V(kOptimizedCodeOffset, kPointerSize) \ 287 V(kLengthOffset, kInt32Size) \ 288 V(kInvocationCountOffset, kInt32Size) \ 289 V(kProfilerTicksOffset, kInt32Size) \ 290 V(kDeoptCountOffset, kInt32Size) \ 291 V(kUnalignedHeaderSize, 0) 292 293 DEFINE_FIELD_OFFSET_CONSTANTS(HeapObject::kHeaderSize, FEEDBACK_VECTOR_FIELDS) 294 #undef FEEDBACK_VECTOR_FIELDS 295 296 static const int kHeaderSize = 297 RoundUp<kPointerAlignment>(kUnalignedHeaderSize); 298 static const int kFeedbackSlotsOffset = kHeaderSize; 299 300 class BodyDescriptor; 301 // No weak fields. 302 typedef BodyDescriptor BodyDescriptorWeak; 303 304 // Garbage collection support. 305 static constexpr int SizeFor(int length) { 306 return kFeedbackSlotsOffset + length * kPointerSize; 307 } 308 309 private: 310 static void AddToVectorsForProfilingTools(Isolate* isolate, 311 Handle<FeedbackVector> vector); 312 313 DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackVector); 314 }; 315 316 class V8_EXPORT_PRIVATE FeedbackVectorSpec { 317 public: 318 explicit FeedbackVectorSpec(Zone* zone) : slot_kinds_(zone) { 319 slot_kinds_.reserve(16); 320 } 321 322 int slots() const { return static_cast<int>(slot_kinds_.size()); } 323 324 FeedbackSlotKind GetKind(FeedbackSlot slot) const { 325 return static_cast<FeedbackSlotKind>(slot_kinds_.at(slot.ToInt())); 326 } 327 328 bool HasTypeProfileSlot() const; 329 330 // If used, the TypeProfileSlot is always added as the first slot and its 331 // index is constant. If other slots are added before the TypeProfileSlot, 332 // this number changes. 333 static const int kTypeProfileSlotIndex = 0; 334 335 FeedbackSlot AddCallICSlot() { return AddSlot(FeedbackSlotKind::kCall); } 336 337 FeedbackSlot AddLoadICSlot() { 338 return AddSlot(FeedbackSlotKind::kLoadProperty); 339 } 340 341 FeedbackSlot AddLoadGlobalICSlot(TypeofMode typeof_mode) { 342 return AddSlot(typeof_mode == INSIDE_TYPEOF 343 ? FeedbackSlotKind::kLoadGlobalInsideTypeof 344 : FeedbackSlotKind::kLoadGlobalNotInsideTypeof); 345 } 346 347 FeedbackSlot AddCreateClosureSlot() { 348 return AddSlot(FeedbackSlotKind::kCreateClosure); 349 } 350 351 FeedbackSlot AddKeyedLoadICSlot() { 352 return AddSlot(FeedbackSlotKind::kLoadKeyed); 353 } 354 355 FeedbackSlot AddStoreICSlot(LanguageMode language_mode) { 356 STATIC_ASSERT(LanguageModeSize == 2); 357 return AddSlot(is_strict(language_mode) 358 ? FeedbackSlotKind::kStoreNamedStrict 359 : FeedbackSlotKind::kStoreNamedSloppy); 360 } 361 362 FeedbackSlot AddStoreOwnICSlot() { 363 return AddSlot(FeedbackSlotKind::kStoreOwnNamed); 364 } 365 366 FeedbackSlot AddStoreGlobalICSlot(LanguageMode language_mode) { 367 STATIC_ASSERT(LanguageModeSize == 2); 368 return AddSlot(is_strict(language_mode) 369 ? FeedbackSlotKind::kStoreGlobalStrict 370 : FeedbackSlotKind::kStoreGlobalSloppy); 371 } 372 373 FeedbackSlot AddKeyedStoreICSlot(LanguageMode language_mode) { 374 STATIC_ASSERT(LanguageModeSize == 2); 375 return AddSlot(is_strict(language_mode) 376 ? FeedbackSlotKind::kStoreKeyedStrict 377 : FeedbackSlotKind::kStoreKeyedSloppy); 378 } 379 380 FeedbackSlot AddStoreInArrayLiteralICSlot() { 381 return AddSlot(FeedbackSlotKind::kStoreInArrayLiteral); 382 } 383 384 FeedbackSlot AddBinaryOpICSlot() { 385 return AddSlot(FeedbackSlotKind::kBinaryOp); 386 } 387 388 FeedbackSlot AddCompareICSlot() { 389 return AddSlot(FeedbackSlotKind::kCompareOp); 390 } 391 392 FeedbackSlot AddForInSlot() { return AddSlot(FeedbackSlotKind::kForIn); } 393 394 FeedbackSlot AddInstanceOfSlot() { 395 return AddSlot(FeedbackSlotKind::kInstanceOf); 396 } 397 398 FeedbackSlot AddLiteralSlot() { return AddSlot(FeedbackSlotKind::kLiteral); } 399 400 FeedbackSlot AddStoreDataPropertyInLiteralICSlot() { 401 return AddSlot(FeedbackSlotKind::kStoreDataPropertyInLiteral); 402 } 403 404 FeedbackSlot AddTypeProfileSlot(); 405 406 FeedbackSlot AddCloneObjectSlot() { 407 return AddSlot(FeedbackSlotKind::kCloneObject); 408 } 409 410 #ifdef OBJECT_PRINT 411 // For gdb debugging. 412 void Print(); 413 #endif // OBJECT_PRINT 414 415 DECL_PRINTER(FeedbackVectorSpec) 416 417 private: 418 FeedbackSlot AddSlot(FeedbackSlotKind kind); 419 420 void append(FeedbackSlotKind kind) { 421 slot_kinds_.push_back(static_cast<unsigned char>(kind)); 422 } 423 424 ZoneVector<unsigned char> slot_kinds_; 425 }; 426 427 // FeedbackMetadata is an array-like object with a slot count (indicating how 428 // many slots are stored). We save space by packing several slots into an array 429 // of int32 data. The length is never stored - it is always calculated from 430 // slot_count. All instances are created through the static New function, and 431 // the number of slots is static once an instance is created. 432 class FeedbackMetadata : public HeapObject { 433 public: 434 // Casting. 435 static inline FeedbackMetadata* cast(Object* obj); 436 437 // The number of slots that this metadata contains. Stored as an int32. 438 DECL_INT32_ACCESSORS(slot_count) 439 440 // Get slot_count using an acquire load. 441 inline int32_t synchronized_slot_count() const; 442 443 // Returns number of feedback vector elements used by given slot kind. 444 static inline int GetSlotSize(FeedbackSlotKind kind); 445 446 bool SpecDiffersFrom(const FeedbackVectorSpec* other_spec) const; 447 448 inline bool is_empty() const; 449 450 // Returns slot kind for given slot. 451 FeedbackSlotKind GetKind(FeedbackSlot slot) const; 452 453 // If {spec} is null, then it is considered empty. 454 V8_EXPORT_PRIVATE static Handle<FeedbackMetadata> New( 455 Isolate* isolate, const FeedbackVectorSpec* spec = nullptr); 456 457 DECL_PRINTER(FeedbackMetadata) 458 DECL_VERIFIER(FeedbackMetadata) 459 460 static const char* Kind2String(FeedbackSlotKind kind); 461 bool HasTypeProfileSlot() const; 462 463 // Garbage collection support. 464 // This includes any necessary padding at the end of the object for pointer 465 // size alignment. 466 static int SizeFor(int slot_count) { 467 return OBJECT_POINTER_ALIGN(kHeaderSize + length(slot_count) * kInt32Size); 468 } 469 470 static const int kSlotCountOffset = HeapObject::kHeaderSize; 471 static const int kHeaderSize = kSlotCountOffset + kInt32Size; 472 473 class BodyDescriptor; 474 // No weak fields. 475 typedef BodyDescriptor BodyDescriptorWeak; 476 477 private: 478 friend class AccessorAssembler; 479 480 // Raw accessors to the encoded slot data. 481 inline int32_t get(int index) const; 482 inline void set(int index, int32_t value); 483 484 // The number of int32 data fields needed to store {slot_count} slots. 485 // Does not include any extra padding for pointer size alignment. 486 static int length(int slot_count) { 487 return VectorICComputer::word_count(slot_count); 488 } 489 inline int length() const; 490 491 static const int kFeedbackSlotKindBits = 5; 492 STATIC_ASSERT(static_cast<int>(FeedbackSlotKind::kKindsNumber) < 493 (1 << kFeedbackSlotKindBits)); 494 495 void SetKind(FeedbackSlot slot, FeedbackSlotKind kind); 496 497 typedef BitSetComputer<FeedbackSlotKind, kFeedbackSlotKindBits, 498 kInt32Size * kBitsPerByte, uint32_t> 499 VectorICComputer; 500 501 DISALLOW_IMPLICIT_CONSTRUCTORS(FeedbackMetadata); 502 }; 503 504 // Verify that an empty hash field looks like a tagged object, but can't 505 // possibly be confused with a pointer. 506 STATIC_ASSERT((Name::kEmptyHashField & kHeapObjectTag) == kHeapObjectTag); 507 STATIC_ASSERT(Name::kEmptyHashField == 0x3); 508 // Verify that a set hash field will not look like a tagged object. 509 STATIC_ASSERT(Name::kHashNotComputedMask == kHeapObjectTag); 510 511 class FeedbackMetadataIterator { 512 public: 513 explicit FeedbackMetadataIterator(Handle<FeedbackMetadata> metadata) 514 : metadata_handle_(metadata), 515 next_slot_(FeedbackSlot(0)), 516 slot_kind_(FeedbackSlotKind::kInvalid) {} 517 518 explicit FeedbackMetadataIterator(FeedbackMetadata* metadata) 519 : metadata_(metadata), 520 next_slot_(FeedbackSlot(0)), 521 slot_kind_(FeedbackSlotKind::kInvalid) {} 522 523 inline bool HasNext() const; 524 525 inline FeedbackSlot Next(); 526 527 // Returns slot kind of the last slot returned by Next(). 528 FeedbackSlotKind kind() const { 529 DCHECK_NE(FeedbackSlotKind::kInvalid, slot_kind_); 530 DCHECK_NE(FeedbackSlotKind::kKindsNumber, slot_kind_); 531 return slot_kind_; 532 } 533 534 // Returns entry size of the last slot returned by Next(). 535 inline int entry_size() const; 536 537 private: 538 FeedbackMetadata* metadata() const { 539 return !metadata_handle_.is_null() ? *metadata_handle_ : metadata_; 540 } 541 542 // The reason for having a handle and a raw pointer to the meta data is 543 // to have a single iterator implementation for both "handlified" and raw 544 // pointer use cases. 545 Handle<FeedbackMetadata> metadata_handle_; 546 FeedbackMetadata* metadata_; 547 FeedbackSlot cur_slot_; 548 FeedbackSlot next_slot_; 549 FeedbackSlotKind slot_kind_; 550 }; 551 552 // A FeedbackNexus is the combination of a FeedbackVector and a slot. 553 class FeedbackNexus final { 554 public: 555 FeedbackNexus(Handle<FeedbackVector> vector, FeedbackSlot slot) 556 : vector_handle_(vector), 557 vector_(nullptr), 558 slot_(slot), 559 kind_(vector->GetKind(slot)) {} 560 FeedbackNexus(FeedbackVector* vector, FeedbackSlot slot) 561 : vector_(vector), slot_(slot), kind_(vector->GetKind(slot)) {} 562 563 Handle<FeedbackVector> vector_handle() const { 564 DCHECK_NULL(vector_); 565 return vector_handle_; 566 } 567 FeedbackVector* vector() const { 568 return vector_handle_.is_null() ? vector_ : *vector_handle_; 569 } 570 FeedbackSlot slot() const { return slot_; } 571 FeedbackSlotKind kind() const { return kind_; } 572 573 inline LanguageMode GetLanguageMode() const { 574 return vector()->GetLanguageMode(slot()); 575 } 576 577 InlineCacheState ic_state() const { return StateFromFeedback(); } 578 bool IsUninitialized() const { return StateFromFeedback() == UNINITIALIZED; } 579 bool IsMegamorphic() const { return StateFromFeedback() == MEGAMORPHIC; } 580 bool IsGeneric() const { return StateFromFeedback() == GENERIC; } 581 582 void Print(std::ostream& os); // NOLINT 583 584 // For map-based ICs (load, keyed-load, store, keyed-store). 585 Map* FindFirstMap() const { 586 MapHandles maps; 587 ExtractMaps(&maps); 588 if (maps.size() > 0) return *maps.at(0); 589 return nullptr; 590 } 591 592 InlineCacheState StateFromFeedback() const; 593 int ExtractMaps(MapHandles* maps) const; 594 MaybeObjectHandle FindHandlerForMap(Handle<Map> map) const; 595 bool FindHandlers(MaybeObjectHandles* code_list, int length = -1) const; 596 597 bool IsCleared() const { 598 InlineCacheState state = StateFromFeedback(); 599 return !FLAG_use_ic || state == UNINITIALIZED || state == PREMONOMORPHIC; 600 } 601 602 // Clear() returns true if the state of the underlying vector was changed. 603 bool Clear(); 604 void ConfigureUninitialized(); 605 void ConfigurePremonomorphic(Handle<Map> receiver_map); 606 // ConfigureMegamorphic() returns true if the state of the underlying vector 607 // was changed. Extra feedback is cleared if the 0 parameter version is used. 608 bool ConfigureMegamorphic(); 609 bool ConfigureMegamorphic(IcCheckType property_type); 610 611 inline MaybeObject* GetFeedback() const; 612 inline MaybeObject* GetFeedbackExtra() const; 613 614 inline Isolate* GetIsolate() const; 615 616 void ConfigureMonomorphic(Handle<Name> name, Handle<Map> receiver_map, 617 const MaybeObjectHandle& handler); 618 619 void ConfigurePolymorphic(Handle<Name> name, MapHandles const& maps, 620 MaybeObjectHandles* handlers); 621 622 BinaryOperationHint GetBinaryOperationFeedback() const; 623 CompareOperationHint GetCompareOperationFeedback() const; 624 ForInHint GetForInFeedback() const; 625 626 // For KeyedLoad ICs. 627 KeyedAccessLoadMode GetKeyedAccessLoadMode() const; 628 629 // For KeyedStore ICs. 630 KeyedAccessStoreMode GetKeyedAccessStoreMode() const; 631 632 // For KeyedLoad and KeyedStore ICs. 633 IcCheckType GetKeyType() const; 634 Name* FindFirstName() const; 635 636 // For Call ICs. 637 int GetCallCount(); 638 void SetSpeculationMode(SpeculationMode mode); 639 SpeculationMode GetSpeculationMode(); 640 641 // Compute the call frequency based on the call count and the invocation 642 // count (taken from the type feedback vector). 643 float ComputeCallFrequency(); 644 645 typedef BitField<SpeculationMode, 0, 1> SpeculationModeField; 646 typedef BitField<uint32_t, 1, 31> CallCountField; 647 648 // For CreateClosure ICs. 649 Handle<FeedbackCell> GetFeedbackCell() const; 650 651 // For InstanceOf ICs. 652 MaybeHandle<JSObject> GetConstructorFeedback() const; 653 654 // For Global Load and Store ICs. 655 void ConfigurePropertyCellMode(Handle<PropertyCell> cell); 656 // Returns false if given combination of indices is not allowed. 657 bool ConfigureLexicalVarMode(int script_context_index, 658 int context_slot_index); 659 void ConfigureHandlerMode(const MaybeObjectHandle& handler); 660 661 // For CloneObject ICs 662 static constexpr int kCloneObjectPolymorphicEntrySize = 2; 663 void ConfigureCloneObject(Handle<Map> source_map, Handle<Map> result_map); 664 665 // Bit positions in a smi that encodes lexical environment variable access. 666 #define LEXICAL_MODE_BIT_FIELDS(V, _) \ 667 V(ContextIndexBits, unsigned, 12, _) \ 668 V(SlotIndexBits, unsigned, 19, _) 669 670 DEFINE_BIT_FIELDS(LEXICAL_MODE_BIT_FIELDS) 671 #undef LEXICAL_MODE_BIT_FIELDS 672 673 // Make sure we don't overflow the smi. 674 STATIC_ASSERT(LEXICAL_MODE_BIT_FIELDS_Ranges::kBitsCount <= kSmiValueSize); 675 676 // For TypeProfile feedback vector slots. 677 // ResetTypeProfile will always reset type profile information. 678 void ResetTypeProfile(); 679 680 // Add a type to the list of types for source position <position>. 681 void Collect(Handle<String> type, int position); 682 JSObject* GetTypeProfile() const; 683 684 std::vector<int> GetSourcePositions() const; 685 std::vector<Handle<String>> GetTypesForSourcePositions(uint32_t pos) const; 686 687 inline void SetFeedback(Object* feedback, 688 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 689 inline void SetFeedback(MaybeObject* feedback, 690 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 691 inline void SetFeedbackExtra(Object* feedback_extra, 692 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 693 inline void SetFeedbackExtra(MaybeObject* feedback_extra, 694 WriteBarrierMode mode = UPDATE_WRITE_BARRIER); 695 696 Handle<WeakFixedArray> EnsureArrayOfSize(int length); 697 Handle<WeakFixedArray> EnsureExtraArrayOfSize(int length); 698 699 private: 700 // The reason for having a vector handle and a raw pointer is that we can and 701 // should use handles during IC miss, but not during GC when we clear ICs. If 702 // you have a handle to the vector that is better because more operations can 703 // be done, like allocation. 704 Handle<FeedbackVector> vector_handle_; 705 FeedbackVector* vector_; 706 FeedbackSlot slot_; 707 FeedbackSlotKind kind_; 708 }; 709 710 inline BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback); 711 inline CompareOperationHint CompareOperationHintFromFeedback(int type_feedback); 712 inline ForInHint ForInHintFromFeedback(int type_feedback); 713 714 } // namespace internal 715 } // namespace v8 716 717 #endif // V8_FEEDBACK_VECTOR_H_ 718