LCOV - code coverage report
Current view: top level - src - feedback-vector-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 92 144 63.9 %
Date: 2019-01-20 Functions: 24 25 96.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             : #include "src/globals.h"
      10             : #include "src/heap/factory-inl.h"
      11             : #include "src/heap/heap-inl.h"
      12             : #include "src/heap/heap-write-barrier.h"
      13             : #include "src/objects/maybe-object-inl.h"
      14             : #include "src/objects/shared-function-info.h"
      15             : #include "src/objects/smi.h"
      16             : 
      17             : // Has to be the last include (doesn't have include guards):
      18             : #include "src/objects/object-macros.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : 
      23    79862410 : OBJECT_CONSTRUCTORS_IMPL(FeedbackVector, HeapObject)
      24   100463966 : OBJECT_CONSTRUCTORS_IMPL(FeedbackMetadata, HeapObject)
      25             : 
      26             : NEVER_READ_ONLY_SPACE_IMPL(FeedbackVector)
      27             : 
      28    39956970 : CAST_ACCESSOR(FeedbackVector)
      29    50232018 : CAST_ACCESSOR(FeedbackMetadata)
      30             : 
      31     7896268 : INT32_ACCESSORS(FeedbackMetadata, slot_count, kSlotCountOffset)
      32             : 
      33             : int32_t FeedbackMetadata::synchronized_slot_count() const {
      34             :   return base::Acquire_Load(reinterpret_cast<const base::Atomic32*>(
      35    15662030 :       FIELD_ADDR(this, kSlotCountOffset)));
      36             : }
      37             : 
      38             : int32_t FeedbackMetadata::get(int index) const {
      39             :   DCHECK(index >= 0 && index < length());
      40    66586121 :   int offset = kHeaderSize + index * kInt32Size;
      41    66586646 :   return READ_INT32_FIELD(this, offset);
      42             : }
      43             : 
      44             : void FeedbackMetadata::set(int index, int32_t value) {
      45             :   DCHECK(index >= 0 && index < length());
      46             :   int offset = kHeaderSize + index * kInt32Size;
      47    24090465 :   WRITE_INT32_FIELD(this, offset, value);
      48             : }
      49             : 
      50             : bool FeedbackMetadata::is_empty() const { return slot_count() == 0; }
      51             : 
      52             : int FeedbackMetadata::length() const {
      53             :   return FeedbackMetadata::length(slot_count());
      54             : }
      55             : 
      56    36752758 : int FeedbackMetadata::GetSlotSize(FeedbackSlotKind kind) {
      57             :   switch (kind) {
      58             :     case FeedbackSlotKind::kForIn:
      59             :     case FeedbackSlotKind::kInstanceOf:
      60             :     case FeedbackSlotKind::kCompareOp:
      61             :     case FeedbackSlotKind::kBinaryOp:
      62             :     case FeedbackSlotKind::kLiteral:
      63             :     case FeedbackSlotKind::kCreateClosure:
      64             :     case FeedbackSlotKind::kTypeProfile:
      65             :       return 1;
      66             : 
      67             :     case FeedbackSlotKind::kCall:
      68             :     case FeedbackSlotKind::kCloneObject:
      69             :     case FeedbackSlotKind::kLoadProperty:
      70             :     case FeedbackSlotKind::kLoadGlobalInsideTypeof:
      71             :     case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
      72             :     case FeedbackSlotKind::kLoadKeyed:
      73             :     case FeedbackSlotKind::kStoreNamedSloppy:
      74             :     case FeedbackSlotKind::kStoreNamedStrict:
      75             :     case FeedbackSlotKind::kStoreOwnNamed:
      76             :     case FeedbackSlotKind::kStoreGlobalSloppy:
      77             :     case FeedbackSlotKind::kStoreGlobalStrict:
      78             :     case FeedbackSlotKind::kStoreKeyedSloppy:
      79             :     case FeedbackSlotKind::kStoreKeyedStrict:
      80             :     case FeedbackSlotKind::kStoreInArrayLiteral:
      81             :     case FeedbackSlotKind::kStoreDataPropertyInLiteral:
      82    24785928 :       return 2;
      83             : 
      84             :     case FeedbackSlotKind::kInvalid:
      85             :     case FeedbackSlotKind::kKindsNumber:
      86           0 :       UNREACHABLE();
      87             :       break;
      88             :   }
      89             :   return 1;
      90             : }
      91             : 
      92    90370605 : ACCESSORS(FeedbackVector, shared_function_info, SharedFunctionInfo,
      93             :           kSharedFunctionInfoOffset)
      94    34928759 : WEAK_ACCESSORS(FeedbackVector, optimized_code_weak_or_smi, kOptimizedCodeOffset)
      95    26722992 : INT32_ACCESSORS(FeedbackVector, length, kLengthOffset)
      96     3604272 : INT32_ACCESSORS(FeedbackVector, invocation_count, kInvocationCountOffset)
      97     6552635 : INT32_ACCESSORS(FeedbackVector, profiler_ticks, kProfilerTicksOffset)
      98     3143843 : INT32_ACCESSORS(FeedbackVector, deopt_count, kDeoptCountOffset)
      99             : 
     100           7 : bool FeedbackVector::is_empty() const { return length() == 0; }
     101             : 
     102             : FeedbackMetadata FeedbackVector::metadata() const {
     103    21003324 :   return shared_function_info()->feedback_metadata();
     104             : }
     105             : 
     106             : void FeedbackVector::clear_invocation_count() { set_invocation_count(0); }
     107             : 
     108             : void FeedbackVector::increment_deopt_count() {
     109             :   int count = deopt_count();
     110       34902 :   if (count < std::numeric_limits<int32_t>::max()) {
     111       34902 :     set_deopt_count(count + 1);
     112             :   }
     113             : }
     114             : 
     115     7305855 : Code FeedbackVector::optimized_code() const {
     116     7305855 :   MaybeObject slot = optimized_code_weak_or_smi();
     117             :   DCHECK(slot->IsSmi() || slot->IsWeakOrCleared());
     118     7305855 :   HeapObject heap_object;
     119    15069210 :   return slot->GetHeapObject(&heap_object) ? Code::cast(heap_object) : Code();
     120             : }
     121             : 
     122     1468292 : OptimizationMarker FeedbackVector::optimization_marker() const {
     123     1468292 :   MaybeObject slot = optimized_code_weak_or_smi();
     124     1468292 :   Smi value;
     125     1468292 :   if (!slot->ToSmi(&value)) return OptimizationMarker::kNone;
     126     1462704 :   return static_cast<OptimizationMarker>(value->value());
     127             : }
     128             : 
     129             : bool FeedbackVector::has_optimized_code() const {
     130     1153647 :   return !optimized_code().is_null();
     131             : }
     132             : 
     133      479852 : bool FeedbackVector::has_optimization_marker() const {
     134      959708 :   return optimization_marker() != OptimizationMarker::kLogFirstExecution &&
     135      959709 :          optimization_marker() != OptimizationMarker::kNone;
     136             : }
     137             : 
     138             : // Conversion from an integer index to either a slot or an ic slot.
     139             : // static
     140     7617586 : FeedbackSlot FeedbackVector::ToSlot(int index) {
     141             :   DCHECK_GE(index, 0);
     142     7617586 :   return FeedbackSlot(index);
     143             : }
     144             : 
     145       81905 : MaybeObject FeedbackVector::Get(FeedbackSlot slot) const {
     146    16749365 :   return get(GetIndex(slot));
     147             : }
     148             : 
     149    23727815 : MaybeObject FeedbackVector::get(int index) const {
     150             :   DCHECK_GE(index, 0);
     151             :   DCHECK_LT(index, this->length());
     152    23727815 :   int offset = kFeedbackSlotsOffset + index * kTaggedSize;
     153    47455630 :   return RELAXED_READ_WEAK_FIELD(*this, offset);
     154             : }
     155             : 
     156             : void FeedbackVector::Set(FeedbackSlot slot, MaybeObject value,
     157             :                          WriteBarrierMode mode) {
     158     7918085 :   set(GetIndex(slot), value, mode);
     159             : }
     160             : 
     161    52044047 : void FeedbackVector::set(int index, MaybeObject value, WriteBarrierMode mode) {
     162             :   DCHECK_GE(index, 0);
     163             :   DCHECK_LT(index, this->length());
     164    52044047 :   int offset = kFeedbackSlotsOffset + index * kTaggedSize;
     165    52044047 :   RELAXED_WRITE_WEAK_FIELD(*this, offset, value);
     166    80535465 :   CONDITIONAL_WEAK_WRITE_BARRIER(*this, offset, value, mode);
     167    52044072 : }
     168             : 
     169       18621 : void FeedbackVector::Set(FeedbackSlot slot, Object value,
     170             :                          WriteBarrierMode mode) {
     171      259608 :   set(GetIndex(slot), MaybeObject::FromObject(value), mode);
     172       18621 : }
     173             : 
     174             : void FeedbackVector::set(int index, Object value, WriteBarrierMode mode) {
     175    29729321 :   set(index, MaybeObject::FromObject(value), mode);
     176             : }
     177             : 
     178             : inline MaybeObjectSlot FeedbackVector::slots_start() {
     179             :   return RawMaybeWeakField(kFeedbackSlotsOffset);
     180             : }
     181             : 
     182             : // Helper function to transform the feedback to BinaryOperationHint.
     183             : BinaryOperationHint BinaryOperationHintFromFeedback(int type_feedback) {
     184             :   switch (type_feedback) {
     185             :     case BinaryOperationFeedback::kNone:
     186             :       return BinaryOperationHint::kNone;
     187             :     case BinaryOperationFeedback::kSignedSmall:
     188             :       return BinaryOperationHint::kSignedSmall;
     189             :     case BinaryOperationFeedback::kSignedSmallInputs:
     190             :       return BinaryOperationHint::kSignedSmallInputs;
     191             :     case BinaryOperationFeedback::kNumber:
     192             :       return BinaryOperationHint::kNumber;
     193             :     case BinaryOperationFeedback::kNumberOrOddball:
     194             :       return BinaryOperationHint::kNumberOrOddball;
     195             :     case BinaryOperationFeedback::kString:
     196             :       return BinaryOperationHint::kString;
     197             :     case BinaryOperationFeedback::kBigInt:
     198             :       return BinaryOperationHint::kBigInt;
     199             :     default:
     200             :       return BinaryOperationHint::kAny;
     201             :   }
     202             :   UNREACHABLE();
     203             : }
     204             : 
     205             : // Helper function to transform the feedback to CompareOperationHint.
     206      527494 : CompareOperationHint CompareOperationHintFromFeedback(int type_feedback) {
     207      527494 :   switch (type_feedback) {
     208             :     case CompareOperationFeedback::kNone:
     209             :       return CompareOperationHint::kNone;
     210             :     case CompareOperationFeedback::kSignedSmall:
     211      188647 :       return CompareOperationHint::kSignedSmall;
     212             :     case CompareOperationFeedback::kNumber:
     213       33666 :       return CompareOperationHint::kNumber;
     214             :     case CompareOperationFeedback::kNumberOrOddball:
     215          21 :       return CompareOperationHint::kNumberOrOddball;
     216             :     case CompareOperationFeedback::kInternalizedString:
     217       17033 :       return CompareOperationHint::kInternalizedString;
     218             :     case CompareOperationFeedback::kString:
     219       27404 :       return CompareOperationHint::kString;
     220             :     case CompareOperationFeedback::kSymbol:
     221         132 :       return CompareOperationHint::kSymbol;
     222             :     case CompareOperationFeedback::kBigInt:
     223         148 :       return CompareOperationHint::kBigInt;
     224             :     case CompareOperationFeedback::kReceiver:
     225        2154 :       return CompareOperationHint::kReceiver;
     226             :     case CompareOperationFeedback::kReceiverOrNullOrUndefined:
     227         409 :       return CompareOperationHint::kReceiverOrNullOrUndefined;
     228             :     default:
     229       73033 :       return CompareOperationHint::kAny;
     230             :   }
     231             :   UNREACHABLE();
     232             : }
     233             : 
     234             : // Helper function to transform the feedback to ForInHint.
     235             : ForInHint ForInHintFromFeedback(int type_feedback) {
     236             :   switch (type_feedback) {
     237             :     case ForInFeedback::kNone:
     238             :       return ForInHint::kNone;
     239             :     case ForInFeedback::kEnumCacheKeys:
     240             :       return ForInHint::kEnumCacheKeys;
     241             :     case ForInFeedback::kEnumCacheKeysAndIndices:
     242             :       return ForInHint::kEnumCacheKeysAndIndices;
     243             :     default:
     244             :       return ForInHint::kAny;
     245             :   }
     246             :   UNREACHABLE();
     247             : }
     248             : 
     249           0 : void FeedbackVector::ComputeCounts(int* with_type_info, int* generic,
     250             :                                    int* vector_ic_count) {
     251             :   MaybeObject megamorphic_sentinel = MaybeObject::FromObject(
     252             :       *FeedbackVector::MegamorphicSentinel(GetIsolate()));
     253             :   int with = 0;
     254             :   int gen = 0;
     255             :   int total = 0;
     256             :   FeedbackMetadataIterator iter(metadata());
     257           0 :   while (iter.HasNext()) {
     258           0 :     FeedbackSlot slot = iter.Next();
     259           0 :     FeedbackSlotKind kind = iter.kind();
     260             : 
     261           0 :     MaybeObject const obj = Get(slot);
     262           0 :     AssertNoLegacyTypes(obj);
     263           0 :     switch (kind) {
     264             :       case FeedbackSlotKind::kCall:
     265             :       case FeedbackSlotKind::kLoadProperty:
     266             :       case FeedbackSlotKind::kLoadGlobalInsideTypeof:
     267             :       case FeedbackSlotKind::kLoadGlobalNotInsideTypeof:
     268             :       case FeedbackSlotKind::kLoadKeyed:
     269             :       case FeedbackSlotKind::kStoreNamedSloppy:
     270             :       case FeedbackSlotKind::kStoreNamedStrict:
     271             :       case FeedbackSlotKind::kStoreOwnNamed:
     272             :       case FeedbackSlotKind::kStoreGlobalSloppy:
     273             :       case FeedbackSlotKind::kStoreGlobalStrict:
     274             :       case FeedbackSlotKind::kStoreKeyedSloppy:
     275             :       case FeedbackSlotKind::kStoreKeyedStrict:
     276             :       case FeedbackSlotKind::kStoreInArrayLiteral:
     277             :       case FeedbackSlotKind::kStoreDataPropertyInLiteral:
     278             :       case FeedbackSlotKind::kTypeProfile: {
     279           0 :         HeapObject heap_object;
     280           0 :         if (obj->IsWeakOrCleared() ||
     281           0 :             (obj->GetHeapObjectIfStrong(&heap_object) &&
     282           0 :              (heap_object->IsWeakFixedArray() || heap_object->IsString()))) {
     283           0 :           with++;
     284           0 :         } else if (obj == megamorphic_sentinel) {
     285           0 :           gen++;
     286           0 :           with++;
     287             :         }
     288           0 :         total++;
     289             :         break;
     290             :       }
     291             :       case FeedbackSlotKind::kBinaryOp: {
     292           0 :         int const feedback = obj.ToSmi().value();
     293             :         BinaryOperationHint hint = BinaryOperationHintFromFeedback(feedback);
     294           0 :         if (hint == BinaryOperationHint::kAny) {
     295           0 :           gen++;
     296             :         }
     297           0 :         if (hint != BinaryOperationHint::kNone) {
     298           0 :           with++;
     299             :         }
     300           0 :         total++;
     301           0 :         break;
     302             :       }
     303             :       case FeedbackSlotKind::kCompareOp: {
     304           0 :         int const feedback = obj.ToSmi().value();
     305           0 :         CompareOperationHint hint = CompareOperationHintFromFeedback(feedback);
     306           0 :         if (hint == CompareOperationHint::kAny) {
     307           0 :           gen++;
     308             :         }
     309           0 :         if (hint != CompareOperationHint::kNone) {
     310           0 :           with++;
     311             :         }
     312           0 :         total++;
     313           0 :         break;
     314             :       }
     315             :       case FeedbackSlotKind::kForIn: {
     316           0 :         int const feedback = obj.ToSmi().value();
     317             :         ForInHint hint = ForInHintFromFeedback(feedback);
     318           0 :         if (hint == ForInHint::kAny) {
     319           0 :           gen++;
     320             :         }
     321           0 :         if (hint != ForInHint::kNone) {
     322           0 :           with++;
     323             :         }
     324           0 :         total++;
     325           0 :         break;
     326             :       }
     327             :       case FeedbackSlotKind::kInstanceOf: {
     328           0 :         if (obj->IsWeakOrCleared()) {
     329           0 :           with++;
     330           0 :         } else if (obj == megamorphic_sentinel) {
     331           0 :           gen++;
     332           0 :           with++;
     333             :         }
     334           0 :         total++;
     335           0 :         break;
     336             :       }
     337             :       case FeedbackSlotKind::kCreateClosure:
     338             :       case FeedbackSlotKind::kLiteral:
     339             :       case FeedbackSlotKind::kCloneObject:
     340             :         break;
     341             :       case FeedbackSlotKind::kInvalid:
     342             :       case FeedbackSlotKind::kKindsNumber:
     343           0 :         UNREACHABLE();
     344             :         break;
     345             :     }
     346             :   }
     347             : 
     348           0 :   *with_type_info = with;
     349           0 :   *generic = gen;
     350           0 :   *vector_ic_count = total;
     351           0 : }
     352             : 
     353             : Handle<Symbol> FeedbackVector::UninitializedSentinel(Isolate* isolate) {
     354             :   return isolate->factory()->uninitialized_symbol();
     355             : }
     356             : 
     357             : Handle<Symbol> FeedbackVector::GenericSentinel(Isolate* isolate) {
     358             :   return isolate->factory()->generic_symbol();
     359             : }
     360             : 
     361             : Handle<Symbol> FeedbackVector::MegamorphicSentinel(Isolate* isolate) {
     362             :   return isolate->factory()->megamorphic_symbol();
     363             : }
     364             : 
     365             : Handle<Symbol> FeedbackVector::PremonomorphicSentinel(Isolate* isolate) {
     366             :   return isolate->factory()->premonomorphic_symbol();
     367             : }
     368             : 
     369       52533 : Symbol FeedbackVector::RawUninitializedSentinel(Isolate* isolate) {
     370       52533 :   return ReadOnlyRoots(isolate).uninitialized_symbol();
     371             : }
     372             : 
     373             : bool FeedbackMetadataIterator::HasNext() const {
     374      268148 :   return next_slot_.ToInt() < metadata()->slot_count();
     375             : }
     376             : 
     377       81452 : FeedbackSlot FeedbackMetadataIterator::Next() {
     378             :   DCHECK(HasNext());
     379       81452 :   cur_slot_ = next_slot_;
     380      162495 :   slot_kind_ = metadata()->GetKind(cur_slot_);
     381       81452 :   next_slot_ = FeedbackSlot(next_slot_.ToInt() + entry_size());
     382       81452 :   return cur_slot_;
     383             : }
     384             : 
     385           0 : int FeedbackMetadataIterator::entry_size() const {
     386       81452 :   return FeedbackMetadata::GetSlotSize(kind());
     387             : }
     388             : 
     389    15329909 : MaybeObject FeedbackNexus::GetFeedback() const {
     390    30659858 :   MaybeObject feedback = vector()->Get(slot());
     391       26116 :   FeedbackVector::AssertNoLegacyTypes(feedback);
     392    15329949 :   return feedback;
     393             : }
     394             : 
     395     6315717 : MaybeObject FeedbackNexus::GetFeedbackExtra() const {
     396             : #ifdef DEBUG
     397             :   FeedbackSlotKind kind = vector()->GetKind(slot());
     398             :   DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
     399             : #endif
     400     6315717 :   int extra_index = vector()->GetIndex(slot()) + 1;
     401     6315721 :   return vector()->get(extra_index);
     402             : }
     403             : 
     404             : void FeedbackNexus::SetFeedback(Object feedback, WriteBarrierMode mode) {
     405      909546 :   SetFeedback(MaybeObject::FromObject(feedback));
     406             : }
     407             : 
     408     7918071 : void FeedbackNexus::SetFeedback(MaybeObject feedback, WriteBarrierMode mode) {
     409             :   FeedbackVector::AssertNoLegacyTypes(feedback);
     410    15836174 :   vector()->Set(slot(), feedback, mode);
     411     7918103 : }
     412             : 
     413     5766948 : void FeedbackNexus::SetFeedbackExtra(Object feedback_extra,
     414             :                                      WriteBarrierMode mode) {
     415             : #ifdef DEBUG
     416             :   FeedbackSlotKind kind = vector()->GetKind(slot());
     417             :   DCHECK_LT(1, FeedbackMetadata::GetSlotSize(kind));
     418             :   FeedbackVector::AssertNoLegacyTypes(MaybeObject::FromObject(feedback_extra));
     419             : #endif
     420     5766948 :   int index = vector()->GetIndex(slot()) + 1;
     421     5766949 :   vector()->set(index, MaybeObject::FromObject(feedback_extra), mode);
     422     5766949 : }
     423             : 
     424     2158596 : void FeedbackNexus::SetFeedbackExtra(MaybeObject feedback_extra,
     425             :                                      WriteBarrierMode mode) {
     426             : #ifdef DEBUG
     427             :   FeedbackVector::AssertNoLegacyTypes(feedback_extra);
     428             : #endif
     429     2158596 :   int index = vector()->GetIndex(slot()) + 1;
     430     2158601 :   vector()->set(index, feedback_extra, mode);
     431     2158609 : }
     432             : 
     433    39353373 : Isolate* FeedbackNexus::GetIsolate() const { return vector()->GetIsolate(); }
     434             : }  // namespace internal
     435             : }  // namespace v8
     436             : 
     437             : #include "src/objects/object-macros-undef.h"
     438             : 
     439             : #endif  // V8_FEEDBACK_VECTOR_INL_H_

Generated by: LCOV version 1.10