LCOV - code coverage report
Current view: top level - src - feedback-vector-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 90 139 64.7 %
Date: 2019-03-21 Functions: 19 20 95.0 %

          Line data    Source code
       1             : // Copyright 2012 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_INL_H_
       6             : #define V8_FEEDBACK_VECTOR_INL_H_
       7             : 
       8             : #include "src/feedback-vector.h"
       9             : 
      10             : #include "src/globals.h"
      11             : #include "src/heap/factory-inl.h"
      12             : #include "src/heap/heap-write-barrier-inl.h"
      13             : #include "src/objects/code-inl.h"
      14             : #include "src/objects/maybe-object-inl.h"
      15             : #include "src/objects/shared-function-info.h"
      16             : #include "src/objects/smi.h"
      17             : 
      18             : // Has to be the last include (doesn't have include guards):
      19             : #include "src/objects/object-macros.h"
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : 
      24             : OBJECT_CONSTRUCTORS_IMPL(FeedbackVector, HeapObject)
      25             : OBJECT_CONSTRUCTORS_IMPL(FeedbackMetadata, HeapObject)
      26             : 
      27             : NEVER_READ_ONLY_SPACE_IMPL(FeedbackVector)
      28             : 
      29             : CAST_ACCESSOR(FeedbackVector)
      30             : CAST_ACCESSOR(FeedbackMetadata)
      31             : 
      32     7897326 : INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
      33             : 
      34     4680022 : INT32_ACCESSORS(FeedbackMetadata, closure_feedback_cell_count,
      35             :                 kFeedbackCellCountOffset)
      36             : 
      37             : int32_t FeedbackMetadata::synchronized_slot_count() const {
      38     5301966 :   return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
      39     5301966 :       FIELD_ADDR(*this, kSlotCountOffset)));
      40             : }
      41             : 
      42             : int32_t FeedbackMetadata::get(int index) const {
      43             :   DCHECK(index >= 0 && index < length());
      44    70154102 :   int offset = kHeaderSize + index * kInt32Size;
      45    70154522 :   return READ_INT32_FIELD(*this, offset);
      46             : }
      47             : 
      48             : void FeedbackMetadata::set(int index, int32_t value) {
      49             :   DCHECK(index >= 0 && index < length());
      50             :   int offset = kHeaderSize + index * kInt32Size;
      51    25902969 :   WRITE_INT32_FIELD(*this, offset, value);
      52             : }
      53             : 
      54             : bool FeedbackMetadata::is_empty() const { return slot_count() == 0; }
      55             : 
      56             : int FeedbackMetadata::length() const {
      57             :   return FeedbackMetadata::length(slot_count());
      58             : }
      59             : 
      60    35486534 : int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
      61             :   switch (kind) {
      62             :     case FeedbackSlotKind::kForIn:
      63             :     case FeedbackSlotKind::kInstanceOf:
      64             :     case FeedbackSlotKind::kCompareOp:
      65             :     case FeedbackSlotKind::kBinaryOp:
      66             :     case FeedbackSlotKind::kLiteral:
      67             :     case FeedbackSlotKind::kTypeProfile:
      68             :       return 1;
      69             : 
      70             :     case FeedbackSlotKind::kCall:
      71             :     case FeedbackSlotKind::kCloneObject:
      72             :     case FeedbackSlotKind::kLoadProperty:
      73             :     case FeedbackSlotKind::kLoadGlobalInsideTypeof:
      74             :     case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
      75             :     case FeedbackSlotKind::kLoadKeyed:
      76             :     case FeedbackSlotKind::kHasKeyed:
      77             :     case FeedbackSlotKind::kStoreNamedSloppy:
      78             :     case FeedbackSlotKind::kStoreNamedStrict:
      79             :     case FeedbackSlotKind::kStoreOwnNamed:
      80             :     case FeedbackSlotKind::kStoreGlobalSloppy:
      81             :     case FeedbackSlotKind::kStoreGlobalStrict:
      82             :     case FeedbackSlotKind::kStoreKeyedSloppy:
      83             :     case FeedbackSlotKind::kStoreKeyedStrict:
      84             :     case FeedbackSlotKind::kStoreInArrayLiteral:
      85             :     case FeedbackSlotKind::kStoreDataPropertyInLiteral:
      86    30122373 :       return 2;
      87             : 
      88             :     case FeedbackSlotKind::kInvalid:
      89             :     case FeedbackSlotKind::kKindsNumber:
      90           0 :       UNREACHABLE();
      91             :       break;
      92             :   }
      93             :   return 1;
      94             : }
      95             : 
      96    38844020 : ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
      97             :           kSharedFunctionInfoOffset)
      98    34661139 : WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
      99    31428809 : ACCESSORS(FeedbackVector, closure_feedback_cell_array, FixedArray,
     100             :           kClosureFeedbackCellArrayOffset)
     101    23800468 : INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
     102     3618675 : INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
     103     7068695 : INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
     104     3156250 : INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
     105             : 
     106           7 : bool FeedbackVector::is_empty() const { return length() == 0; }
     107             : 
     108    23412762 : FeedbackMetadata FeedbackVector::metadata() const {
     109    23412762 :   return shared_function_info()->feedback_metadata();
     110             : }
     111             : 
     112             : void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
     113             : 
     114             : void FeedbackVector::increment_deopt_count() {
     115             :   int count = deopt_count();
     116       36812 :   if (count < std::numeric_limits<int32_t>::max()) {
     117       36812 :     set_deopt_count(count + 1);
     118             :   }
     119             : }
     120             : 
     121     7367277 : Code FeedbackVector::optimized_code() const {
     122             :   MaybeObject slot = optimized_code_weak_or_smi();
     123             :   DCHECK(slot->IsSmi() || slot->IsWeakOrCleared());
     124             :   HeapObject heap_object;
     125    14734554 :   return slot->GetHeapObject(&heap_object) ? Code::cast(heap_object) : Code();
     126             : }
     127             : 
     128             : OptimizationMarker FeedbackVector::optimization_marker() const {
     129             :   MaybeObject slot = optimized_code_weak_or_smi();
     130             :   Smi value;
     131     1486297 :   if (!slot->ToSmi(&value)) return OptimizationMarker::kNone;
     132             :   return static_cast<OptimizationMarker>(value->value());
     133             : }
     134             : 
     135             : bool FeedbackVector::has_optimized_code() const {
     136     1245078 :   return !optimized_code().is_null();
     137             : }
     138             : 
     139      488811 : bool FeedbackVector::has_optimization_marker() const {
     140      977620 :   return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
     141      488811 :          optimization_marker() != OptimizationMarker::kNone;
     142             : }
     143             : 
     144             : // Conversion from an integer index to either a slot or an ic slot.
     145             : // static
     146             : FeedbackSlot FeedbackVector::ToSlot(int index) {
     147             :   DCHECK_GE(index, 0);
     148             :   return FeedbackSlot(index);
     149             : }
     150             : 
     151             : MaybeObject FeedbackVector::Get(FeedbackSlot slot) const {
     152             :   return get(GetIndex(slot));
     153             : }
     154             : 
     155             : MaybeObject FeedbackVector::get(int index) const {
     156             :   DCHECK_GE(index, 0);
     157             :   DCHECK_LT(index, this->length());
     158    26912800 :   int offset = kFeedbackSlotsOffset + index * kTaggedSize;
     159    53825660 :   return RELAXED_READ_WEAK_FIELD(*this, offset);
     160             : }
     161             : 
     162      446200 : Handle<FeedbackCell> FeedbackVector::GetClosureFeedbackCell(int index) const {
     163             :   DCHECK_GE(index, 0);
     164             :   FixedArray cell_array = closure_feedback_cell_array();
     165      446200 :   return handle(FeedbackCell::cast(cell_array.get(index)), GetIsolate());
     166             : }
     167             : 
     168             : void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
     169             :                          WriteBarrierMode mode) {
     170     8718033 :   set(GetIndex(slot), value, mode);
     171             : }
     172             : 
     173    56142159 : void FeedbackVector::set(int index, MaybeObject value, WriteBarrierMode mode) {
     174             :   DCHECK_GE(index, 0);
     175             :   DCHECK_LT(index, this->length());
     176    56142159 :   int offset = kFeedbackSlotsOffset + index * kTaggedSize;
     177    56142159 :   RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
     178    79348886 :   CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
     179    56142176 : }
     180             : 
     181             : void FeedbackVector::Set(FeedbackSlot slot, Object value,
     182             :                          WriteBarrierMode mode) {
     183      259704 :   set(GetIndex(slot), MaybeObject::FromObject(value), mode);
     184             : }
     185             : 
     186             : void FeedbackVector::set(int index, Object value, WriteBarrierMode mode) {
     187    32186490 :   set(index, MaybeObject::FromObject(value), mode);
     188             : }
     189             : 
     190             : inline MaybeObjectSlot FeedbackVector::slots_start() {
     191             :   return RawMaybeWeakField(kFeedbackSlotsOffset);
     192             : }
     193             : 
     194             : // Helper function to transform the feedback to BinaryOperationHint.
     195      967534 : BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
     196      967534 :   switch (type_feedback) {
     197             :     case BinaryOperationFeedback::kNone:
     198             :       return BinaryOperationHint::kNone;
     199             :     case BinaryOperationFeedback::kSignedSmall:
     200      401759 :       return BinaryOperationHint::kSignedSmall;
     201             :     case BinaryOperationFeedback::kSignedSmallInputs:
     202       27367 :       return BinaryOperationHint::kSignedSmallInputs;
     203             :     case BinaryOperationFeedback::kNumber:
     204      224212 :       return BinaryOperationHint::kNumber;
     205             :     case BinaryOperationFeedback::kNumberOrOddball:
     206        6603 :       return BinaryOperationHint::kNumberOrOddball;
     207             :     case BinaryOperationFeedback::kConsOneByteString:
     208        6212 :       return BinaryOperationHint::kConsOneByteString;
     209             :     case BinaryOperationFeedback::kConsTwoByteString:
     210         494 :       return BinaryOperationHint::kConsTwoByteString;
     211             :     case BinaryOperationFeedback::kConsString:
     212           0 :       return BinaryOperationHint::kConsString;
     213             :     case BinaryOperationFeedback::kString:
     214       13432 :       return BinaryOperationHint::kString;
     215             :     case BinaryOperationFeedback::kBigInt:
     216         938 :       return BinaryOperationHint::kBigInt;
     217             :     default:
     218       10181 :       return BinaryOperationHint::kAny;
     219             :   }
     220             :   UNREACHABLE();
     221             : }
     222             : 
     223             : // Helper function to transform the feedback to CompareOperationHint.
     224      526601 : CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
     225      526601 :   switch (type_feedback) {
     226             :     case CompareOperationFeedback::kNone:
     227             :       return CompareOperationHint::kNone;
     228             :     case CompareOperationFeedback::kSignedSmall:
     229      183609 :       return CompareOperationHint::kSignedSmall;
     230             :     case CompareOperationFeedback::kNumber:
     231       31641 :       return CompareOperationHint::kNumber;
     232             :     case CompareOperationFeedback::kNumberOrOddball:
     233          21 :       return CompareOperationHint::kNumberOrOddball;
     234             :     case CompareOperationFeedback::kInternalizedString:
     235       17032 :       return CompareOperationHint::kInternalizedString;
     236             :     case CompareOperationFeedback::kString:
     237       28065 :       return CompareOperationHint::kString;
     238             :     case CompareOperationFeedback::kSymbol:
     239         117 :       return CompareOperationHint::kSymbol;
     240             :     case CompareOperationFeedback::kBigInt:
     241         148 :       return CompareOperationHint::kBigInt;
     242             :     case CompareOperationFeedback::kReceiver:
     243        2109 :       return CompareOperationHint::kReceiver;
     244             :     case CompareOperationFeedback::kReceiverOrNullOrUndefined:
     245         347 :       return CompareOperationHint::kReceiverOrNullOrUndefined;
     246             :     default:
     247       73277 :       return CompareOperationHint::kAny;
     248             :   }
     249             :   UNREACHABLE();
     250             : }
     251             : 
     252             : // Helper function to transform the feedback to ForInHint.
     253             : ForInHint ForInHintFromFeedback(int type_feedback) {
     254             :   switch (type_feedback) {
     255             :     case ForInFeedback::kNone:
     256             :       return ForInHint::kNone;
     257             :     case ForInFeedback::kEnumCacheKeys:
     258             :       return ForInHint::kEnumCacheKeys;
     259             :     case ForInFeedback::kEnumCacheKeysAndIndices:
     260             :       return ForInHint::kEnumCacheKeysAndIndices;
     261             :     default:
     262             :       return ForInHint::kAny;
     263             :   }
     264             :   UNREACHABLE();
     265             : }
     266             : 
     267           0 : void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
     268             :                                    int* vector_ic_count) {
     269             :   MaybeObject megamorphic_sentinel = MaybeObject::FromObject(
     270             :       *FeedbackVector::MegamorphicSentinel(GetIsolate()));
     271             :   int with = 0;
     272             :   int gen = 0;
     273             :   int total = 0;
     274           0 :   FeedbackMetadataIterator iter(metadata());
     275           0 :   while (iter.HasNext()) {
     276           0 :     FeedbackSlot slot = iter.Next();
     277             :     FeedbackSlotKind kind = iter.kind();
     278             : 
     279             :     MaybeObject const obj = Get(slot);
     280           0 :     AssertNoLegacyTypes(obj);
     281           0 :     switch (kind) {
     282             :       case FeedbackSlotKind::kCall:
     283             :       case FeedbackSlotKind::kLoadProperty:
     284             :       case FeedbackSlotKind::kLoadGlobalInsideTypeof:
     285             :       case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
     286             :       case FeedbackSlotKind::kLoadKeyed:
     287             :       case FeedbackSlotKind::kHasKeyed:
     288             :       case FeedbackSlotKind::kStoreNamedSloppy:
     289             :       case FeedbackSlotKind::kStoreNamedStrict:
     290             :       case FeedbackSlotKind::kStoreOwnNamed:
     291             :       case FeedbackSlotKind::kStoreGlobalSloppy:
     292             :       case FeedbackSlotKind::kStoreGlobalStrict:
     293             :       case FeedbackSlotKind::kStoreKeyedSloppy:
     294             :       case FeedbackSlotKind::kStoreKeyedStrict:
     295             :       case FeedbackSlotKind::kStoreInArrayLiteral:
     296             :       case FeedbackSlotKind::kStoreDataPropertyInLiteral:
     297             :       case FeedbackSlotKind::kTypeProfile: {
     298           0 :         HeapObject heap_object;
     299           0 :         if (obj->IsWeakOrCleared() ||
     300           0 :             (obj->GetHeapObjectIfStrong(&heap_object) &&
     301           0 :              (heap_object->IsWeakFixedArray() || heap_object->IsString()))) {
     302           0 :           with++;
     303           0 :         } else if (obj == megamorphic_sentinel) {
     304           0 :           gen++;
     305           0 :           with++;
     306             :         }
     307           0 :         total++;
     308             :         break;
     309             :       }
     310             :       case FeedbackSlotKind::kBinaryOp: {
     311             :         int const feedback = obj.ToSmi().value();
     312           0 :         BinaryOperationHint hint = BinaryOperationHintFromFeedback(feedback);
     313           0 :         if (hint == BinaryOperationHint::kAny) {
     314           0 :           gen++;
     315             :         }
     316           0 :         if (hint != BinaryOperationHint::kNone) {
     317           0 :           with++;
     318             :         }
     319           0 :         total++;
     320           0 :         break;
     321             :       }
     322             :       case FeedbackSlotKind::kCompareOp: {
     323             :         int const feedback = obj.ToSmi().value();
     324           0 :         CompareOperationHint hint = CompareOperationHintFromFeedback(feedback);
     325           0 :         if (hint == CompareOperationHint::kAny) {
     326           0 :           gen++;
     327             :         }
     328           0 :         if (hint != CompareOperationHint::kNone) {
     329           0 :           with++;
     330             :         }
     331           0 :         total++;
     332           0 :         break;
     333             :       }
     334             :       case FeedbackSlotKind::kForIn: {
     335             :         int const feedback = obj.ToSmi().value();
     336             :         ForInHint hint = ForInHintFromFeedback(feedback);
     337           0 :         if (hint == ForInHint::kAny) {
     338           0 :           gen++;
     339             :         }
     340           0 :         if (hint != ForInHint::kNone) {
     341           0 :           with++;
     342             :         }
     343           0 :         total++;
     344           0 :         break;
     345             :       }
     346             :       case FeedbackSlotKind::kInstanceOf: {
     347           0 :         if (obj->IsWeakOrCleared()) {
     348           0 :           with++;
     349           0 :         } else if (obj == megamorphic_sentinel) {
     350           0 :           gen++;
     351           0 :           with++;
     352             :         }
     353           0 :         total++;
     354           0 :         break;
     355             :       }
     356             :       case FeedbackSlotKind::kLiteral:
     357             :       case FeedbackSlotKind::kCloneObject:
     358             :         break;
     359             :       case FeedbackSlotKind::kInvalid:
     360             :       case FeedbackSlotKind::kKindsNumber:
     361           0 :         UNREACHABLE();
     362             :         break;
     363             :     }
     364             :   }
     365             : 
     366           0 :   *with_type_info = with;
     367           0 :   *generic = gen;
     368           0 :   *vector_ic_count = total;
     369           0 : }
     370             : 
     371        1848 : Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
     372        1848 :   return isolate->factory()->uninitialized_symbol();
     373             : }
     374             : 
     375             : Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
     376             :   return isolate->factory()->generic_symbol();
     377             : }
     378             : 
     379        4368 : Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
     380        4368 :   return isolate->factory()->megamorphic_symbol();
     381             : }
     382             : 
     383             : Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
     384             :   return isolate->factory()->premonomorphic_symbol();
     385             : }
     386             : 
     387             : Symbol FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
     388             :   return ReadOnlyRoots(isolate).uninitialized_symbol();
     389             : }
     390             : 
     391             : bool FeedbackMetadataIterator::HasNext() const {
     392             :   return next_slot_.ToInt() < metadata()->slot_count();
     393             : }
     394             : 
     395       81361 : FeedbackSlot FeedbackMetadataIterator::Next() {
     396             :   DCHECK(HasNext());
     397       81361 :   cur_slot_ = next_slot_;
     398       81361 :   slot_kind_ = metadata()->GetKind(cur_slot_);
     399       81361 :   next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
     400       81361 :   return cur_slot_;
     401             : }
     402             : 
     403             : int FeedbackMetadataIterator::entry_size() const {
     404       81361 :   return FeedbackMetadata::GetSlotSize(kind());
     405             : }
     406             : 
     407    17497485 : MaybeObject FeedbackNexus::GetFeedback() const {
     408             :   MaybeObject feedback = vector()->Get(slot());
     409      413684 :   FeedbackVector::AssertNoLegacyTypes(feedback);
     410    17497492 :   return feedback;
     411             : }
     412             : 
     413     7768770 : MaybeObject FeedbackNexus::GetFeedbackExtra() const {
     414             : #ifdef DEBUG
     415             :   FeedbackSlotKind kind = vector()->GetKind(slot());
     416             :   DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
     417             : #endif
     418             :   int extra_index = vector()->GetIndex(slot()) + 1;
     419     7768770 :   return vector()->get(extra_index);
     420             : }
     421             : 
     422             : void FeedbackNexus::SetFeedback(Object feedback, WriteBarrierMode mode) {
     423     1015473 :   SetFeedback(MaybeObject::FromObject(feedback));
     424             : }
     425             : 
     426     8718028 : void FeedbackNexus::SetFeedback(MaybeObject feedback, WriteBarrierMode mode) {
     427             :   FeedbackVector::AssertNoLegacyTypes(feedback);
     428    17436064 :   vector()->Set(slot(), feedback, mode);
     429     8718036 : }
     430             : 
     431     6069672 : void FeedbackNexus::SetFeedbackExtra(Object feedback_extra,
     432             :                                      WriteBarrierMode mode) {
     433             : #ifdef DEBUG
     434             :   FeedbackSlotKind kind = vector()->GetKind(slot());
     435             :   DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
     436             :   FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
     437             : #endif
     438     6069672 :   int index = vector()->GetIndex(slot()) + 1;
     439     6069672 :   vector()->set(index, MaybeObject::FromObject(feedback_extra), mode);
     440     6069670 : }
     441             : 
     442     2655954 : void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
     443             :                                      WriteBarrierMode mode) {
     444             : #ifdef DEBUG
     445             :   FeedbackVector::AssertNoLegacyTypes(feedback_extra);
     446             : #endif
     447     2655954 :   int index = vector()->GetIndex(slot()) + 1;
     448     2655954 :   vector()->set(index, feedback_extra, mode);
     449     2655953 : }
     450             : 
     451             : Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
     452             : }  // namespace internal
     453             : }  // namespace v8
     454             : 
     455             : #include "src/objects/object-macros-undef.h"
     456             : 
     457             : #endif  // V8_FEEDBACK_VECTOR_INL_H_

Generated by: LCOV version 1.10