LCOV - code coverage report
Current view: top level - src/compiler - compilation-dependencies.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 239 242 98.8 %
Date: 2019-04-19 Functions: 54 55 98.2 %

          Line data    Source code
       1             : // Copyright 2015 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/compiler/compilation-dependencies.h"
       6             : 
       7             : #include "src/handles-inl.h"
       8             : #include "src/objects-inl.h"
       9             : #include "src/objects/allocation-site-inl.h"
      10             : #include "src/zone/zone-handle-set.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : namespace compiler {
      15             : 
      16      483560 : CompilationDependencies::CompilationDependencies(JSHeapBroker* broker,
      17             :                                                  Zone* zone)
      18      967120 :     : zone_(zone), broker_(broker), dependencies_(zone) {}
      19             : 
      20      595240 : class CompilationDependencies::Dependency : public ZoneObject {
      21             :  public:
      22             :   virtual bool IsValid() const = 0;
      23      585689 :   virtual void PrepareInstall() {}
      24             :   virtual void Install(const MaybeObjectHandle& code) = 0;
      25             : 
      26             : #ifdef DEBUG
      27             :   virtual bool IsPretenureModeDependency() const { return false; }
      28             : #endif
      29             : };
      30             : 
      31             : class InitialMapDependency final : public CompilationDependencies::Dependency {
      32             :  public:
      33             :   // TODO(neis): Once the concurrent compiler frontend is always-on, we no
      34             :   // longer need to explicitly store the initial map.
      35             :   InitialMapDependency(const JSFunctionRef& function, const MapRef& initial_map)
      36        5446 :       : function_(function), initial_map_(initial_map) {
      37             :     DCHECK(function_.has_initial_map());
      38             :     DCHECK(function_.initial_map().equals(initial_map_));
      39             :   }
      40             : 
      41       10841 :   bool IsValid() const override {
      42       10841 :     Handle<JSFunction> function = function_.object();
      43       21682 :     return function->has_initial_map() &&
      44       21682 :            function->initial_map() == *initial_map_.object();
      45             :   }
      46             : 
      47        5420 :   void Install(const MaybeObjectHandle& code) override {
      48             :     SLOW_DCHECK(IsValid());
      49       16260 :     DependentCode::InstallDependency(function_.isolate(), code,
      50             :                                      initial_map_.object(),
      51        5420 :                                      DependentCode::kInitialMapChangedGroup);
      52        5420 :   }
      53             : 
      54             :  private:
      55             :   JSFunctionRef function_;
      56             :   MapRef initial_map_;
      57             : };
      58             : 
      59             : class PrototypePropertyDependency final
      60             :     : public CompilationDependencies::Dependency {
      61             :  public:
      62             :   // TODO(neis): Once the concurrent compiler frontend is always-on, we no
      63             :   // longer need to explicitly store the prototype.
      64             :   PrototypePropertyDependency(const JSFunctionRef& function,
      65             :                               const ObjectRef& prototype)
      66        1348 :       : function_(function), prototype_(prototype) {
      67             :     DCHECK(function_.has_prototype());
      68             :     DCHECK(!function_.PrototypeRequiresRuntimeLookup());
      69             :     DCHECK(function_.prototype().equals(prototype_));
      70             :   }
      71             : 
      72        2672 :   bool IsValid() const override {
      73        2672 :     Handle<JSFunction> function = function_.object();
      74       10688 :     return function->has_prototype_slot() && function->has_prototype() &&
      75        8016 :            !function->PrototypeRequiresRuntimeLookup() &&
      76        8016 :            function->prototype() == *prototype_.object();
      77             :   }
      78             : 
      79        1343 :   void PrepareInstall() override {
      80             :     SLOW_DCHECK(IsValid());
      81        1343 :     Handle<JSFunction> function = function_.object();
      82        1343 :     if (!function->has_initial_map()) JSFunction::EnsureHasInitialMap(function);
      83        1343 :   }
      84             : 
      85        1329 :   void Install(const MaybeObjectHandle& code) override {
      86             :     SLOW_DCHECK(IsValid());
      87        1329 :     Handle<JSFunction> function = function_.object();
      88             :     DCHECK(function->has_initial_map());
      89        1329 :     Handle<Map> initial_map(function->initial_map(), function_.isolate());
      90        2658 :     DependentCode::InstallDependency(function_.isolate(), code, initial_map,
      91        1329 :                                      DependentCode::kInitialMapChangedGroup);
      92        1329 :   }
      93             : 
      94             :  private:
      95             :   JSFunctionRef function_;
      96             :   ObjectRef prototype_;
      97             : };
      98             : 
      99             : class StableMapDependency final : public CompilationDependencies::Dependency {
     100             :  public:
     101      162640 :   explicit StableMapDependency(const MapRef& map) : map_(map) {
     102             :     DCHECK(map_.is_stable());
     103             :   }
     104             : 
     105      647944 :   bool IsValid() const override { return map_.object()->is_stable(); }
     106             : 
     107      161961 :   void Install(const MaybeObjectHandle& code) override {
     108             :     SLOW_DCHECK(IsValid());
     109      485883 :     DependentCode::InstallDependency(map_.isolate(), code, map_.object(),
     110      161961 :                                      DependentCode::kPrototypeCheckGroup);
     111      161961 :   }
     112             : 
     113             :  private:
     114             :   MapRef map_;
     115             : };
     116             : 
     117             : class TransitionDependency final : public CompilationDependencies::Dependency {
     118             :  public:
     119       19644 :   explicit TransitionDependency(const MapRef& map) : map_(map) {
     120             :     DCHECK(!map_.is_deprecated());
     121             :   }
     122             : 
     123       78444 :   bool IsValid() const override { return !map_.object()->is_deprecated(); }
     124             : 
     125       19609 :   void Install(const MaybeObjectHandle& code) override {
     126             :     SLOW_DCHECK(IsValid());
     127       58827 :     DependentCode::InstallDependency(map_.isolate(), code, map_.object(),
     128       19609 :                                      DependentCode::kTransitionGroup);
     129       19609 :   }
     130             : 
     131             :  private:
     132             :   MapRef map_;
     133             : };
     134             : 
     135             : class PretenureModeDependency final
     136             :     : public CompilationDependencies::Dependency {
     137             :  public:
     138             :   // TODO(neis): Once the concurrent compiler frontend is always-on, we no
     139             :   // longer need to explicitly store the mode.
     140             :   PretenureModeDependency(const AllocationSiteRef& site,
     141             :                           AllocationType allocation)
     142        7521 :       : site_(site), allocation_(allocation) {
     143             :     DCHECK_EQ(allocation, site_.GetAllocationType());
     144             :   }
     145             : 
     146       14818 :   bool IsValid() const override {
     147       29636 :     return allocation_ == site_.object()->GetAllocationType();
     148             :   }
     149             : 
     150        7403 :   void Install(const MaybeObjectHandle& code) override {
     151             :     SLOW_DCHECK(IsValid());
     152       22209 :     DependentCode::InstallDependency(
     153             :         site_.isolate(), code, site_.object(),
     154        7403 :         DependentCode::kAllocationSiteTenuringChangedGroup);
     155        7403 :   }
     156             : 
     157             : #ifdef DEBUG
     158             :   bool IsPretenureModeDependency() const override { return true; }
     159             : #endif
     160             : 
     161             :  private:
     162             :   AllocationSiteRef site_;
     163             :   AllocationType allocation_;
     164             : };
     165             : 
     166             : class FieldRepresentationDependency final
     167             :     : public CompilationDependencies::Dependency {
     168             :  public:
     169             :   // TODO(neis): Once the concurrent compiler frontend is always-on, we no
     170             :   // longer need to explicitly store the representation.
     171             :   FieldRepresentationDependency(const MapRef& owner, int descriptor,
     172             :                                 Representation representation)
     173             :       : owner_(owner),
     174             :         descriptor_(descriptor),
     175      111007 :         representation_(representation) {
     176             :     DCHECK(owner_.equals(owner_.FindFieldOwner(descriptor_)));
     177             :     DCHECK(representation_.Equals(
     178             :         owner_.GetPropertyDetails(descriptor_).representation()));
     179             :   }
     180             : 
     181      220745 :   bool IsValid() const override {
     182             :     DisallowHeapAllocation no_heap_allocation;
     183      220745 :     Handle<Map> owner = owner_.object();
     184      441490 :     return representation_.Equals(owner->instance_descriptors()
     185      662235 :                                       ->GetDetails(descriptor_)
     186      220745 :                                       .representation());
     187             :   }
     188             : 
     189      110367 :   void Install(const MaybeObjectHandle& code) override {
     190             :     SLOW_DCHECK(IsValid());
     191      331101 :     DependentCode::InstallDependency(owner_.isolate(), code, owner_.object(),
     192      110367 :                                      DependentCode::kFieldOwnerGroup);
     193      110367 :   }
     194             : 
     195             :  private:
     196             :   MapRef owner_;
     197             :   int descriptor_;
     198             :   Representation representation_;
     199             : };
     200             : 
     201             : class FieldTypeDependency final : public CompilationDependencies::Dependency {
     202             :  public:
     203             :   // TODO(neis): Once the concurrent compiler frontend is always-on, we no
     204             :   // longer need to explicitly store the type.
     205             :   FieldTypeDependency(const MapRef& owner, int descriptor,
     206             :                       const ObjectRef& type)
     207        3843 :       : owner_(owner), descriptor_(descriptor), type_(type) {
     208             :     DCHECK(owner_.equals(owner_.FindFieldOwner(descriptor_)));
     209             :     DCHECK(type_.equals(owner_.GetFieldType(descriptor_)));
     210             :   }
     211             : 
     212        7568 :   bool IsValid() const override {
     213             :     DisallowHeapAllocation no_heap_allocation;
     214        7568 :     Handle<Map> owner = owner_.object();
     215        7568 :     Handle<Object> type = type_.object();
     216       22704 :     return *type == owner->instance_descriptors()->GetFieldType(descriptor_);
     217             :   }
     218             : 
     219        3784 :   void Install(const MaybeObjectHandle& code) override {
     220             :     SLOW_DCHECK(IsValid());
     221       11352 :     DependentCode::InstallDependency(owner_.isolate(), code, owner_.object(),
     222        3784 :                                      DependentCode::kFieldOwnerGroup);
     223        3784 :   }
     224             : 
     225             :  private:
     226             :   MapRef owner_;
     227             :   int descriptor_;
     228             :   ObjectRef type_;
     229             : };
     230             : 
     231             : class FieldConstnessDependency final
     232             :     : public CompilationDependencies::Dependency {
     233             :  public:
     234             :   FieldConstnessDependency(const MapRef& owner, int descriptor)
     235       70924 :       : owner_(owner), descriptor_(descriptor) {
     236             :     DCHECK(owner_.equals(owner_.FindFieldOwner(descriptor_)));
     237             :     DCHECK_EQ(PropertyConstness::kConst,
     238             :               owner_.GetPropertyDetails(descriptor_).constness());
     239             :   }
     240             : 
     241      141350 :   bool IsValid() const override {
     242             :     DisallowHeapAllocation no_heap_allocation;
     243      141350 :     Handle<Map> owner = owner_.object();
     244             :     return PropertyConstness::kConst ==
     245      424050 :            owner->instance_descriptors()->GetDetails(descriptor_).constness();
     246             :   }
     247             : 
     248       70670 :   void Install(const MaybeObjectHandle& code) override {
     249             :     SLOW_DCHECK(IsValid());
     250      212010 :     DependentCode::InstallDependency(owner_.isolate(), code, owner_.object(),
     251       70670 :                                      DependentCode::kFieldOwnerGroup);
     252       70670 :   }
     253             : 
     254             :  private:
     255             :   MapRef owner_;
     256             :   int descriptor_;
     257             : };
     258             : 
     259             : class GlobalPropertyDependency final
     260             :     : public CompilationDependencies::Dependency {
     261             :  public:
     262             :   // TODO(neis): Once the concurrent compiler frontend is always-on, we no
     263             :   // longer need to explicitly store the type and the read_only flag.
     264             :   GlobalPropertyDependency(const PropertyCellRef& cell, PropertyCellType type,
     265             :                            bool read_only)
     266      184646 :       : cell_(cell), type_(type), read_only_(read_only) {
     267             :     DCHECK_EQ(type_, cell_.property_details().cell_type());
     268             :     DCHECK_EQ(read_only_, cell_.property_details().IsReadOnly());
     269             :   }
     270             : 
     271      367502 :   bool IsValid() const override {
     272      367502 :     Handle<PropertyCell> cell = cell_.object();
     273             :     // The dependency is never valid if the cell is 'invalidated'. This is
     274             :     // marked by setting the value to the hole.
     275      735004 :     if (cell->value() == *(cell_.isolate()->factory()->the_hole_value())) {
     276             :       DCHECK(cell->property_details().cell_type() ==
     277             :                  PropertyCellType::kInvalidated ||
     278             :              cell->property_details().cell_type() ==
     279             :                  PropertyCellType::kUninitialized);
     280             :       return false;
     281             :     }
     282     1102479 :     return type_ == cell->property_details().cell_type() &&
     283      367491 :            read_only_ == cell->property_details().IsReadOnly();
     284             :   }
     285             : 
     286      183702 :   void Install(const MaybeObjectHandle& code) override {
     287             :     SLOW_DCHECK(IsValid());
     288      551106 :     DependentCode::InstallDependency(cell_.isolate(), code, cell_.object(),
     289      183702 :                                      DependentCode::kPropertyCellChangedGroup);
     290      183702 :   }
     291             : 
     292             :  private:
     293             :   PropertyCellRef cell_;
     294             :   PropertyCellType type_;
     295             :   bool read_only_;
     296             : };
     297             : 
     298             : class ProtectorDependency final : public CompilationDependencies::Dependency {
     299             :  public:
     300       19824 :   explicit ProtectorDependency(const PropertyCellRef& cell) : cell_(cell) {
     301             :     DCHECK_EQ(cell_.value().AsSmi(), Isolate::kProtectorValid);
     302             :   }
     303             : 
     304       39436 :   bool IsValid() const override {
     305       39436 :     Handle<PropertyCell> cell = cell_.object();
     306       39436 :     return cell->value() == Smi::FromInt(Isolate::kProtectorValid);
     307             :   }
     308             : 
     309       19716 :   void Install(const MaybeObjectHandle& code) override {
     310             :     SLOW_DCHECK(IsValid());
     311       59148 :     DependentCode::InstallDependency(cell_.isolate(), code, cell_.object(),
     312       19716 :                                      DependentCode::kPropertyCellChangedGroup);
     313       19716 :   }
     314             : 
     315             :  private:
     316             :   PropertyCellRef cell_;
     317             : };
     318             : 
     319             : class ElementsKindDependency final
     320             :     : public CompilationDependencies::Dependency {
     321             :  public:
     322             :   // TODO(neis): Once the concurrent compiler frontend is always-on, we no
     323             :   // longer need to explicitly store the elements kind.
     324             :   ElementsKindDependency(const AllocationSiteRef& site, ElementsKind kind)
     325        2951 :       : site_(site), kind_(kind) {
     326             :     DCHECK(AllocationSite::ShouldTrack(kind_));
     327             :     DCHECK_EQ(kind_, site_.PointsToLiteral()
     328             :                          ? site_.boilerplate().value().GetElementsKind()
     329             :                          : site_.GetElementsKind());
     330             :   }
     331             : 
     332        5822 :   bool IsValid() const override {
     333        5822 :     Handle<AllocationSite> site = site_.object();
     334             :     ElementsKind kind = site->PointsToLiteral()
     335             :                             ? site->boilerplate()->GetElementsKind()
     336        5822 :                             : site->GetElementsKind();
     337        5822 :     return kind_ == kind;
     338             :   }
     339             : 
     340        2903 :   void Install(const MaybeObjectHandle& code) override {
     341             :     SLOW_DCHECK(IsValid());
     342        8709 :     DependentCode::InstallDependency(
     343             :         site_.isolate(), code, site_.object(),
     344        2903 :         DependentCode::kAllocationSiteTransitionChangedGroup);
     345        2903 :   }
     346             : 
     347             :  private:
     348             :   AllocationSiteRef site_;
     349             :   ElementsKind kind_;
     350             : };
     351             : 
     352             : class InitialMapInstanceSizePredictionDependency final
     353             :     : public CompilationDependencies::Dependency {
     354             :  public:
     355             :   InitialMapInstanceSizePredictionDependency(const JSFunctionRef& function,
     356             :                                              int instance_size)
     357        5446 :       : function_(function), instance_size_(instance_size) {}
     358             : 
     359       10847 :   bool IsValid() const override {
     360             :     // The dependency is valid if the prediction is the same as the current
     361             :     // slack tracking result.
     362       21694 :     if (!function_.object()->has_initial_map()) return false;
     363       32523 :     int instance_size = function_.object()->ComputeInstanceSizeWithMinSlack(
     364       10841 :         function_.isolate());
     365       10841 :     return instance_size == instance_size_;
     366             :   }
     367             : 
     368        5421 :   void PrepareInstall() override {
     369             :     SLOW_DCHECK(IsValid());
     370       10842 :     function_.object()->CompleteInobjectSlackTrackingIfActive();
     371        5421 :   }
     372             : 
     373        5420 :   void Install(const MaybeObjectHandle& code) override {
     374             :     SLOW_DCHECK(IsValid());
     375             :     DCHECK(!function_.object()
     376             :                 ->initial_map()
     377             :                 ->IsInobjectSlackTrackingInProgress());
     378        5420 :   }
     379             : 
     380             :  private:
     381             :   JSFunctionRef function_;
     382             :   int instance_size_;
     383             : };
     384             : 
     385        5446 : MapRef CompilationDependencies::DependOnInitialMap(
     386             :     const JSFunctionRef& function) {
     387        5446 :   MapRef map = function.initial_map();
     388       16338 :   dependencies_.push_front(new (zone_) InitialMapDependency(function, map));
     389        5446 :   return map;
     390             : }
     391             : 
     392        1348 : ObjectRef CompilationDependencies::DependOnPrototypeProperty(
     393             :     const JSFunctionRef& function) {
     394        1348 :   ObjectRef prototype = function.prototype();
     395        2696 :   dependencies_.push_front(
     396        1348 :       new (zone_) PrototypePropertyDependency(function, prototype));
     397        1348 :   return prototype;
     398             : }
     399             : 
     400      164497 : void CompilationDependencies::DependOnStableMap(const MapRef& map) {
     401      164497 :   if (map.CanTransition()) {
     402      487920 :     dependencies_.push_front(new (zone_) StableMapDependency(map));
     403             :   } else {
     404             :     DCHECK(map.is_stable());
     405             :   }
     406      164497 : }
     407             : 
     408       22026 : void CompilationDependencies::DependOnTransition(const MapRef& target_map) {
     409       22026 :   if (target_map.CanBeDeprecated()) {
     410       58932 :     dependencies_.push_front(new (zone_) TransitionDependency(target_map));
     411             :   } else {
     412             :     DCHECK(!target_map.is_deprecated());
     413             :   }
     414       22026 : }
     415             : 
     416        7521 : AllocationType CompilationDependencies::DependOnPretenureMode(
     417             :     const AllocationSiteRef& site) {
     418        7521 :   AllocationType allocation = site.GetAllocationType();
     419       22563 :   dependencies_.push_front(new (zone_)
     420             :                                PretenureModeDependency(site, allocation));
     421        7521 :   return allocation;
     422             : }
     423             : 
     424       70924 : PropertyConstness CompilationDependencies::DependOnFieldConstness(
     425             :     const MapRef& map, int descriptor) {
     426       70924 :   MapRef owner = map.FindFieldOwner(descriptor);
     427             :   PropertyConstness constness =
     428      141848 :       owner.GetPropertyDetails(descriptor).constness();
     429       70924 :   if (constness == PropertyConstness::kMutable) return constness;
     430             : 
     431             :   // If the map can have fast elements transitions, then the field can be only
     432             :   // considered constant if the map does not transition.
     433      141848 :   if (Map::CanHaveFastTransitionableElementsKind(map.instance_type())) {
     434             :     // If the map can already transition away, let us report the field as
     435             :     // mutable.
     436       13650 :     if (!map.is_stable()) {
     437             :       return PropertyConstness::kMutable;
     438             :     }
     439       13650 :     DependOnStableMap(map);
     440             :   }
     441             : 
     442             :   DCHECK_EQ(constness, PropertyConstness::kConst);
     443      212772 :   dependencies_.push_front(new (zone_)
     444             :                                FieldConstnessDependency(owner, descriptor));
     445       70924 :   return PropertyConstness::kConst;
     446             : }
     447             : 
     448      111007 : void CompilationDependencies::DependOnFieldRepresentation(const MapRef& map,
     449             :                                                           int descriptor) {
     450      111007 :   MapRef owner = map.FindFieldOwner(descriptor);
     451      111007 :   PropertyDetails details = owner.GetPropertyDetails(descriptor);
     452             :   DCHECK(details.representation().Equals(
     453             :       map.GetPropertyDetails(descriptor).representation()));
     454      333021 :   dependencies_.push_front(new (zone_) FieldRepresentationDependency(
     455             :       owner, descriptor, details.representation()));
     456      111007 : }
     457             : 
     458        3843 : void CompilationDependencies::DependOnFieldType(const MapRef& map,
     459             :                                                 int descriptor) {
     460        3843 :   MapRef owner = map.FindFieldOwner(descriptor);
     461        3843 :   ObjectRef type = owner.GetFieldType(descriptor);
     462             :   DCHECK(type.equals(map.GetFieldType(descriptor)));
     463       11529 :   dependencies_.push_front(new (zone_)
     464             :                                FieldTypeDependency(owner, descriptor, type));
     465        3843 : }
     466             : 
     467      184646 : void CompilationDependencies::DependOnGlobalProperty(
     468             :     const PropertyCellRef& cell) {
     469      369292 :   PropertyCellType type = cell.property_details().cell_type();
     470      369292 :   bool read_only = cell.property_details().IsReadOnly();
     471      553938 :   dependencies_.push_front(new (zone_)
     472             :                                GlobalPropertyDependency(cell, type, read_only));
     473      184646 : }
     474             : 
     475       20744 : bool CompilationDependencies::DependOnProtector(const PropertyCellRef& cell) {
     476       20744 :   if (cell.value().AsSmi() != Isolate::kProtectorValid) return false;
     477       59472 :   dependencies_.push_front(new (zone_) ProtectorDependency(cell));
     478       19824 :   return true;
     479             : }
     480             : 
     481        8008 : bool CompilationDependencies::DependOnArrayBufferDetachingProtector() {
     482        8008 :   return DependOnProtector(PropertyCellRef(
     483             :       broker_,
     484       24024 :       broker_->isolate()->factory()->array_buffer_detaching_protector()));
     485             : }
     486             : 
     487         991 : bool CompilationDependencies::DependOnArrayIteratorProtector() {
     488         991 :   return DependOnProtector(PropertyCellRef(
     489        2973 :       broker_, broker_->isolate()->factory()->array_iterator_protector()));
     490             : }
     491             : 
     492         806 : bool CompilationDependencies::DependOnArraySpeciesProtector() {
     493         806 :   return DependOnProtector(PropertyCellRef(
     494        2418 :       broker_, broker_->isolate()->factory()->array_species_protector()));
     495             : }
     496             : 
     497        6549 : bool CompilationDependencies::DependOnNoElementsProtector() {
     498        6549 :   return DependOnProtector(PropertyCellRef(
     499       19647 :       broker_, broker_->isolate()->factory()->no_elements_protector()));
     500             : }
     501             : 
     502        4019 : bool CompilationDependencies::DependOnPromiseHookProtector() {
     503        4019 :   return DependOnProtector(PropertyCellRef(
     504       12057 :       broker_, broker_->isolate()->factory()->promise_hook_protector()));
     505             : }
     506             : 
     507         228 : bool CompilationDependencies::DependOnPromiseSpeciesProtector() {
     508         228 :   return DependOnProtector(PropertyCellRef(
     509         684 :       broker_, broker_->isolate()->factory()->promise_species_protector()));
     510             : }
     511             : 
     512         109 : bool CompilationDependencies::DependOnPromiseThenProtector() {
     513         109 :   return DependOnProtector(PropertyCellRef(
     514         327 :       broker_, broker_->isolate()->factory()->promise_then_protector()));
     515             : }
     516             : 
     517        7740 : void CompilationDependencies::DependOnElementsKind(
     518             :     const AllocationSiteRef& site) {
     519             :   // Do nothing if the object doesn't have any useful element transitions left.
     520        7740 :   ElementsKind kind = site.PointsToLiteral()
     521       20246 :                           ? site.boilerplate().value().GetElementsKind()
     522       15480 :                           : site.GetElementsKind();
     523        7740 :   if (AllocationSite::ShouldTrack(kind)) {
     524        8853 :     dependencies_.push_front(new (zone_) ElementsKindDependency(site, kind));
     525             :   }
     526        7740 : }
     527             : 
     528           0 : bool CompilationDependencies::AreValid() const {
     529           0 :   for (auto dep : dependencies_) {
     530           0 :     if (!dep->IsValid()) return false;
     531             :   }
     532             :   return true;
     533             : }
     534             : 
     535      464251 : bool CompilationDependencies::Commit(Handle<Code> code) {
     536     1056704 :   for (auto dep : dependencies_) {
     537      592497 :     if (!dep->IsValid()) {
     538             :       dependencies_.clear();
     539             :       return false;
     540             :     }
     541      592453 :     dep->PrepareInstall();
     542             :   }
     543             : 
     544             :   DisallowCodeDependencyChange no_dependency_change;
     545     1056491 :   for (auto dep : dependencies_) {
     546             :     // Check each dependency's validity again right before installing it,
     547             :     // because the first iteration above might have invalidated some
     548             :     // dependencies. For example, PrototypePropertyDependency::PrepareInstall
     549             :     // can call EnsureHasInitialMap, which can invalidate a StableMapDependency
     550             :     // on the prototype object's map.
     551      592298 :     if (!dep->IsValid()) {
     552             :       dependencies_.clear();
     553             :       return false;
     554             :     }
     555      592284 :     dep->Install(MaybeObjectHandle::Weak(code));
     556             :   }
     557             : 
     558             :   // It is even possible that a GC during the above installations invalidated
     559             :   // one of the dependencies. However, this should only affect pretenure mode
     560             :   // dependencies, which we assert below. It is safe to return successfully in
     561             :   // these cases, because once the code gets executed it will do a stack check
     562             :   // that triggers its deoptimization.
     563      464193 :   if (FLAG_stress_gc_during_compilation) {
     564           4 :     broker_->isolate()->heap()->PreciseCollectAllGarbage(
     565             :         Heap::kNoGCFlags, GarbageCollectionReason::kTesting,
     566           4 :         kGCCallbackFlagForced);
     567             :   }
     568             : #ifdef DEBUG
     569             :   for (auto dep : dependencies_) {
     570             :     CHECK_IMPLIES(!dep->IsValid(), dep->IsPretenureModeDependency());
     571             :   }
     572             : #endif
     573             : 
     574             :   dependencies_.clear();
     575      464193 :   return true;
     576             : }
     577             : 
     578             : namespace {
     579             : // This function expects to never see a JSProxy.
     580       54710 : void DependOnStablePrototypeChain(CompilationDependencies* deps, MapRef map,
     581             :                                   base::Optional<JSObjectRef> last_prototype) {
     582       30185 :   while (true) {
     583       84895 :     map.SerializePrototype();
     584       84895 :     HeapObjectRef proto = map.prototype();
     585       84895 :     if (!proto.IsJSObject()) {
     586          50 :       CHECK_EQ(proto.map().oddball_type(), OddballType::kNull);
     587       54710 :       break;
     588             :     }
     589       84845 :     map = proto.map();
     590       84845 :     deps->DependOnStableMap(map);
     591       84845 :     if (last_prototype.has_value() && proto.equals(*last_prototype)) break;
     592             :   }
     593       54710 : }
     594             : }  // namespace
     595             : 
     596             : template <class MapContainer>
     597       52465 : void CompilationDependencies::DependOnStablePrototypeChains(
     598             :     MapContainer const& receiver_maps, WhereToStart start,
     599             :     base::Optional<JSObjectRef> last_prototype) {
     600             :   // Determine actual holder and perform prototype chain checks.
     601      107175 :   for (auto map : receiver_maps) {
     602       54710 :     MapRef receiver_map(broker_, map);
     603       54710 :     if (receiver_map.IsPrimitiveMap()) {
     604             :       // Perform the implicit ToObject for primitives here.
     605             :       // Implemented according to ES6 section 7.3.2 GetV (V, P).
     606             :       base::Optional<JSFunctionRef> constructor =
     607        8124 :           broker_->native_context().GetConstructorFunction(receiver_map);
     608        8124 :       if (constructor.has_value()) receiver_map = constructor->initial_map();
     609             :     }
     610       54710 :     if (start == kStartAtReceiver) DependOnStableMap(receiver_map);
     611       54710 :     DependOnStablePrototypeChain(this, receiver_map, last_prototype);
     612             :   }
     613       52465 : }
     614             : template void CompilationDependencies::DependOnStablePrototypeChains(
     615             :     MapHandles const& receiver_maps, WhereToStart start,
     616             :     base::Optional<JSObjectRef> last_prototype);
     617             : template void CompilationDependencies::DependOnStablePrototypeChains(
     618             :     ZoneHandleSet<Map> const& receiver_maps, WhereToStart start,
     619             :     base::Optional<JSObjectRef> last_prototype);
     620             : 
     621        6034 : void CompilationDependencies::DependOnElementsKinds(
     622             :     const AllocationSiteRef& site) {
     623        6034 :   AllocationSiteRef current = site;
     624         219 :   while (true) {
     625        6253 :     DependOnElementsKind(current);
     626        6253 :     if (!current.nested_site().IsAllocationSite()) break;
     627         219 :     current = current.nested_site().AsAllocationSite();
     628             :   }
     629        6034 :   CHECK_EQ(current.nested_site().AsSmi(), 0);
     630        6034 : }
     631             : 
     632         951 : SlackTrackingPrediction::SlackTrackingPrediction(MapRef initial_map,
     633             :                                                  int instance_size)
     634             :     : instance_size_(instance_size),
     635             :       inobject_property_count_(
     636       12794 :           (instance_size >> kTaggedSizeLog2) -
     637        8299 :           initial_map.GetInObjectPropertiesStartInWords()) {}
     638             : 
     639             : SlackTrackingPrediction
     640        5446 : CompilationDependencies::DependOnInitialMapInstanceSizePrediction(
     641             :     const JSFunctionRef& function) {
     642        5446 :   MapRef initial_map = DependOnInitialMap(function);
     643        5446 :   int instance_size = function.InitialMapInstanceSizeWithMinSlack();
     644             :   // Currently, we always install the prediction dependency. If this turns out
     645             :   // to be too expensive, we can only install the dependency if slack
     646             :   // tracking is active.
     647       10892 :   dependencies_.push_front(
     648        5446 :       new (zone_)
     649             :           InitialMapInstanceSizePredictionDependency(function, instance_size));
     650             :   DCHECK_LE(instance_size, function.initial_map().instance_size());
     651        5446 :   return SlackTrackingPrediction(initial_map, instance_size);
     652             : }
     653             : 
     654             : }  // namespace compiler
     655             : }  // namespace internal
     656      122036 : }  // namespace v8

Generated by: LCOV version 1.10