LCOV - code coverage report
Current view: top level - src - feedback-vector.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 364 421 86.5 %
Date: 2017-10-20 Functions: 58 67 86.6 %

          Line data    Source code
       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             : #include "src/feedback-vector.h"
       6             : #include "src/code-stubs.h"
       7             : #include "src/feedback-vector-inl.h"
       8             : #include "src/ic/ic-inl.h"
       9             : #include "src/objects.h"
      10             : #include "src/objects/object-macros.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : template <typename Derived>
      16    19422544 : FeedbackSlot FeedbackVectorSpecBase<Derived>::AddSlot(FeedbackSlotKind kind) {
      17           0 :   int slot = This()->slots();
      18    19422544 :   int entries_per_slot = FeedbackMetadata::GetSlotSize(kind);
      19             :   This()->append(kind);
      20    32018893 :   for (int i = 1; i < entries_per_slot; i++) {
      21             :     This()->append(FeedbackSlotKind::kInvalid);
      22             :   }
      23    19422549 :   return FeedbackSlot(slot);
      24             : }
      25             : 
      26             : template FeedbackSlot FeedbackVectorSpecBase<FeedbackVectorSpec>::AddSlot(
      27             :     FeedbackSlotKind kind);
      28             : template FeedbackSlot FeedbackVectorSpecBase<StaticFeedbackVectorSpec>::AddSlot(
      29             :     FeedbackSlotKind kind);
      30             : 
      31             : template <typename Derived>
      32          85 : FeedbackSlot FeedbackVectorSpecBase<Derived>::AddTypeProfileSlot() {
      33          85 :   FeedbackSlot slot = AddSlot(FeedbackSlotKind::kTypeProfile);
      34          85 :   CHECK_EQ(FeedbackVectorSpec::kTypeProfileSlotIndex,
      35             :            FeedbackVector::GetIndex(slot));
      36          85 :   return slot;
      37             : }
      38             : 
      39             : template FeedbackSlot
      40             : FeedbackVectorSpecBase<FeedbackVectorSpec>::AddTypeProfileSlot();
      41             : template FeedbackSlot
      42             : FeedbackVectorSpecBase<StaticFeedbackVectorSpec>::AddTypeProfileSlot();
      43             : 
      44           0 : bool FeedbackVectorSpec::HasTypeProfileSlot() const {
      45             :   FeedbackSlot slot =
      46             :       FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
      47           0 :   if (slots() <= slot.ToInt()) {
      48             :     return false;
      49             :   }
      50           0 :   return GetKind(slot) == FeedbackSlotKind::kTypeProfile;
      51             : }
      52             : 
      53     2680638 : static bool IsPropertyNameFeedback(Object* feedback) {
      54     2680638 :   if (feedback->IsString()) return true;
      55     2642368 :   if (!feedback->IsSymbol()) return false;
      56             :   Symbol* symbol = Symbol::cast(feedback);
      57      562493 :   Heap* heap = symbol->GetHeap();
      58       49957 :   return symbol != heap->uninitialized_symbol() &&
      59      512536 :          symbol != heap->premonomorphic_symbol() &&
      60      491746 :          symbol != heap->megamorphic_symbol();
      61             : }
      62             : 
      63           0 : std::ostream& operator<<(std::ostream& os, FeedbackSlotKind kind) {
      64           0 :   return os << FeedbackMetadata::Kind2String(kind);
      65             : }
      66             : 
      67    70923692 : FeedbackSlotKind FeedbackMetadata::GetKind(FeedbackSlot slot) const {
      68             :   int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
      69             :   int data = Smi::ToInt(get(index));
      70   141847384 :   return VectorICComputer::decode(data, slot.ToInt());
      71             : }
      72             : 
      73    32012723 : void FeedbackMetadata::SetKind(FeedbackSlot slot, FeedbackSlotKind kind) {
      74             :   int index = VectorICComputer::index(kReservedIndexCount, slot.ToInt());
      75             :   int data = Smi::ToInt(get(index));
      76    64025446 :   int new_data = VectorICComputer::encode(data, slot.ToInt(), kind);
      77             :   set(index, Smi::FromInt(new_data));
      78    32012723 : }
      79             : 
      80             : template Handle<FeedbackMetadata> FeedbackMetadata::New(
      81             :     Isolate* isolate, const StaticFeedbackVectorSpec* spec);
      82             : template Handle<FeedbackMetadata> FeedbackMetadata::New(
      83             :     Isolate* isolate, const FeedbackVectorSpec* spec);
      84             : 
      85             : // static
      86             : template <typename Spec>
      87    11529722 : Handle<FeedbackMetadata> FeedbackMetadata::New(Isolate* isolate,
      88             :                                                const Spec* spec) {
      89             :   Factory* factory = isolate->factory();
      90             : 
      91             :   const int slot_count = spec->slots();
      92             :   const int slot_kinds_length = VectorICComputer::word_count(slot_count);
      93    11529722 :   const int length = slot_kinds_length + kReservedIndexCount;
      94    11529722 :   if (length == kReservedIndexCount) {
      95             :     return Handle<FeedbackMetadata>::cast(factory->empty_fixed_array());
      96             :   }
      97             : #ifdef DEBUG
      98             :   for (int i = 0; i < slot_count;) {
      99             :     FeedbackSlotKind kind = spec->GetKind(FeedbackSlot(i));
     100             :     int entry_size = FeedbackMetadata::GetSlotSize(kind);
     101             :     for (int j = 1; j < entry_size; j++) {
     102             :       FeedbackSlotKind kind = spec->GetKind(FeedbackSlot(i + j));
     103             :       DCHECK_EQ(FeedbackSlotKind::kInvalid, kind);
     104             :     }
     105             :     i += entry_size;
     106             :   }
     107             : #endif
     108             : 
     109     1662825 :   Handle<FixedArray> array = factory->NewFixedArray(length, TENURED);
     110             :   array->set(kSlotsCountIndex, Smi::FromInt(slot_count));
     111             :   // Fill the bit-vector part with zeros.
     112     7925721 :   for (int i = 0; i < slot_kinds_length; i++) {
     113             :     array->set(kReservedIndexCount + i, Smi::kZero);
     114             :   }
     115             : 
     116             :   Handle<FeedbackMetadata> metadata = Handle<FeedbackMetadata>::cast(array);
     117             : 
     118    32012721 :   for (int i = 0; i < slot_count; i++) {
     119             :     FeedbackSlot slot(i);
     120             :     FeedbackSlotKind kind = spec->GetKind(slot);
     121    32012722 :     metadata->SetKind(slot, kind);
     122             :   }
     123             : 
     124             :   // It's important that the FeedbackMetadata have a COW map, since it's
     125             :   // pointed to by both a SharedFunctionInfo and indirectly by closures through
     126             :   // the FeedbackVector. The serializer uses the COW map type to decide
     127             :   // this object belongs in the startup snapshot and not the partial
     128             :   // snapshot(s).
     129     3325650 :   metadata->set_map(isolate->heap()->fixed_cow_array_map());
     130             : 
     131     1662825 :   return metadata;
     132             : }
     133             : 
     134     2134855 : bool FeedbackMetadata::SpecDiffersFrom(
     135             :     const FeedbackVectorSpec* other_spec) const {
     136     2134855 :   if (other_spec->slots() != slot_count()) {
     137             :     return true;
     138             :   }
     139             : 
     140     2134855 :   int slots = slot_count();
     141    23662428 :   for (int i = 0; i < slots;) {
     142             :     FeedbackSlot slot(i);
     143    19392709 :     FeedbackSlotKind kind = GetKind(slot);
     144    19392709 :     int entry_size = FeedbackMetadata::GetSlotSize(kind);
     145             : 
     146    19392717 :     if (kind != other_spec->GetKind(slot)) {
     147             :       return true;
     148             :     }
     149    19392718 :     i += entry_size;
     150             :   }
     151             :   return false;
     152             : }
     153             : 
     154           0 : const char* FeedbackMetadata::Kind2String(FeedbackSlotKind kind) {
     155           0 :   switch (kind) {
     156             :     case FeedbackSlotKind::kInvalid:
     157             :       return "Invalid";
     158             :     case FeedbackSlotKind::kCall:
     159           0 :       return "Call";
     160             :     case FeedbackSlotKind::kLoadProperty:
     161           0 :       return "LoadProperty";
     162             :     case FeedbackSlotKind::kLoadGlobalInsideTypeof:
     163           0 :       return "LoadGlobalInsideTypeof";
     164             :     case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
     165           0 :       return "LoadGlobalNotInsideTypeof";
     166             :     case FeedbackSlotKind::kLoadKeyed:
     167           0 :       return "LoadKeyed";
     168             :     case FeedbackSlotKind::kStoreNamedSloppy:
     169           0 :       return "StoreNamedSloppy";
     170             :     case FeedbackSlotKind::kStoreNamedStrict:
     171           0 :       return "StoreNamedStrict";
     172             :     case FeedbackSlotKind::kStoreOwnNamed:
     173           0 :       return "StoreOwnNamed";
     174             :     case FeedbackSlotKind::kStoreGlobalSloppy:
     175           0 :       return "StoreGlobalSloppy";
     176             :     case FeedbackSlotKind::kStoreGlobalStrict:
     177           0 :       return "StoreGlobalStrict";
     178             :     case FeedbackSlotKind::kStoreKeyedSloppy:
     179           0 :       return "StoreKeyedSloppy";
     180             :     case FeedbackSlotKind::kStoreKeyedStrict:
     181           0 :       return "StoreKeyedStrict";
     182             :     case FeedbackSlotKind::kBinaryOp:
     183           0 :       return "BinaryOp";
     184             :     case FeedbackSlotKind::kCompareOp:
     185           0 :       return "CompareOp";
     186             :     case FeedbackSlotKind::kStoreDataPropertyInLiteral:
     187           0 :       return "StoreDataPropertyInLiteral";
     188             :     case FeedbackSlotKind::kCreateClosure:
     189           0 :       return "kCreateClosure";
     190             :     case FeedbackSlotKind::kLiteral:
     191           0 :       return "Literal";
     192             :     case FeedbackSlotKind::kTypeProfile:
     193           0 :       return "TypeProfile";
     194             :     case FeedbackSlotKind::kForIn:
     195           0 :       return "ForIn";
     196             :     case FeedbackSlotKind::kKindsNumber:
     197             :       break;
     198             :   }
     199           0 :   UNREACHABLE();
     200             : }
     201             : 
     202         901 : bool FeedbackMetadata::HasTypeProfileSlot() const {
     203             :   FeedbackSlot slot =
     204             :       FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
     205        1762 :   return slot.ToInt() < this->length() &&
     206        1762 :          GetKind(slot) == FeedbackSlotKind::kTypeProfile;
     207             : }
     208             : 
     209    21034289 : FeedbackSlotKind FeedbackVector::GetKind(FeedbackSlot slot) const {
     210             :   DCHECK(!is_empty());
     211    21034289 :   return metadata()->GetKind(slot);
     212             : }
     213             : 
     214         570 : FeedbackSlot FeedbackVector::GetTypeProfileSlot() const {
     215             :   DCHECK(metadata()->HasTypeProfileSlot());
     216             :   FeedbackSlot slot =
     217             :       FeedbackVector::ToSlot(FeedbackVectorSpec::kTypeProfileSlotIndex);
     218             :   DCHECK_EQ(FeedbackSlotKind::kTypeProfile, GetKind(slot));
     219         570 :   return slot;
     220             : }
     221             : 
     222             : // static
     223     6329861 : Handle<FeedbackVector> FeedbackVector::New(Isolate* isolate,
     224             :                                            Handle<SharedFunctionInfo> shared) {
     225             :   Factory* factory = isolate->factory();
     226             : 
     227     6329861 :   const int slot_count = shared->feedback_metadata()->slot_count();
     228             : 
     229     6329862 :   Handle<FeedbackVector> vector = factory->NewFeedbackVector(shared, TENURED);
     230             : 
     231             :   DCHECK_EQ(vector->length(), slot_count);
     232             : 
     233             :   DCHECK_EQ(vector->shared_function_info(), *shared);
     234             :   DCHECK_EQ(vector->optimized_code_cell(),
     235             :             Smi::FromEnum(OptimizationMarker::kNone));
     236             :   DCHECK_EQ(vector->invocation_count(), 0);
     237             :   DCHECK_EQ(vector->profiler_ticks(), 0);
     238             :   DCHECK_EQ(vector->deopt_count(), 0);
     239             : 
     240             :   // Ensure we can skip the write barrier
     241             :   Handle<Object> uninitialized_sentinel = UninitializedSentinel(isolate);
     242             :   DCHECK_EQ(isolate->heap()->uninitialized_symbol(), *uninitialized_sentinel);
     243             :   Handle<Oddball> undefined_value = factory->undefined_value();
     244    42921934 :   for (int i = 0; i < slot_count;) {
     245             :     FeedbackSlot slot(i);
     246    30262210 :     FeedbackSlotKind kind = shared->feedback_metadata()->GetKind(slot);
     247             :     int index = FeedbackVector::GetIndex(slot);
     248    30262209 :     int entry_size = FeedbackMetadata::GetSlotSize(kind);
     249             : 
     250             :     Object* extra_value = *uninitialized_sentinel;
     251    30262209 :     switch (kind) {
     252             :       case FeedbackSlotKind::kLoadGlobalInsideTypeof:
     253             :       case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
     254     4869406 :         vector->set(index, isolate->heap()->empty_weak_cell(),
     255     4869406 :                     SKIP_WRITE_BARRIER);
     256     4869406 :         break;
     257             :       case FeedbackSlotKind::kForIn:
     258             :       case FeedbackSlotKind::kCompareOp:
     259             :       case FeedbackSlotKind::kBinaryOp:
     260     3226193 :         vector->set(index, Smi::kZero, SKIP_WRITE_BARRIER);
     261     3226193 :         break;
     262             :       case FeedbackSlotKind::kCreateClosure: {
     263     6100498 :         Handle<Cell> cell = factory->NewNoClosuresCell(undefined_value);
     264     6100498 :         vector->set(index, *cell);
     265             :         break;
     266             :       }
     267             :       case FeedbackSlotKind::kLiteral:
     268      951892 :         vector->set(index, Smi::kZero, SKIP_WRITE_BARRIER);
     269      951892 :         break;
     270             :       case FeedbackSlotKind::kCall:
     271     4790711 :         vector->set(index, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
     272             :         extra_value = Smi::kZero;
     273     4790711 :         break;
     274             :       case FeedbackSlotKind::kLoadProperty:
     275             :       case FeedbackSlotKind::kLoadKeyed:
     276             :       case FeedbackSlotKind::kStoreNamedSloppy:
     277             :       case FeedbackSlotKind::kStoreNamedStrict:
     278             :       case FeedbackSlotKind::kStoreOwnNamed:
     279             :       case FeedbackSlotKind::kStoreGlobalSloppy:
     280             :       case FeedbackSlotKind::kStoreGlobalStrict:
     281             :       case FeedbackSlotKind::kStoreKeyedSloppy:
     282             :       case FeedbackSlotKind::kStoreKeyedStrict:
     283             :       case FeedbackSlotKind::kStoreDataPropertyInLiteral:
     284             :       case FeedbackSlotKind::kTypeProfile:
     285    10323509 :         vector->set(index, *uninitialized_sentinel, SKIP_WRITE_BARRIER);
     286    10323509 :         break;
     287             : 
     288             :       case FeedbackSlotKind::kInvalid:
     289             :       case FeedbackSlotKind::kKindsNumber:
     290           0 :         UNREACHABLE();
     291             :         break;
     292             :     }
     293    50245736 :     for (int j = 1; j < entry_size; j++) {
     294    39967052 :       vector->set(index + j, extra_value, SKIP_WRITE_BARRIER);
     295             :     }
     296    30262210 :     i += entry_size;
     297             :   }
     298             : 
     299             :   Handle<FeedbackVector> result = Handle<FeedbackVector>::cast(vector);
     300    12658550 :   if (!isolate->is_best_effort_code_coverage() ||
     301             :       isolate->is_collecting_type_profile()) {
     302        1605 :     AddToVectorsForProfilingTools(isolate, result);
     303             :   }
     304     6329862 :   return result;
     305             : }
     306             : 
     307             : // static
     308           0 : Handle<FeedbackVector> FeedbackVector::Copy(Isolate* isolate,
     309             :                                             Handle<FeedbackVector> vector) {
     310             :   Handle<FeedbackVector> result;
     311             :   result = Handle<FeedbackVector>::cast(
     312           0 :       isolate->factory()->CopyFixedArray(Handle<FixedArray>::cast(vector)));
     313           0 :   if (!isolate->is_best_effort_code_coverage() ||
     314             :       isolate->is_collecting_type_profile()) {
     315           0 :     AddToVectorsForProfilingTools(isolate, result);
     316             :   }
     317           0 :   return result;
     318             : }
     319             : 
     320             : // static
     321        1605 : void FeedbackVector::AddToVectorsForProfilingTools(
     322             :     Isolate* isolate, Handle<FeedbackVector> vector) {
     323             :   DCHECK(!isolate->is_best_effort_code_coverage() ||
     324             :          isolate->is_collecting_type_profile());
     325        3210 :   if (!vector->shared_function_info()->IsSubjectToDebugging()) return;
     326             :   Handle<ArrayList> list = Handle<ArrayList>::cast(
     327             :       isolate->factory()->feedback_vectors_for_profiling_tools());
     328        1275 :   list = ArrayList::Add(list, vector);
     329        1275 :   isolate->SetFeedbackVectorsForProfilingTools(*list);
     330             : }
     331             : 
     332             : // static
     333       18557 : void FeedbackVector::SetOptimizedCode(Handle<FeedbackVector> vector,
     334             :                                       Handle<Code> code) {
     335             :   DCHECK_EQ(code->kind(), Code::OPTIMIZED_FUNCTION);
     336             :   Factory* factory = vector->GetIsolate()->factory();
     337       18557 :   Handle<WeakCell> cell = factory->NewWeakCell(code);
     338       18557 :   vector->set_optimized_code_cell(*cell);
     339       18557 : }
     340             : 
     341      673541 : void FeedbackVector::SetOptimizationMarker(OptimizationMarker marker) {
     342      673541 :   set_optimized_code_cell(Smi::FromEnum(marker));
     343      673541 : }
     344             : 
     345      413852 : void FeedbackVector::ClearOptimizedCode() {
     346      416059 :   set_optimized_code_cell(Smi::FromEnum(OptimizationMarker::kNone));
     347      413853 : }
     348             : 
     349     4546278 : void FeedbackVector::EvictOptimizedCodeMarkedForDeoptimization(
     350             :     SharedFunctionInfo* shared, const char* reason) {
     351             :   Object* slot = optimized_code_cell();
     352     4546278 :   if (slot->IsSmi()) return;
     353             : 
     354             :   WeakCell* cell = WeakCell::cast(slot);
     355      496396 :   if (cell->cleared()) {
     356             :     ClearOptimizedCode();
     357             :     return;
     358             :   }
     359             : 
     360             :   Code* code = Code::cast(cell->value());
     361      496160 :   if (code->marked_for_deoptimization()) {
     362        1971 :     if (FLAG_trace_deopt) {
     363             :       PrintF("[evicting optimizing code marked for deoptimization (%s) for ",
     364           0 :              reason);
     365           0 :       shared->ShortPrint();
     366           0 :       PrintF("]\n");
     367             :     }
     368        1971 :     if (!code->deopt_already_counted()) {
     369             :       increment_deopt_count();
     370             :       code->set_deopt_already_counted(true);
     371             :     }
     372             :     ClearOptimizedCode();
     373             :   }
     374             : }
     375             : 
     376       67308 : bool FeedbackVector::ClearSlots(Isolate* isolate) {
     377             :   Object* uninitialized_sentinel =
     378             :       FeedbackVector::RawUninitializedSentinel(isolate);
     379             : 
     380             :   bool feedback_updated = false;
     381             :   FeedbackMetadataIterator iter(metadata());
     382      300468 :   while (iter.HasNext()) {
     383      233160 :     FeedbackSlot slot = iter.Next();
     384      233160 :     FeedbackSlotKind kind = iter.kind();
     385             : 
     386             :     Object* obj = Get(slot);
     387      233160 :     if (obj != uninitialized_sentinel) {
     388      193040 :       switch (kind) {
     389             :         case FeedbackSlotKind::kCall: {
     390             :           CallICNexus nexus(this, slot);
     391        7701 :           if (!nexus.IsCleared()) {
     392             :             nexus.Clear();
     393             :             feedback_updated = true;
     394             :           }
     395             :           break;
     396             :         }
     397             :         case FeedbackSlotKind::kLoadProperty: {
     398             :           LoadICNexus nexus(this, slot);
     399       39173 :           if (!nexus.IsCleared()) {
     400             :             nexus.Clear();
     401             :             feedback_updated = true;
     402             :           }
     403             :           break;
     404             :         }
     405             :         case FeedbackSlotKind::kLoadGlobalInsideTypeof:
     406             :         case FeedbackSlotKind::kLoadGlobalNotInsideTypeof: {
     407             :           LoadGlobalICNexus nexus(this, slot);
     408        6749 :           if (!nexus.IsCleared()) {
     409             :             nexus.Clear();
     410             :             feedback_updated = true;
     411             :           }
     412             :           break;
     413             :         }
     414             :         case FeedbackSlotKind::kLoadKeyed: {
     415             :           KeyedLoadICNexus nexus(this, slot);
     416        4837 :           if (!nexus.IsCleared()) {
     417             :             nexus.Clear();
     418             :             feedback_updated = true;
     419             :           }
     420             :           break;
     421             :         }
     422             :         case FeedbackSlotKind::kStoreNamedSloppy:
     423             :         case FeedbackSlotKind::kStoreNamedStrict:
     424             :         case FeedbackSlotKind::kStoreOwnNamed:
     425             :         case FeedbackSlotKind::kStoreGlobalSloppy:
     426             :         case FeedbackSlotKind::kStoreGlobalStrict: {
     427             :           StoreICNexus nexus(this, slot);
     428       59863 :           if (!nexus.IsCleared()) {
     429             :             nexus.Clear();
     430             :             feedback_updated = true;
     431             :           }
     432             :           break;
     433             :         }
     434             :         case FeedbackSlotKind::kStoreKeyedSloppy:
     435             :         case FeedbackSlotKind::kStoreKeyedStrict: {
     436             :           KeyedStoreICNexus nexus(this, slot);
     437        4003 :           if (!nexus.IsCleared()) {
     438             :             nexus.Clear();
     439             :             feedback_updated = true;
     440             :           }
     441             :           break;
     442             :         }
     443             :         case FeedbackSlotKind::kForIn:
     444             :         case FeedbackSlotKind::kBinaryOp:
     445             :         case FeedbackSlotKind::kCompareOp: {
     446             :           DCHECK(Get(slot)->IsSmi());
     447             :           // don't clear these smi slots.
     448             :           // Set(slot, Smi::kZero);
     449             :           break;
     450             :         }
     451             :         case FeedbackSlotKind::kCreateClosure: {
     452             :           case FeedbackSlotKind::kTypeProfile:
     453             :             break;
     454             :         }
     455             :         case FeedbackSlotKind::kLiteral: {
     456             :           Set(slot, Smi::kZero, SKIP_WRITE_BARRIER);
     457             :           feedback_updated = true;
     458        3663 :           break;
     459             :         }
     460             :         case FeedbackSlotKind::kStoreDataPropertyInLiteral: {
     461             :           StoreDataPropertyInLiteralICNexus nexus(this, slot);
     462         473 :           if (!nexus.IsCleared()) {
     463             :             nexus.Clear();
     464             :             feedback_updated = true;
     465             :           }
     466             :           break;
     467             :         }
     468             :         case FeedbackSlotKind::kInvalid:
     469             :         case FeedbackSlotKind::kKindsNumber:
     470           0 :           UNREACHABLE();
     471             :           break;
     472             :       }
     473             :     }
     474             :   }
     475       67308 :   return feedback_updated;
     476             : }
     477             : 
     478      284727 : Handle<FixedArray> FeedbackNexus::EnsureArrayOfSize(int length) {
     479             :   Isolate* isolate = GetIsolate();
     480      284727 :   Handle<Object> feedback = handle(GetFeedback(), isolate);
     481      396262 :   if (!feedback->IsFixedArray() ||
     482             :       FixedArray::cast(*feedback)->length() != length) {
     483      279186 :     Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
     484      279186 :     SetFeedback(*array);
     485      279186 :     return array;
     486             :   }
     487             :   return Handle<FixedArray>::cast(feedback);
     488             : }
     489             : 
     490       29599 : Handle<FixedArray> FeedbackNexus::EnsureExtraArrayOfSize(int length) {
     491             :   Isolate* isolate = GetIsolate();
     492       29599 :   Handle<Object> feedback_extra = handle(GetFeedbackExtra(), isolate);
     493       34343 :   if (!feedback_extra->IsFixedArray() ||
     494             :       FixedArray::cast(*feedback_extra)->length() != length) {
     495       28920 :     Handle<FixedArray> array = isolate->factory()->NewFixedArray(length);
     496       28920 :     SetFeedbackExtra(*array);
     497       28920 :     return array;
     498             :   }
     499             :   return Handle<FixedArray>::cast(feedback_extra);
     500             : }
     501             : 
     502         473 : void FeedbackNexus::ConfigureUninitialized() {
     503             :   SetFeedback(*FeedbackVector::UninitializedSentinel(GetIsolate()),
     504         473 :               SKIP_WRITE_BARRIER);
     505             :   SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(GetIsolate()),
     506         473 :                    SKIP_WRITE_BARRIER);
     507         473 : }
     508             : 
     509     3590930 : void FeedbackNexus::ConfigurePremonomorphic() {
     510             :   SetFeedback(*FeedbackVector::PremonomorphicSentinel(GetIsolate()),
     511     3590930 :               SKIP_WRITE_BARRIER);
     512             :   SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(GetIsolate()),
     513     3590930 :                    SKIP_WRITE_BARRIER);
     514     3590930 : }
     515             : 
     516       90372 : void FeedbackNexus::ConfigureMegamorphic(IcCheckType property_type) {
     517             :   Isolate* isolate = GetIsolate();
     518             :   SetFeedback(*FeedbackVector::MegamorphicSentinel(isolate),
     519       90372 :               SKIP_WRITE_BARRIER);
     520       90372 :   SetFeedbackExtra(Smi::FromInt(static_cast<int>(property_type)),
     521       90372 :                    SKIP_WRITE_BARRIER);
     522       90372 : }
     523             : 
     524     2554251 : InlineCacheState LoadICNexus::StateFromFeedback() const {
     525             :   Isolate* isolate = GetIsolate();
     526     2554251 :   Object* feedback = GetFeedback();
     527             : 
     528     2554252 :   if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
     529             :     return UNINITIALIZED;
     530     1764248 :   } else if (feedback == *FeedbackVector::MegamorphicSentinel(isolate)) {
     531             :     return MEGAMORPHIC;
     532     1452220 :   } else if (feedback == *FeedbackVector::PremonomorphicSentinel(isolate)) {
     533             :     return PREMONOMORPHIC;
     534      549780 :   } else if (feedback->IsFixedArray()) {
     535             :     // Determine state purely by our structure, don't check if the maps are
     536             :     // cleared.
     537             :     return POLYMORPHIC;
     538      407120 :   } else if (feedback->IsWeakCell()) {
     539             :     // Don't check if the map is cleared.
     540             :     return MONOMORPHIC;
     541             :   }
     542             : 
     543           0 :   return UNINITIALIZED;
     544             : }
     545             : 
     546     1889630 : InlineCacheState LoadGlobalICNexus::StateFromFeedback() const {
     547             :   Isolate* isolate = GetIsolate();
     548     1889630 :   Object* feedback = GetFeedback();
     549             : 
     550     1889630 :   Object* extra = GetFeedbackExtra();
     551     3772534 :   if (!WeakCell::cast(feedback)->cleared() ||
     552             :       extra != *FeedbackVector::UninitializedSentinel(isolate)) {
     553             :     return MONOMORPHIC;
     554             :   }
     555     1882701 :   return UNINITIALIZED;
     556             : }
     557             : 
     558      382037 : InlineCacheState KeyedLoadICNexus::StateFromFeedback() const {
     559             :   Isolate* isolate = GetIsolate();
     560      382037 :   Object* feedback = GetFeedback();
     561             : 
     562      382037 :   if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
     563             :     return UNINITIALIZED;
     564      160518 :   } else if (feedback == *FeedbackVector::PremonomorphicSentinel(isolate)) {
     565             :     return PREMONOMORPHIC;
     566      129561 :   } else if (feedback == *FeedbackVector::MegamorphicSentinel(isolate)) {
     567             :     return MEGAMORPHIC;
     568       93031 :   } else if (feedback->IsFixedArray()) {
     569             :     // Determine state purely by our structure, don't check if the maps are
     570             :     // cleared.
     571             :     return POLYMORPHIC;
     572       79156 :   } else if (feedback->IsWeakCell()) {
     573             :     // Don't check if the map is cleared.
     574             :     return MONOMORPHIC;
     575       16985 :   } else if (feedback->IsName()) {
     576       16985 :     Object* extra = GetFeedbackExtra();
     577             :     FixedArray* extra_array = FixedArray::cast(extra);
     578       16985 :     return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
     579             :   }
     580             : 
     581             :   return UNINITIALIZED;
     582             : }
     583             : 
     584     4656796 : InlineCacheState StoreICNexus::StateFromFeedback() const {
     585             :   Isolate* isolate = GetIsolate();
     586     4656796 :   Object* feedback = GetFeedback();
     587             : 
     588     4656796 :   if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
     589             :     return UNINITIALIZED;
     590     1183291 :   } else if (feedback == *FeedbackVector::MegamorphicSentinel(isolate)) {
     591             :     return MEGAMORPHIC;
     592      781495 :   } else if (feedback == *FeedbackVector::PremonomorphicSentinel(isolate)) {
     593             :     return PREMONOMORPHIC;
     594      320106 :   } else if (feedback->IsFixedArray()) {
     595             :     // Determine state purely by our structure, don't check if the maps are
     596             :     // cleared.
     597             :     return POLYMORPHIC;
     598      224434 :   } else if (feedback->IsWeakCell()) {
     599             :     // Don't check if the map is cleared.
     600             :     return MONOMORPHIC;
     601             :   }
     602             : 
     603           0 :   return UNINITIALIZED;
     604             : }
     605             : 
     606      412088 : InlineCacheState KeyedStoreICNexus::StateFromFeedback() const {
     607             :   Isolate* isolate = GetIsolate();
     608      412088 :   Object* feedback = GetFeedback();
     609             : 
     610      412088 :   if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
     611             :     return UNINITIALIZED;
     612       98219 :   } else if (feedback == *FeedbackVector::PremonomorphicSentinel(isolate)) {
     613             :     return PREMONOMORPHIC;
     614       89232 :   } else if (feedback == *FeedbackVector::MegamorphicSentinel(isolate)) {
     615             :     return MEGAMORPHIC;
     616       52094 :   } else if (feedback->IsFixedArray()) {
     617             :     // Determine state purely by our structure, don't check if the maps are
     618             :     // cleared.
     619             :     return POLYMORPHIC;
     620       44213 :   } else if (feedback->IsWeakCell()) {
     621             :     // Don't check if the map is cleared.
     622             :     return MONOMORPHIC;
     623        2675 :   } else if (feedback->IsName()) {
     624        2675 :     Object* extra = GetFeedbackExtra();
     625             :     FixedArray* extra_array = FixedArray::cast(extra);
     626        2675 :     return extra_array->length() > 2 ? POLYMORPHIC : MONOMORPHIC;
     627             :   }
     628             : 
     629             :   return UNINITIALIZED;
     630             : }
     631             : 
     632      538754 : InlineCacheState CallICNexus::StateFromFeedback() const {
     633             :   Isolate* isolate = GetIsolate();
     634      538754 :   Object* feedback = GetFeedback();
     635             :   DCHECK(GetFeedbackExtra() ==
     636             :              *FeedbackVector::UninitializedSentinel(isolate) ||
     637             :          GetFeedbackExtra()->IsSmi());
     638             : 
     639      538756 :   if (feedback == *FeedbackVector::MegamorphicSentinel(isolate)) {
     640             :     return GENERIC;
     641     1034231 :   } else if (feedback->IsAllocationSite() || feedback->IsWeakCell()) {
     642             :     return MONOMORPHIC;
     643             :   }
     644             : 
     645      334752 :   CHECK(feedback == *FeedbackVector::UninitializedSentinel(isolate));
     646             :   return UNINITIALIZED;
     647             : }
     648             : 
     649      618735 : int CallICNexus::ExtractCallCount() {
     650      618735 :   Object* call_count = GetFeedbackExtra();
     651      618735 :   CHECK(call_count->IsSmi());
     652             :   int value = Smi::ToInt(call_count);
     653      618735 :   return value;
     654             : }
     655             : 
     656      618715 : float CallICNexus::ComputeCallFrequency() {
     657      618715 :   double const invocation_count = vector()->invocation_count();
     658      618715 :   double const call_count = ExtractCallCount();
     659      618715 :   if (invocation_count == 0) {
     660             :     // Prevent division by 0.
     661             :     return 0.0f;
     662             :   }
     663      173219 :   return static_cast<float>(call_count / invocation_count);
     664             : }
     665             : 
     666        7701 : void CallICNexus::ConfigureUninitialized() {
     667             :   Isolate* isolate = GetIsolate();
     668             :   SetFeedback(*FeedbackVector::UninitializedSentinel(isolate),
     669        7701 :               SKIP_WRITE_BARRIER);
     670        7701 :   SetFeedbackExtra(Smi::kZero, SKIP_WRITE_BARRIER);
     671        7701 : }
     672             : 
     673        6325 : void LoadGlobalICNexus::ConfigureUninitialized() {
     674             :   Isolate* isolate = GetIsolate();
     675        6325 :   SetFeedback(isolate->heap()->empty_weak_cell(), SKIP_WRITE_BARRIER);
     676             :   SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
     677        6325 :                    SKIP_WRITE_BARRIER);
     678        6325 : }
     679             : 
     680     3274196 : void LoadGlobalICNexus::ConfigurePropertyCellMode(Handle<PropertyCell> cell) {
     681             :   Isolate* isolate = GetIsolate();
     682     6548394 :   SetFeedback(*isolate->factory()->NewWeakCell(cell));
     683             :   SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(isolate),
     684     3274198 :                    SKIP_WRITE_BARRIER);
     685     3274198 : }
     686             : 
     687       52292 : void LoadGlobalICNexus::ConfigureHandlerMode(Handle<Object> handler) {
     688       52292 :   SetFeedback(GetIsolate()->heap()->empty_weak_cell());
     689       52292 :   SetFeedbackExtra(*handler);
     690       52292 : }
     691             : 
     692     1722616 : void FeedbackNexus::ConfigureMonomorphic(Handle<Name> name,
     693             :                                          Handle<Map> receiver_map,
     694             :                                          Handle<Object> handler) {
     695     1722616 :   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
     696     1722616 :   if (name.is_null()) {
     697     1697290 :     SetFeedback(*cell);
     698     1697290 :     SetFeedbackExtra(*handler);
     699             :   } else {
     700       25326 :     Handle<FixedArray> array = EnsureExtraArrayOfSize(2);
     701       25326 :     SetFeedback(*name);
     702       25326 :     array->set(0, *cell);
     703       25326 :     array->set(1, *handler);
     704             :   }
     705     1722616 : }
     706             : 
     707      289000 : void FeedbackNexus::ConfigurePolymorphic(Handle<Name> name,
     708     1013492 :                                          MapHandles const& maps,
     709             :                                          ObjectHandles* handlers) {
     710      289000 :   int receiver_count = static_cast<int>(maps.size());
     711             :   DCHECK_GT(receiver_count, 1);
     712             :   Handle<FixedArray> array;
     713      289000 :   if (name.is_null()) {
     714      284727 :     array = EnsureArrayOfSize(receiver_count * 2);
     715             :     SetFeedbackExtra(*FeedbackVector::UninitializedSentinel(GetIsolate()),
     716      284727 :                      SKIP_WRITE_BARRIER);
     717             :   } else {
     718        4273 :     array = EnsureExtraArrayOfSize(receiver_count * 2);
     719        4273 :     SetFeedback(*name);
     720             :   }
     721             : 
     722     1013492 :   for (int current = 0; current < receiver_count; ++current) {
     723     1448984 :     Handle<Map> map = maps[current];
     724      724492 :     Handle<WeakCell> cell = Map::WeakCellForMap(map);
     725     1448984 :     array->set(current * 2, *cell);
     726     1448984 :     array->set(current * 2 + 1, *handlers->at(current));
     727             :   }
     728      289000 : }
     729             : 
     730     1242654 : int FeedbackNexus::ExtractMaps(MapHandles* maps) const {
     731             :   Isolate* isolate = GetIsolate();
     732     1242654 :   Object* feedback = GetFeedback();
     733     1242654 :   bool is_named_feedback = IsPropertyNameFeedback(feedback);
     734     1242654 :   if (feedback->IsFixedArray() || is_named_feedback) {
     735             :     int found = 0;
     736      234091 :     if (is_named_feedback) {
     737        6231 :       feedback = GetFeedbackExtra();
     738             :     }
     739             :     FixedArray* array = FixedArray::cast(feedback);
     740             :     const int increment = 2;
     741     1668704 :     for (int i = 0; i < array->length(); i += increment) {
     742             :       DCHECK(array->get(i)->IsWeakCell());
     743             :       WeakCell* cell = WeakCell::cast(array->get(i));
     744      600261 :       if (!cell->cleared()) {
     745             :         Map* map = Map::cast(cell->value());
     746      946146 :         maps->push_back(handle(map, isolate));
     747      473073 :         found++;
     748             :       }
     749             :     }
     750             :     return found;
     751     1008563 :   } else if (feedback->IsWeakCell()) {
     752             :     WeakCell* cell = WeakCell::cast(feedback);
     753      640186 :     if (!cell->cleared()) {
     754             :       Map* map = Map::cast(cell->value());
     755      885860 :       maps->push_back(handle(map, isolate));
     756      442930 :       return 1;
     757             :     }
     758             :   }
     759             : 
     760             :   return 0;
     761             : }
     762             : 
     763      622836 : MaybeHandle<Object> FeedbackNexus::FindHandlerForMap(Handle<Map> map) const {
     764      622836 :   Object* feedback = GetFeedback();
     765             :   Isolate* isolate = GetIsolate();
     766      622836 :   bool is_named_feedback = IsPropertyNameFeedback(feedback);
     767      622836 :   if (feedback->IsFixedArray() || is_named_feedback) {
     768      203104 :     if (is_named_feedback) {
     769        2236 :       feedback = GetFeedbackExtra();
     770             :     }
     771             :     FixedArray* array = FixedArray::cast(feedback);
     772             :     const int increment = 2;
     773     1443888 :     for (int i = 0; i < array->length(); i += increment) {
     774             :       DCHECK(array->get(i)->IsWeakCell());
     775             :       WeakCell* cell = WeakCell::cast(array->get(i));
     776      520490 :       if (!cell->cleared()) {
     777             :         Map* array_map = Map::cast(cell->value());
     778      393625 :         if (array_map == *map) {
     779        1650 :           Object* code = array->get(i + increment - 1);
     780             :           DCHECK(IC::IsHandler(code));
     781        1650 :           return handle(code, isolate);
     782             :         }
     783             :       }
     784             :     }
     785      419732 :   } else if (feedback->IsWeakCell()) {
     786             :     WeakCell* cell = WeakCell::cast(feedback);
     787      419732 :     if (!cell->cleared()) {
     788             :       Map* cell_map = Map::cast(cell->value());
     789      227569 :       if (cell_map == *map) {
     790       40311 :         Object* code = GetFeedbackExtra();
     791             :         DCHECK(IC::IsHandler(code));
     792       40311 :         return handle(code, isolate);
     793             :       }
     794             :     }
     795             :   }
     796             : 
     797      580875 :   return MaybeHandle<Code>();
     798             : }
     799             : 
     800      645781 : bool FeedbackNexus::FindHandlers(ObjectHandles* code_list, int length) const {
     801      645781 :   Object* feedback = GetFeedback();
     802             :   Isolate* isolate = GetIsolate();
     803             :   int count = 0;
     804      645781 :   bool is_named_feedback = IsPropertyNameFeedback(feedback);
     805      645781 :   if (feedback->IsFixedArray() || is_named_feedback) {
     806      217126 :     if (is_named_feedback) {
     807        5565 :       feedback = GetFeedbackExtra();
     808             :     }
     809             :     FixedArray* array = FixedArray::cast(feedback);
     810             :     const int increment = 2;
     811     1627292 :     for (int i = 0; i < array->length(); i += increment) {
     812             :       DCHECK(array->get(i)->IsWeakCell());
     813             :       WeakCell* cell = WeakCell::cast(array->get(i));
     814             :       // Be sure to skip handlers whose maps have been cleared.
     815      596520 :       if (!cell->cleared()) {
     816      482704 :         Object* code = array->get(i + increment - 1);
     817             :         DCHECK(IC::IsHandler(code));
     818      965408 :         code_list->push_back(handle(code, isolate));
     819      482704 :         count++;
     820             :       }
     821             :     }
     822      428655 :   } else if (feedback->IsWeakCell()) {
     823             :     WeakCell* cell = WeakCell::cast(feedback);
     824      373691 :     if (!cell->cleared()) {
     825      221697 :       Object* code = GetFeedbackExtra();
     826             :       DCHECK(IC::IsHandler(code));
     827      443394 :       code_list->push_back(handle(code, isolate));
     828             :       count++;
     829             :     }
     830             :   }
     831      645781 :   return count == length;
     832             : }
     833             : 
     834       49746 : Name* KeyedLoadICNexus::FindFirstName() const {
     835       49746 :   Object* feedback = GetFeedback();
     836       49746 :   if (IsPropertyNameFeedback(feedback)) {
     837       32200 :     return Name::cast(feedback);
     838             :   }
     839             :   return nullptr;
     840             : }
     841             : 
     842       14744 : Name* KeyedStoreICNexus::FindFirstName() const {
     843       14744 :   Object* feedback = GetFeedback();
     844       14744 :   if (IsPropertyNameFeedback(feedback)) {
     845        4421 :     return Name::cast(feedback);
     846             :   }
     847             :   return nullptr;
     848             : }
     849             : 
     850       79476 : KeyedAccessStoreMode KeyedStoreICNexus::GetKeyedAccessStoreMode() const {
     851             :   KeyedAccessStoreMode mode = STANDARD_STORE;
     852             :   MapHandles maps;
     853             :   ObjectHandles handlers;
     854             : 
     855       79476 :   if (GetKeyType() == PROPERTY) return mode;
     856             : 
     857       78718 :   ExtractMaps(&maps);
     858      157436 :   FindHandlers(&handlers, static_cast<int>(maps.size()));
     859      157481 :   for (const Handle<Object>& maybe_code_handler : handlers) {
     860             :     // The first handler that isn't the slow handler will have the bits we need.
     861             :     Handle<Code> handler;
     862       23780 :     if (maybe_code_handler->IsTuple3()) {
     863             :       // Elements transition.
     864             :       Handle<Tuple3> data_handler = Handle<Tuple3>::cast(maybe_code_handler);
     865             :       handler = handle(Code::cast(data_handler->value2()));
     866       23736 :     } else if (maybe_code_handler->IsTuple2()) {
     867             :       // Element store with prototype chain check.
     868             :       Handle<Tuple2> data_handler = Handle<Tuple2>::cast(maybe_code_handler);
     869             :       handler = handle(Code::cast(data_handler->value2()));
     870         748 :     } else if (maybe_code_handler->IsSmi()) {
     871             :       // Skip proxy handlers.
     872             :       DCHECK_EQ(*maybe_code_handler, *StoreHandler::StoreProxy(GetIsolate()));
     873             :       continue;
     874             :     } else {
     875             :       // Element store without prototype chain check.
     876             :       handler = Handle<Code>::cast(maybe_code_handler);
     877         729 :       if (handler->is_builtin()) continue;
     878             :     }
     879             :     CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key());
     880             :     uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key());
     881       23735 :     CHECK(major_key == CodeStub::KeyedStoreSloppyArguments ||
     882             :           major_key == CodeStub::StoreFastElement ||
     883             :           major_key == CodeStub::StoreSlowElement ||
     884             :           major_key == CodeStub::ElementsTransitionAndStore ||
     885             :           major_key == CodeStub::NoCache);
     886       23735 :     if (major_key != CodeStub::NoCache) {
     887             :       mode = CommonStoreModeBits::decode(minor_key);
     888             :       break;
     889             :     }
     890             :   }
     891             : 
     892       78718 :   return mode;
     893             : }
     894             : 
     895       17515 : IcCheckType KeyedLoadICNexus::GetKeyType() const {
     896       17515 :   Object* feedback = GetFeedback();
     897       17515 :   if (feedback == *FeedbackVector::MegamorphicSentinel(GetIsolate())) {
     898        2466 :     return static_cast<IcCheckType>(Smi::ToInt(GetFeedbackExtra()));
     899             :   }
     900       16282 :   return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
     901             : }
     902             : 
     903       89752 : IcCheckType KeyedStoreICNexus::GetKeyType() const {
     904       89752 :   Object* feedback = GetFeedback();
     905       89752 :   if (feedback == *FeedbackVector::MegamorphicSentinel(GetIsolate())) {
     906        2312 :     return static_cast<IcCheckType>(Smi::ToInt(GetFeedbackExtra()));
     907             :   }
     908       88596 :   return IsPropertyNameFeedback(feedback) ? PROPERTY : ELEMENT;
     909             : }
     910             : 
     911      285222 : InlineCacheState BinaryOpICNexus::StateFromFeedback() const {
     912             :   BinaryOperationHint hint = GetBinaryOperationFeedback();
     913      285222 :   if (hint == BinaryOperationHint::kNone) {
     914             :     return UNINITIALIZED;
     915      271271 :   } else if (hint == BinaryOperationHint::kAny) {
     916             :     return GENERIC;
     917             :   }
     918             : 
     919      268208 :   return MONOMORPHIC;
     920             : }
     921             : 
     922      148176 : InlineCacheState CompareICNexus::StateFromFeedback() const {
     923             :   CompareOperationHint hint = GetCompareOperationFeedback();
     924      148176 :   if (hint == CompareOperationHint::kNone) {
     925             :     return UNINITIALIZED;
     926      131968 :   } else if (hint == CompareOperationHint::kAny) {
     927             :     return GENERIC;
     928             :   }
     929             : 
     930       98899 :   return MONOMORPHIC;
     931             : }
     932             : 
     933      713244 : BinaryOperationHint BinaryOpICNexus::GetBinaryOperationFeedback() const {
     934      998466 :   int feedback = Smi::ToInt(GetFeedback());
     935      713244 :   return BinaryOperationHintFromFeedback(feedback);
     936             : }
     937             : 
     938      397244 : CompareOperationHint CompareICNexus::GetCompareOperationFeedback() const {
     939      545420 :   int feedback = Smi::ToInt(GetFeedback());
     940      397244 :   return CompareOperationHintFromFeedback(feedback);
     941             : }
     942             : 
     943        1206 : InlineCacheState ForInICNexus::StateFromFeedback() const {
     944             :   ForInHint hint = GetForInFeedback();
     945        1206 :   if (hint == ForInHint::kNone) {
     946             :     return UNINITIALIZED;
     947        1170 :   } else if (hint == ForInHint::kAny) {
     948             :     return GENERIC;
     949             :   }
     950         516 :   return MONOMORPHIC;
     951             : }
     952             : 
     953        3222 : ForInHint ForInICNexus::GetForInFeedback() const {
     954        4428 :   int feedback = Smi::ToInt(GetFeedback());
     955        3222 :   return ForInHintFromFeedback(feedback);
     956             : }
     957             : 
     958      847839 : InlineCacheState StoreDataPropertyInLiteralICNexus::StateFromFeedback() const {
     959             :   Isolate* isolate = GetIsolate();
     960      847839 :   Object* feedback = GetFeedback();
     961             : 
     962      847839 :   if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
     963             :     return UNINITIALIZED;
     964      286165 :   } else if (feedback->IsWeakCell()) {
     965             :     // Don't check if the map is cleared.
     966             :     return MONOMORPHIC;
     967             :   }
     968             : 
     969       22196 :   return MEGAMORPHIC;
     970             : }
     971             : 
     972      506444 : void StoreDataPropertyInLiteralICNexus::ConfigureMonomorphic(
     973             :     Handle<Name> name, Handle<Map> receiver_map) {
     974      506444 :   Handle<WeakCell> cell = Map::WeakCellForMap(receiver_map);
     975             : 
     976      506444 :   SetFeedback(*cell);
     977      506444 :   SetFeedbackExtra(*name);
     978      506444 : }
     979             : 
     980           0 : InlineCacheState CollectTypeProfileNexus::StateFromFeedback() const {
     981             :   Isolate* isolate = GetIsolate();
     982           0 :   Object* const feedback = GetFeedback();
     983             : 
     984           0 :   if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
     985             :     return UNINITIALIZED;
     986             :   }
     987           0 :   return MONOMORPHIC;
     988             : }
     989             : 
     990             : namespace {
     991             : 
     992          80 : bool InList(Handle<ArrayList> types, Handle<String> type) {
     993         235 :   for (int i = 0; i < types->Length(); i++) {
     994             :     Object* obj = types->Get(i);
     995          95 :     if (String::cast(obj)->Equals(*type)) {
     996             :       return true;
     997             :     }
     998             :   }
     999             :   return false;
    1000             : }
    1001             : }  // anonymous namespace
    1002             : 
    1003         285 : void CollectTypeProfileNexus::Collect(Handle<String> type, int position) {
    1004             :   DCHECK_GE(position, 0);
    1005             :   Isolate* isolate = GetIsolate();
    1006             : 
    1007         285 :   Object* const feedback = GetFeedback();
    1008             : 
    1009             :   // Map source position to collection of types
    1010             :   Handle<UnseededNumberDictionary> types;
    1011             : 
    1012         285 :   if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
    1013          85 :     types = UnseededNumberDictionary::New(isolate, 1);
    1014             :   } else {
    1015             :     types = handle(UnseededNumberDictionary::cast(feedback));
    1016             :   }
    1017             : 
    1018             :   Handle<ArrayList> position_specific_types;
    1019             : 
    1020         285 :   int entry = types->FindEntry(position);
    1021         285 :   if (entry == UnseededNumberDictionary::kNotFound) {
    1022         205 :     position_specific_types = ArrayList::New(isolate, 1);
    1023             :     types = UnseededNumberDictionary::Set(
    1024         410 :         types, position, ArrayList::Add(position_specific_types, type));
    1025             :   } else {
    1026             :     DCHECK(types->ValueAt(entry)->IsArrayList());
    1027         160 :     position_specific_types = handle(ArrayList::cast(types->ValueAt(entry)));
    1028          80 :     if (!InList(position_specific_types, type)) {  // Add type
    1029             :       types = UnseededNumberDictionary::Set(
    1030         120 :           types, position, ArrayList::Add(position_specific_types, type));
    1031             :     }
    1032             :   }
    1033         285 :   SetFeedback(*types);
    1034         285 : }
    1035             : 
    1036         285 : void CollectTypeProfileNexus::Clear() {
    1037         285 :   SetFeedback(*FeedbackVector::UninitializedSentinel(GetIsolate()));
    1038         285 : }
    1039             : 
    1040         150 : std::vector<int> CollectTypeProfileNexus::GetSourcePositions() const {
    1041             :   std::vector<int> source_positions;
    1042             :   Isolate* isolate = GetIsolate();
    1043             : 
    1044         150 :   Object* const feedback = GetFeedback();
    1045             : 
    1046         150 :   if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
    1047             :     return source_positions;
    1048             :   }
    1049             : 
    1050             :   Handle<UnseededNumberDictionary> types = Handle<UnseededNumberDictionary>(
    1051             :       UnseededNumberDictionary::cast(feedback), isolate);
    1052             : 
    1053        1040 :   for (int index = UnseededNumberDictionary::kElementsStartIndex;
    1054             :        index < types->length(); index += UnseededNumberDictionary::kEntrySize) {
    1055             :     int key_index = index + UnseededNumberDictionary::kEntryKeyIndex;
    1056             :     Object* key = types->get(key_index);
    1057         440 :     if (key->IsSmi()) {
    1058         185 :       int position = Smi::cast(key)->value();
    1059         185 :       source_positions.push_back(position);
    1060             :     }
    1061             :   }
    1062             :   return source_positions;
    1063             : }
    1064             : 
    1065         185 : std::vector<Handle<String>> CollectTypeProfileNexus::GetTypesForSourcePositions(
    1066             :     uint32_t position) const {
    1067             :   Isolate* isolate = GetIsolate();
    1068             : 
    1069         185 :   Object* const feedback = GetFeedback();
    1070             :   std::vector<Handle<String>> types_for_position;
    1071         185 :   if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
    1072             :     return types_for_position;
    1073             :   }
    1074             : 
    1075             :   Handle<UnseededNumberDictionary> types = Handle<UnseededNumberDictionary>(
    1076             :       UnseededNumberDictionary::cast(feedback), isolate);
    1077             : 
    1078             :   int entry = types->FindEntry(position);
    1079         185 :   if (entry == UnseededNumberDictionary::kNotFound) {
    1080             :     return types_for_position;
    1081             :   }
    1082             :   DCHECK(types->ValueAt(entry)->IsArrayList());
    1083             :   Handle<ArrayList> position_specific_types =
    1084         185 :       Handle<ArrayList>(ArrayList::cast(types->ValueAt(entry)));
    1085         615 :   for (int i = 0; i < position_specific_types->Length(); i++) {
    1086             :     Object* t = position_specific_types->Get(i);
    1087         245 :     types_for_position.push_back(Handle<String>(String::cast(t), isolate));
    1088             :   }
    1089             : 
    1090             :   return types_for_position;
    1091             : }
    1092             : 
    1093             : namespace {
    1094             : 
    1095           0 : Handle<JSObject> ConvertToJSObject(Isolate* isolate,
    1096             :                                    Handle<UnseededNumberDictionary> feedback) {
    1097             :   Handle<JSObject> type_profile =
    1098           0 :       isolate->factory()->NewJSObject(isolate->object_function());
    1099             : 
    1100           0 :   for (int index = UnseededNumberDictionary::kElementsStartIndex;
    1101             :        index < feedback->length();
    1102             :        index += UnseededNumberDictionary::kEntrySize) {
    1103             :     int key_index = index + UnseededNumberDictionary::kEntryKeyIndex;
    1104             :     Object* key = feedback->get(key_index);
    1105           0 :     if (key->IsSmi()) {
    1106           0 :       int value_index = index + UnseededNumberDictionary::kEntryValueIndex;
    1107             : 
    1108             :       Handle<ArrayList> position_specific_types(
    1109             :           ArrayList::cast(feedback->get(value_index)));
    1110             : 
    1111             :       int position = Smi::ToInt(key);
    1112             :       JSObject::AddDataElement(
    1113             :           type_profile, position,
    1114             :           isolate->factory()->NewJSArrayWithElements(
    1115             :               ArrayList::Elements(position_specific_types)),
    1116           0 :           PropertyAttributes::NONE)
    1117           0 :           .ToHandleChecked();
    1118             :     }
    1119             :   }
    1120           0 :   return type_profile;
    1121             : }
    1122             : }  // namespace
    1123             : 
    1124           0 : JSObject* CollectTypeProfileNexus::GetTypeProfile() const {
    1125             :   Isolate* isolate = GetIsolate();
    1126             : 
    1127           0 :   Object* const feedback = GetFeedback();
    1128             : 
    1129           0 :   if (feedback == *FeedbackVector::UninitializedSentinel(isolate)) {
    1130           0 :     return *isolate->factory()->NewJSObject(isolate->object_function());
    1131             :   }
    1132             : 
    1133             :   return *ConvertToJSObject(isolate,
    1134           0 :                             handle(UnseededNumberDictionary::cast(feedback)));
    1135             : }
    1136             : 
    1137             : }  // namespace internal
    1138             : }  // namespace v8

Generated by: LCOV version 1.10