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-17 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      483336 : CompilationDependencies::CompilationDependencies(JSHeapBroker* broker,
      17             :                                                  Zone* zone)
      18      966672 :     : zone_(zone), broker_(broker), dependencies_(zone) {}
      19             : 
      20      599195 : class CompilationDependencies::Dependency : public ZoneObject {
      21             :  public:
      22             :   virtual bool IsValid() const = 0;
      23      588669 :   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        5415 :       : function_(function), initial_map_(initial_map) {
      37             :     DCHECK(function_.has_initial_map());
      38             :     DCHECK(function_.initial_map().equals(initial_map_));
      39             :   }
      40             : 
      41       10770 :   bool IsValid() const override {
      42       10770 :     Handle<JSFunction> function = function_.object();
      43       21540 :     return function->has_initial_map() &&
      44       21540 :            function->initial_map() == *initial_map_.object();
      45             :   }
      46             : 
      47        5384 :   void Install(const MaybeObjectHandle& code) override {
      48             :     SLOW_DCHECK(IsValid());
      49       16152 :     DependentCode::InstallDependency(function_.isolate(), code,
      50             :                                      initial_map_.object(),
      51        5384 :                                      DependentCode::kInitialMapChangedGroup);
      52        5384 :   }
      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        1364 :       : function_(function), prototype_(prototype) {
      67             :     DCHECK(function_.has_prototype());
      68             :     DCHECK(!function_.PrototypeRequiresRuntimeLookup());
      69             :     DCHECK(function_.prototype().equals(prototype_));
      70             :   }
      71             : 
      72        2704 :   bool IsValid() const override {
      73        2704 :     Handle<JSFunction> function = function_.object();
      74       10816 :     return function->has_prototype_slot() && function->has_prototype() &&
      75        8112 :            !function->PrototypeRequiresRuntimeLookup() &&
      76        8112 :            function->prototype() == *prototype_.object();
      77             :   }
      78             : 
      79        1359 :   void PrepareInstall() override {
      80             :     SLOW_DCHECK(IsValid());
      81        1359 :     Handle<JSFunction> function = function_.object();
      82        1359 :     if (!function->has_initial_map()) JSFunction::EnsureHasInitialMap(function);
      83        1359 :   }
      84             : 
      85        1345 :   void Install(const MaybeObjectHandle& code) override {
      86             :     SLOW_DCHECK(IsValid());
      87        1345 :     Handle<JSFunction> function = function_.object();
      88             :     DCHECK(function->has_initial_map());
      89        1345 :     Handle<Map> initial_map(function->initial_map(), function_.isolate());
      90        2690 :     DependentCode::InstallDependency(function_.isolate(), code, initial_map,
      91        1345 :                                      DependentCode::kInitialMapChangedGroup);
      92        1345 :   }
      93             : 
      94             :  private:
      95             :   JSFunctionRef function_;
      96             :   ObjectRef prototype_;
      97             : };
      98             : 
      99             : class StableMapDependency final : public CompilationDependencies::Dependency {
     100             :  public:
     101      163601 :   explicit StableMapDependency(const MapRef& map) : map_(map) {
     102             :     DCHECK(map_.is_stable());
     103             :   }
     104             : 
     105      650754 :   bool IsValid() const override { return map_.object()->is_stable(); }
     106             : 
     107      162653 :   void Install(const MaybeObjectHandle& code) override {
     108             :     SLOW_DCHECK(IsValid());
     109      487959 :     DependentCode::InstallDependency(map_.isolate(), code, map_.object(),
     110      162653 :                                      DependentCode::kPrototypeCheckGroup);
     111      162653 :   }
     112             : 
     113             :  private:
     114             :   MapRef map_;
     115             : };
     116             : 
     117             : class TransitionDependency final : public CompilationDependencies::Dependency {
     118             :  public:
     119       19648 :   explicit TransitionDependency(const MapRef& map) : map_(map) {
     120             :     DCHECK(!map_.is_deprecated());
     121             :   }
     122             : 
     123       78488 :   bool IsValid() const override { return !map_.object()->is_deprecated(); }
     124             : 
     125       19620 :   void Install(const MaybeObjectHandle& code) override {
     126             :     SLOW_DCHECK(IsValid());
     127       58860 :     DependentCode::InstallDependency(map_.isolate(), code, map_.object(),
     128       19620 :                                      DependentCode::kTransitionGroup);
     129       19620 :   }
     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        7575 :       : site_(site), allocation_(allocation) {
     143             :     DCHECK_EQ(allocation, site_.GetAllocationType());
     144             :   }
     145             : 
     146       14886 :   bool IsValid() const override {
     147       29772 :     return allocation_ == site_.object()->GetAllocationType();
     148             :   }
     149             : 
     150        7434 :   void Install(const MaybeObjectHandle& code) override {
     151             :     SLOW_DCHECK(IsValid());
     152       22302 :     DependentCode::InstallDependency(
     153             :         site_.isolate(), code, site_.object(),
     154        7434 :         DependentCode::kAllocationSiteTenuringChangedGroup);
     155        7434 :   }
     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      112037 :         representation_(representation) {
     176             :     DCHECK(owner_.equals(owner_.FindFieldOwner(descriptor_)));
     177             :     DCHECK(representation_.Equals(
     178             :         owner_.GetPropertyDetails(descriptor_).representation()));
     179             :   }
     180             : 
     181      222306 :   bool IsValid() const override {
     182             :     DisallowHeapAllocation no_heap_allocation;
     183      222306 :     Handle<Map> owner = owner_.object();
     184      444612 :     return representation_.Equals(owner->instance_descriptors()
     185      666918 :                                       ->GetDetails(descriptor_)
     186      222306 :                                       .representation());
     187             :   }
     188             : 
     189      111140 :   void Install(const MaybeObjectHandle& code) override {
     190             :     SLOW_DCHECK(IsValid());
     191      333420 :     DependentCode::InstallDependency(owner_.isolate(), code, owner_.object(),
     192      111140 :                                      DependentCode::kFieldOwnerGroup);
     193      111140 :   }
     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        4094 :       : owner_(owner), descriptor_(descriptor), type_(type) {
     208             :     DCHECK(owner_.equals(owner_.FindFieldOwner(descriptor_)));
     209             :     DCHECK(type_.equals(owner_.GetFieldType(descriptor_)));
     210             :   }
     211             : 
     212        7998 :   bool IsValid() const override {
     213             :     DisallowHeapAllocation no_heap_allocation;
     214        7998 :     Handle<Map> owner = owner_.object();
     215        7998 :     Handle<Object> type = type_.object();
     216       23994 :     return *type == owner->instance_descriptors()->GetFieldType(descriptor_);
     217             :   }
     218             : 
     219        3999 :   void Install(const MaybeObjectHandle& code) override {
     220             :     SLOW_DCHECK(IsValid());
     221       11997 :     DependentCode::InstallDependency(owner_.isolate(), code, owner_.object(),
     222        3999 :                                      DependentCode::kFieldOwnerGroup);
     223        3999 :   }
     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       71285 :       : owner_(owner), descriptor_(descriptor) {
     236             :     DCHECK(owner_.equals(owner_.FindFieldOwner(descriptor_)));
     237             :     DCHECK_EQ(PropertyConstness::kConst,
     238             :               owner_.GetPropertyDetails(descriptor_).constness());
     239             :   }
     240             : 
     241      141920 :   bool IsValid() const override {
     242             :     DisallowHeapAllocation no_heap_allocation;
     243      141920 :     Handle<Map> owner = owner_.object();
     244             :     return PropertyConstness::kConst ==
     245      425760 :            owner->instance_descriptors()->GetDetails(descriptor_).constness();
     246             :   }
     247             : 
     248       70951 :   void Install(const MaybeObjectHandle& code) override {
     249             :     SLOW_DCHECK(IsValid());
     250      212853 :     DependentCode::InstallDependency(owner_.isolate(), code, owner_.object(),
     251       70951 :                                      DependentCode::kFieldOwnerGroup);
     252       70951 :   }
     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      185718 :       : 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      369020 :   bool IsValid() const override {
     272      369020 :     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      738040 :     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     1107028 :     return type_ == cell->property_details().cell_type() &&
     283      369004 :            read_only_ == cell->property_details().IsReadOnly();
     284             :   }
     285             : 
     286      184386 :   void Install(const MaybeObjectHandle& code) override {
     287             :     SLOW_DCHECK(IsValid());
     288      553158 :     DependentCode::InstallDependency(cell_.isolate(), code, cell_.object(),
     289      184386 :                                      DependentCode::kPropertyCellChangedGroup);
     290      184386 :   }
     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       20066 :   explicit ProtectorDependency(const PropertyCellRef& cell) : cell_(cell) {
     301             :     DCHECK_EQ(cell_.value().AsSmi(), Isolate::kProtectorValid);
     302             :   }
     303             : 
     304       39668 :   bool IsValid() const override {
     305       39668 :     Handle<PropertyCell> cell = cell_.object();
     306       39668 :     return cell->value() == Smi::FromInt(Isolate::kProtectorValid);
     307             :   }
     308             : 
     309       19832 :   void Install(const MaybeObjectHandle& code) override {
     310             :     SLOW_DCHECK(IsValid());
     311       59496 :     DependentCode::InstallDependency(cell_.isolate(), code, cell_.object(),
     312       19832 :                                      DependentCode::kPropertyCellChangedGroup);
     313       19832 :   }
     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        2977 :       : 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        5861 :   bool IsValid() const override {
     333        5861 :     Handle<AllocationSite> site = site_.object();
     334             :     ElementsKind kind = site->PointsToLiteral()
     335             :                             ? site->boilerplate()->GetElementsKind()
     336        5861 :                             : site->GetElementsKind();
     337        5861 :     return kind_ == kind;
     338             :   }
     339             : 
     340        2921 :   void Install(const MaybeObjectHandle& code) override {
     341             :     SLOW_DCHECK(IsValid());
     342        8763 :     DependentCode::InstallDependency(
     343             :         site_.isolate(), code, site_.object(),
     344        2921 :         DependentCode::kAllocationSiteTransitionChangedGroup);
     345        2921 :   }
     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        5415 :       : function_(function), instance_size_(instance_size) {}
     358             : 
     359       10775 :   bool IsValid() const override {
     360             :     // The dependency is valid if the prediction is the same as the current
     361             :     // slack tracking result.
     362       21550 :     if (!function_.object()->has_initial_map()) return false;
     363       32310 :     int instance_size = function_.object()->ComputeInstanceSizeWithMinSlack(
     364       10770 :         function_.isolate());
     365       10770 :     return instance_size == instance_size_;
     366             :   }
     367             : 
     368        5386 :   void PrepareInstall() override {
     369             :     SLOW_DCHECK(IsValid());
     370       10772 :     function_.object()->CompleteInobjectSlackTrackingIfActive();
     371        5386 :   }
     372             : 
     373        5384 :   void Install(const MaybeObjectHandle& code) override {
     374             :     SLOW_DCHECK(IsValid());
     375             :     DCHECK(!function_.object()
     376             :                 ->initial_map()
     377             :                 ->IsInobjectSlackTrackingInProgress());
     378        5384 :   }
     379             : 
     380             :  private:
     381             :   JSFunctionRef function_;
     382             :   int instance_size_;
     383             : };
     384             : 
     385        5415 : MapRef CompilationDependencies::DependOnInitialMap(
     386             :     const JSFunctionRef& function) {
     387        5415 :   MapRef map = function.initial_map();
     388       16245 :   dependencies_.push_front(new (zone_) InitialMapDependency(function, map));
     389        5415 :   return map;
     390             : }
     391             : 
     392        1364 : ObjectRef CompilationDependencies::DependOnPrototypeProperty(
     393             :     const JSFunctionRef& function) {
     394        1364 :   ObjectRef prototype = function.prototype();
     395        2728 :   dependencies_.push_front(
     396        1364 :       new (zone_) PrototypePropertyDependency(function, prototype));
     397        1364 :   return prototype;
     398             : }
     399             : 
     400      165422 : void CompilationDependencies::DependOnStableMap(const MapRef& map) {
     401      165422 :   if (map.CanTransition()) {
     402      490803 :     dependencies_.push_front(new (zone_) StableMapDependency(map));
     403             :   } else {
     404             :     DCHECK(map.is_stable());
     405             :   }
     406      165422 : }
     407             : 
     408       22031 : void CompilationDependencies::DependOnTransition(const MapRef& target_map) {
     409       22031 :   if (target_map.CanBeDeprecated()) {
     410       58944 :     dependencies_.push_front(new (zone_) TransitionDependency(target_map));
     411             :   } else {
     412             :     DCHECK(!target_map.is_deprecated());
     413             :   }
     414       22031 : }
     415             : 
     416        7575 : AllocationType CompilationDependencies::DependOnPretenureMode(
     417             :     const AllocationSiteRef& site) {
     418        7575 :   AllocationType allocation = site.GetAllocationType();
     419       22725 :   dependencies_.push_front(new (zone_)
     420             :                                PretenureModeDependency(site, allocation));
     421        7575 :   return allocation;
     422             : }
     423             : 
     424       71285 : PropertyConstness CompilationDependencies::DependOnFieldConstness(
     425             :     const MapRef& map, int descriptor) {
     426       71285 :   MapRef owner = map.FindFieldOwner(descriptor);
     427             :   PropertyConstness constness =
     428      142570 :       owner.GetPropertyDetails(descriptor).constness();
     429       71285 :   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      142570 :   if (Map::CanHaveFastTransitionableElementsKind(map.instance_type())) {
     434             :     // If the map can already transition away, let us report the field as
     435             :     // mutable.
     436       13726 :     if (!map.is_stable()) {
     437             :       return PropertyConstness::kMutable;
     438             :     }
     439       13726 :     DependOnStableMap(map);
     440             :   }
     441             : 
     442             :   DCHECK_EQ(constness, PropertyConstness::kConst);
     443      213855 :   dependencies_.push_front(new (zone_)
     444             :                                FieldConstnessDependency(owner, descriptor));
     445       71285 :   return PropertyConstness::kConst;
     446             : }
     447             : 
     448      112037 : void CompilationDependencies::DependOnFieldRepresentation(const MapRef& map,
     449             :                                                           int descriptor) {
     450      112037 :   MapRef owner = map.FindFieldOwner(descriptor);
     451      112037 :   PropertyDetails details = owner.GetPropertyDetails(descriptor);
     452             :   DCHECK(details.representation().Equals(
     453             :       map.GetPropertyDetails(descriptor).representation()));
     454      336111 :   dependencies_.push_front(new (zone_) FieldRepresentationDependency(
     455             :       owner, descriptor, details.representation()));
     456      112037 : }
     457             : 
     458        4094 : void CompilationDependencies::DependOnFieldType(const MapRef& map,
     459             :                                                 int descriptor) {
     460        4094 :   MapRef owner = map.FindFieldOwner(descriptor);
     461        4094 :   ObjectRef type = owner.GetFieldType(descriptor);
     462             :   DCHECK(type.equals(map.GetFieldType(descriptor)));
     463       12282 :   dependencies_.push_front(new (zone_)
     464             :                                FieldTypeDependency(owner, descriptor, type));
     465        4094 : }
     466             : 
     467      185718 : void CompilationDependencies::DependOnGlobalProperty(
     468             :     const PropertyCellRef& cell) {
     469      371436 :   PropertyCellType type = cell.property_details().cell_type();
     470      371436 :   bool read_only = cell.property_details().IsReadOnly();
     471      557154 :   dependencies_.push_front(new (zone_)
     472             :                                GlobalPropertyDependency(cell, type, read_only));
     473      185718 : }
     474             : 
     475       20947 : bool CompilationDependencies::DependOnProtector(const PropertyCellRef& cell) {
     476       20947 :   if (cell.value().AsSmi() != Isolate::kProtectorValid) return false;
     477       60198 :   dependencies_.push_front(new (zone_) ProtectorDependency(cell));
     478       20066 :   return true;
     479             : }
     480             : 
     481        8212 : bool CompilationDependencies::DependOnArrayBufferDetachingProtector() {
     482        8212 :   return DependOnProtector(PropertyCellRef(
     483             :       broker_,
     484       24636 :       broker_->isolate()->factory()->array_buffer_detaching_protector()));
     485             : }
     486             : 
     487         966 : bool CompilationDependencies::DependOnArrayIteratorProtector() {
     488         966 :   return DependOnProtector(PropertyCellRef(
     489        2898 :       broker_, broker_->isolate()->factory()->array_iterator_protector()));
     490             : }
     491             : 
     492         807 : bool CompilationDependencies::DependOnArraySpeciesProtector() {
     493         807 :   return DependOnProtector(PropertyCellRef(
     494        2421 :       broker_, broker_->isolate()->factory()->array_species_protector()));
     495             : }
     496             : 
     497        6567 : bool CompilationDependencies::DependOnNoElementsProtector() {
     498        6567 :   return DependOnProtector(PropertyCellRef(
     499       19701 :       broker_, broker_->isolate()->factory()->no_elements_protector()));
     500             : }
     501             : 
     502        4021 : bool CompilationDependencies::DependOnPromiseHookProtector() {
     503        4021 :   return DependOnProtector(PropertyCellRef(
     504       12063 :       broker_, broker_->isolate()->factory()->promise_hook_protector()));
     505             : }
     506             : 
     507         230 : bool CompilationDependencies::DependOnPromiseSpeciesProtector() {
     508         230 :   return DependOnProtector(PropertyCellRef(
     509         690 :       broker_, broker_->isolate()->factory()->promise_species_protector()));
     510             : }
     511             : 
     512         110 : bool CompilationDependencies::DependOnPromiseThenProtector() {
     513         110 :   return DependOnProtector(PropertyCellRef(
     514         330 :       broker_, broker_->isolate()->factory()->promise_then_protector()));
     515             : }
     516             : 
     517        7807 : void CompilationDependencies::DependOnElementsKind(
     518             :     const AllocationSiteRef& site) {
     519             :   // Do nothing if the object doesn't have any useful element transitions left.
     520        7807 :   ElementsKind kind = site.PointsToLiteral()
     521       20399 :                           ? site.boilerplate().value().GetElementsKind()
     522       15614 :                           : site.GetElementsKind();
     523        7807 :   if (AllocationSite::ShouldTrack(kind)) {
     524        8931 :     dependencies_.push_front(new (zone_) ElementsKindDependency(site, kind));
     525             :   }
     526        7807 : }
     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      463997 : bool CompilationDependencies::Commit(Handle<Code> code) {
     536     1059411 :   for (auto dep : dependencies_) {
     537      595466 :     if (!dep->IsValid()) {
     538             :       dependencies_.clear();
     539             :       return false;
     540             :     }
     541      595414 :     dep->PrepareInstall();
     542             :   }
     543             : 
     544             :   DisallowCodeDependencyChange no_dependency_change;
     545     1058994 :   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      595063 :     if (!dep->IsValid()) {
     552             :       dependencies_.clear();
     553             :       return false;
     554             :     }
     555      595049 :     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      463931 :   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      463931 :   return true;
     576             : }
     577             : 
     578             : namespace {
     579             : // This function expects to never see a JSProxy.
     580       55357 : void DependOnStablePrototypeChain(CompilationDependencies* deps, MapRef map,
     581             :                                   base::Optional<JSObjectRef> last_prototype) {
     582       30249 :   while (true) {
     583       85606 :     map.SerializePrototype();
     584       85606 :     HeapObjectRef proto = map.prototype();
     585       85606 :     if (!proto.IsJSObject()) {
     586          50 :       CHECK_EQ(proto.map().oddball_type(), OddballType::kNull);
     587       55357 :       break;
     588             :     }
     589       85556 :     map = proto.map();
     590       85556 :     deps->DependOnStableMap(map);
     591       85556 :     if (last_prototype.has_value() && proto.equals(*last_prototype)) break;
     592             :   }
     593       55357 : }
     594             : }  // namespace
     595             : 
     596             : template <class MapContainer>
     597       53087 : 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      108444 :   for (auto map : receiver_maps) {
     602       55357 :     MapRef receiver_map(broker_, map);
     603       55357 :     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        8130 :           broker_->native_context().GetConstructorFunction(receiver_map);
     608        8130 :       if (constructor.has_value()) receiver_map = constructor->initial_map();
     609             :     }
     610       55357 :     if (start == kStartAtReceiver) DependOnStableMap(receiver_map);
     611       55357 :     DependOnStablePrototypeChain(this, receiver_map, last_prototype);
     612             :   }
     613       53087 : }
     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        6064 : void CompilationDependencies::DependOnElementsKinds(
     622             :     const AllocationSiteRef& site) {
     623        6064 :   AllocationSiteRef current = site;
     624         232 :   while (true) {
     625        6296 :     DependOnElementsKind(current);
     626        6296 :     if (!current.nested_site().IsAllocationSite()) break;
     627         232 :     current = current.nested_site().AsAllocationSite();
     628             :   }
     629        6064 :   CHECK_EQ(current.nested_site().AsSmi(), 0);
     630        6064 : }
     631             : 
     632         980 : SlackTrackingPrediction::SlackTrackingPrediction(MapRef initial_map,
     633             :                                                  int instance_size)
     634             :     : instance_size_(instance_size),
     635             :       inobject_property_count_(
     636       12790 :           (instance_size >> kTaggedSizeLog2) -
     637        8355 :           initial_map.GetInObjectPropertiesStartInWords()) {}
     638             : 
     639             : SlackTrackingPrediction
     640        5415 : CompilationDependencies::DependOnInitialMapInstanceSizePrediction(
     641             :     const JSFunctionRef& function) {
     642        5415 :   MapRef initial_map = DependOnInitialMap(function);
     643        5415 :   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       10830 :   dependencies_.push_front(
     648        5415 :       new (zone_)
     649             :           InitialMapInstanceSizePredictionDependency(function, instance_size));
     650             :   DCHECK_LE(instance_size, function.initial_map().instance_size());
     651        5415 :   return SlackTrackingPrediction(initial_map, instance_size);
     652             : }
     653             : 
     654             : }  // namespace compiler
     655             : }  // namespace internal
     656      122004 : }  // namespace v8

Generated by: LCOV version 1.10