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

Generated by: LCOV version 1.10