LCOV - code coverage report
Current view: top level - src/objects - allocation-site-inl.h (source / functions) Hit Total Coverage
Test: app.info Lines: 53 58 91.4 %
Date: 2019-04-19 Functions: 11 11 100.0 %

          Line data    Source code
       1             : // Copyright 2018 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_OBJECTS_ALLOCATION_SITE_INL_H_
       6             : #define V8_OBJECTS_ALLOCATION_SITE_INL_H_
       7             : 
       8             : #include "src/objects/allocation-site.h"
       9             : 
      10             : #include "src/heap/heap-write-barrier-inl.h"
      11             : #include "src/objects/js-objects-inl.h"
      12             : 
      13             : // Has to be the last include (doesn't have include guards):
      14             : #include "src/objects/object-macros.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : 
      19             : OBJECT_CONSTRUCTORS_IMPL(AllocationMemento, Struct)
      20             : OBJECT_CONSTRUCTORS_IMPL(AllocationSite, Struct)
      21             : 
      22             : NEVER_READ_ONLY_SPACE_IMPL(AllocationSite)
      23             : 
      24             : CAST_ACCESSOR(AllocationMemento)
      25             : CAST_ACCESSOR(AllocationSite)
      26             : 
      27     3477047 : ACCESSORS(AllocationSite, transition_info_or_boilerplate, Object,
      28             :           kTransitionInfoOrBoilerplateOffset)
      29     1735268 : ACCESSORS(AllocationSite, nested_site, Object, kNestedSiteOffset)
      30     1164244 : INT32_ACCESSORS(AllocationSite, pretenure_data, kPretenureDataOffset)
      31     3222083 : INT32_ACCESSORS(AllocationSite, pretenure_create_count,
      32             :                 kPretenureCreateCountOffset)
      33      272115 : ACCESSORS(AllocationSite, dependent_code, DependentCode, kDependentCodeOffset)
      34     8361791 : ACCESSORS_CHECKED(AllocationSite, weak_next, Object, kWeakNextOffset,
      35             :                   HasWeakNext())
      36     4142554 : ACCESSORS(AllocationMemento, allocation_site, Object, kAllocationSiteOffset)
      37             : 
      38             : JSObject AllocationSite::boilerplate() const {
      39             :   DCHECK(PointsToLiteral());
      40             :   return JSObject::cast(transition_info_or_boilerplate());
      41             : }
      42             : 
      43             : void AllocationSite::set_boilerplate(JSObject object, WriteBarrierMode mode) {
      44      112078 :   set_transition_info_or_boilerplate(object, mode);
      45             : }
      46             : 
      47             : int AllocationSite::transition_info() const {
      48             :   DCHECK(!PointsToLiteral());
      49             :   return Smi::cast(transition_info_or_boilerplate())->value();
      50             : }
      51             : 
      52             : void AllocationSite::set_transition_info(int value) {
      53             :   DCHECK(!PointsToLiteral());
      54             :   set_transition_info_or_boilerplate(Smi::FromInt(value), SKIP_WRITE_BARRIER);
      55             : }
      56             : 
      57        2359 : bool AllocationSite::HasWeakNext() const {
      58        2359 :   return map() == GetReadOnlyRoots().allocation_site_map();
      59             : }
      60             : 
      61      190106 : void AllocationSite::Initialize() {
      62      190106 :   set_transition_info_or_boilerplate(Smi::kZero);
      63      190106 :   SetElementsKind(GetInitialFastElementsKind());
      64      190108 :   set_nested_site(Smi::kZero);
      65             :   set_pretenure_data(0);
      66             :   set_pretenure_create_count(0);
      67             :   set_dependent_code(
      68             :       DependentCode::cast(GetReadOnlyRoots().empty_weak_fixed_array()),
      69             :       SKIP_WRITE_BARRIER);
      70      190109 : }
      71             : 
      72             : bool AllocationSite::IsZombie() const {
      73             :   return pretenure_decision() == kZombie;
      74             : }
      75             : 
      76             : bool AllocationSite::IsMaybeTenure() const {
      77             :   return pretenure_decision() == kMaybeTenure;
      78             : }
      79             : 
      80             : bool AllocationSite::PretenuringDecisionMade() const {
      81             :   return pretenure_decision() != kUndecided;
      82             : }
      83             : 
      84             : void AllocationSite::MarkZombie() {
      85             :   DCHECK(!IsZombie());
      86       78009 :   Initialize();
      87             :   set_pretenure_decision(kZombie);
      88             : }
      89             : 
      90             : ElementsKind AllocationSite::GetElementsKind() const {
      91             :   return ElementsKindBits::decode(transition_info());
      92             : }
      93             : 
      94      205805 : void AllocationSite::SetElementsKind(ElementsKind kind) {
      95      411610 :   set_transition_info(ElementsKindBits::update(transition_info(), kind));
      96      205805 : }
      97             : 
      98             : bool AllocationSite::CanInlineCall() const {
      99        2944 :   return DoNotInlineBit::decode(transition_info()) == 0;
     100             : }
     101             : 
     102        2554 : void AllocationSite::SetDoNotInlineCall() {
     103        5108 :   set_transition_info(DoNotInlineBit::update(transition_info(), true));
     104        2554 : }
     105             : 
     106             : bool AllocationSite::PointsToLiteral() const {
     107             :   Object raw_value = transition_info_or_boilerplate();
     108             :   DCHECK_EQ(!raw_value->IsSmi(),
     109             :             raw_value->IsJSArray() || raw_value->IsJSObject());
     110        7647 :   return !raw_value->IsSmi();
     111             : }
     112             : 
     113             : // Heuristic: We only need to create allocation site info if the boilerplate
     114             : // elements kind is the initial elements kind.
     115             : bool AllocationSite::ShouldTrack(ElementsKind boilerplate_elements_kind) {
     116             :   return IsSmiElementsKind(boilerplate_elements_kind);
     117             : }
     118             : 
     119             : inline bool AllocationSite::CanTrack(InstanceType type) {
     120   144375488 :   if (FLAG_allocation_site_pretenuring) {
     121             :     // TurboFan doesn't care at all about String pretenuring feedback,
     122             :     // so don't bother even trying to track that.
     123   144375488 :     return type == JS_ARRAY_TYPE || type == JS_OBJECT_TYPE;
     124             :   }
     125           0 :   return type == JS_ARRAY_TYPE;
     126             : }
     127             : 
     128             : AllocationSite::PretenureDecision AllocationSite::pretenure_decision() const {
     129      728928 :   return PretenureDecisionBits::decode(pretenure_data());
     130             : }
     131             : 
     132             : void AllocationSite::set_pretenure_decision(PretenureDecision decision) {
     133             :   int32_t value = pretenure_data();
     134      157847 :   set_pretenure_data(PretenureDecisionBits::update(value, decision));
     135             : }
     136             : 
     137             : bool AllocationSite::deopt_dependent_code() const {
     138         124 :   return DeoptDependentCodeBit::decode(pretenure_data());
     139             : }
     140             : 
     141             : void AllocationSite::set_deopt_dependent_code(bool deopt) {
     142             :   int32_t value = pretenure_data();
     143         228 :   set_pretenure_data(DeoptDependentCodeBit::update(value, deopt));
     144             : }
     145             : 
     146             : int AllocationSite::memento_found_count() const {
     147             :   return MementoFoundCountBits::decode(pretenure_data());
     148             : }
     149             : 
     150             : inline void AllocationSite::set_memento_found_count(int count) {
     151             :   int32_t value = pretenure_data();
     152             :   // Verify that we can count more mementos than we can possibly find in one
     153             :   // new space collection.
     154             :   DCHECK((GetHeap()->MaxSemiSpaceSize() /
     155             :           (Heap::kMinObjectSizeInTaggedWords * kTaggedSize +
     156             :            AllocationMemento::kSize)) < MementoFoundCountBits::kMax);
     157             :   DCHECK_LT(count, MementoFoundCountBits::kMax);
     158       85776 :   set_pretenure_data(MementoFoundCountBits::update(value, count));
     159             : }
     160             : 
     161             : int AllocationSite::memento_create_count() const {
     162             :   return pretenure_create_count();
     163             : }
     164             : 
     165             : void AllocationSite::set_memento_create_count(int count) {
     166             :   set_pretenure_create_count(count);
     167             : }
     168             : 
     169             : bool AllocationSite::IncrementMementoFoundCount(int increment) {
     170       83008 :   if (IsZombie()) return false;
     171             : 
     172             :   int value = memento_found_count();
     173       83008 :   set_memento_found_count(value + increment);
     174       83008 :   return memento_found_count() >= kPretenureMinimumCreated;
     175             : }
     176             : 
     177             : inline void AllocationSite::IncrementMementoCreateCount() {
     178             :   DCHECK(FLAG_allocation_site_pretenuring);
     179             :   int value = memento_create_count();
     180     1514604 :   set_memento_create_count(value + 1);
     181             : }
     182             : 
     183      394731 : bool AllocationMemento::IsValid() const {
     184      789464 :   return allocation_site()->IsAllocationSite() &&
     185      394731 :          !AllocationSite::cast(allocation_site())->IsZombie();
     186             : }
     187             : 
     188             : AllocationSite AllocationMemento::GetAllocationSite() const {
     189             :   DCHECK(IsValid());
     190             :   return AllocationSite::cast(allocation_site());
     191             : }
     192             : 
     193             : Address AllocationMemento::GetAllocationSiteUnchecked() const {
     194             :   return allocation_site()->ptr();
     195             : }
     196             : 
     197             : template <AllocationSiteUpdateMode update_or_check>
     198      394731 : bool AllocationSite::DigestTransitionFeedback(Handle<AllocationSite> site,
     199             :                                               ElementsKind to_kind) {
     200             :   Isolate* isolate = site->GetIsolate();
     201             :   bool result = false;
     202             : 
     203      404664 :   if (site->PointsToLiteral() && site->boilerplate()->IsJSArray()) {
     204             :     Handle<JSArray> boilerplate(JSArray::cast(site->boilerplate()), isolate);
     205             :     ElementsKind kind = boilerplate->GetElementsKind();
     206             :     // if kind is holey ensure that to_kind is as well.
     207        9933 :     if (IsHoleyElementsKind(kind)) {
     208             :       to_kind = GetHoleyElementsKind(to_kind);
     209             :     }
     210        9933 :     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
     211             :       // If the array is huge, it's not likely to be defined in a local
     212             :       // function, so we shouldn't make new instances of it very often.
     213        7603 :       uint32_t length = 0;
     214       15206 :       CHECK(boilerplate->length()->ToArrayLength(&length));
     215        7603 :       if (length <= kMaximumArrayBytesToPretransition) {
     216             :         if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) {
     217           0 :           return true;
     218             :         }
     219        7603 :         if (FLAG_trace_track_allocation_sites) {
     220           0 :           bool is_nested = site->IsNested();
     221           0 :           PrintF("AllocationSite: JSArray %p boilerplate %supdated %s->%s\n",
     222             :                  reinterpret_cast<void*>(site->ptr()),
     223             :                  is_nested ? "(nested)" : " ", ElementsKindToString(kind),
     224             :                  ElementsKindToString(to_kind));
     225             :         }
     226        7603 :         JSObject::TransitionElementsKind(boilerplate, to_kind);
     227        7603 :         site->dependent_code()->DeoptimizeDependentCodeGroup(
     228             :             isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
     229             :         result = true;
     230             :       }
     231             :     }
     232             :   } else {
     233             :     // The AllocationSite is for a constructed Array.
     234             :     ElementsKind kind = site->GetElementsKind();
     235             :     // if kind is holey ensure that to_kind is as well.
     236      384798 :     if (IsHoleyElementsKind(kind)) {
     237             :       to_kind = GetHoleyElementsKind(to_kind);
     238             :     }
     239      384798 :     if (IsMoreGeneralElementsKindTransition(kind, to_kind)) {
     240             :       if (update_or_check == AllocationSiteUpdateMode::kCheckOnly) return true;
     241       15700 :       if (FLAG_trace_track_allocation_sites) {
     242           0 :         PrintF("AllocationSite: JSArray %p site updated %s->%s\n",
     243             :                reinterpret_cast<void*>(site->ptr()), ElementsKindToString(kind),
     244             :                ElementsKindToString(to_kind));
     245             :       }
     246       15700 :       site->SetElementsKind(to_kind);
     247       15700 :       site->dependent_code()->DeoptimizeDependentCodeGroup(
     248             :           isolate, DependentCode::kAllocationSiteTransitionChangedGroup);
     249             :       result = true;
     250             :     }
     251             :   }
     252             :   return result;
     253             : }
     254             : 
     255             : }  // namespace internal
     256             : }  // namespace v8
     257             : 
     258             : #include "src/objects/object-macros-undef.h"
     259             : 
     260             : #endif  // V8_OBJECTS_ALLOCATION_SITE_INL_H_

Generated by: LCOV version 1.10