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/base/optional.h"
8#include "src/execution/protectors.h"
9#include "src/handles/handles-inl.h"
10#include "src/objects/allocation-site-inl.h"
11#include "src/objects/internal-index.h"
12#include "src/objects/js-array-inl.h"
13#include "src/objects/js-function-inl.h"
14#include "src/objects/objects-inl.h"
15#include "src/zone/zone-handle-set.h"
16
17namespace v8 {
18namespace internal {
19namespace compiler {
20
21#define DEPENDENCY_LIST(V)              \
22  V(ConsistentJSFunctionView)           \
23  V(ConstantInDictionaryPrototypeChain) \
24  V(ElementsKind)                       \
25  V(FieldConstness)                     \
26  V(FieldRepresentation)                \
27  V(FieldType)                          \
28  V(GlobalProperty)                     \
29  V(InitialMap)                         \
30  V(InitialMapInstanceSizePrediction)   \
31  V(OwnConstantDataProperty)            \
32  V(OwnConstantDictionaryProperty)      \
33  V(OwnConstantElement)                 \
34  V(PretenureMode)                      \
35  V(Protector)                          \
36  V(PrototypeProperty)                  \
37  V(StableMap)                          \
38  V(Transition)                         \
39  V(ObjectSlotValue)
40
41CompilationDependencies::CompilationDependencies(JSHeapBroker* broker,
42                                                 Zone* zone)
43    : zone_(zone), broker_(broker), dependencies_(zone) {
44  broker->set_dependencies(this);
45}
46
47namespace {
48
49enum CompilationDependencyKind {
50#define V(Name) k##Name,
51  DEPENDENCY_LIST(V)
52#undef V
53};
54
55#define V(Name) class Name##Dependency;
56DEPENDENCY_LIST(V)
57#undef V
58
59const char* CompilationDependencyKindToString(CompilationDependencyKind kind) {
60#define V(Name) #Name "Dependency",
61  static const char* const names[] = {DEPENDENCY_LIST(V)};
62#undef V
63  return names[kind];
64}
65
66class PendingDependencies;
67
68}  // namespace
69
70class CompilationDependency : public ZoneObject {
71 public:
72  explicit CompilationDependency(CompilationDependencyKind kind) : kind(kind) {}
73
74  virtual bool IsValid() const = 0;
75  virtual void PrepareInstall() const {}
76  virtual void Install(PendingDependencies* deps) const = 0;
77
78#define V(Name)                                     \
79  bool Is##Name() const { return kind == k##Name; } \
80  V8_ALLOW_UNUSED const Name##Dependency* As##Name() const;
81  DEPENDENCY_LIST(V)
82#undef V
83
84  const char* ToString() const {
85    return CompilationDependencyKindToString(kind);
86  }
87
88  const CompilationDependencyKind kind;
89
90 private:
91  virtual size_t Hash() const = 0;
92  virtual bool Equals(const CompilationDependency* that) const = 0;
93  friend struct CompilationDependencies::CompilationDependencyHash;
94  friend struct CompilationDependencies::CompilationDependencyEqual;
95};
96
97size_t CompilationDependencies::CompilationDependencyHash::operator()(
98    const CompilationDependency* dep) const {
99  return base::hash_combine(dep->kind, dep->Hash());
100}
101
102bool CompilationDependencies::CompilationDependencyEqual::operator()(
103    const CompilationDependency* lhs, const CompilationDependency* rhs) const {
104  return lhs->kind == rhs->kind && lhs->Equals(rhs);
105}
106
107namespace {
108
109// Dependencies can only be fully deduplicated immediately prior to
110// installation (because PrepareInstall may create the object on which the dep
111// will be installed). We gather and dedupe deps in this class, and install
112// them from here.
113class PendingDependencies final {
114 public:
115  explicit PendingDependencies(Zone* zone) : deps_(zone) {}
116
117  void Register(Handle<HeapObject> object,
118                DependentCode::DependencyGroup group) {
119    deps_[object] |= group;
120  }
121
122  void InstallAll(Isolate* isolate, Handle<Code> code) {
123    if (V8_UNLIKELY(FLAG_predictable)) {
124      InstallAllPredictable(isolate, code);
125      return;
126    }
127
128    // With deduplication done we no longer rely on the object address for
129    // hashing.
130    AllowGarbageCollection yes_gc;
131    for (const auto& o_and_g : deps_) {
132      DependentCode::InstallDependency(isolate, code, o_and_g.first,
133                                       o_and_g.second);
134    }
135  }
136
137  void InstallAllPredictable(Isolate* isolate, Handle<Code> code) {
138    CHECK(FLAG_predictable);
139    // First, guarantee predictable iteration order.
140    using HandleAndGroup =
141        std::pair<Handle<HeapObject>, DependentCode::DependencyGroups>;
142    std::vector<HandleAndGroup> entries(deps_.begin(), deps_.end());
143
144    std::sort(entries.begin(), entries.end(),
145              [](const HandleAndGroup& lhs, const HandleAndGroup& rhs) {
146                return lhs.first->ptr() < rhs.first->ptr();
147              });
148
149    // With deduplication done we no longer rely on the object address for
150    // hashing.
151    AllowGarbageCollection yes_gc;
152    for (const auto& o_and_g : entries) {
153      DependentCode::InstallDependency(isolate, code, o_and_g.first,
154                                       o_and_g.second);
155    }
156  }
157
158 private:
159  struct HandleHash {
160    size_t operator()(const Handle<HeapObject>& x) const {
161      return static_cast<size_t>(x->ptr());
162    }
163  };
164  struct HandleEqual {
165    bool operator()(const Handle<HeapObject>& lhs,
166                    const Handle<HeapObject>& rhs) const {
167      return lhs.is_identical_to(rhs);
168    }
169  };
170  ZoneUnorderedMap<Handle<HeapObject>, DependentCode::DependencyGroups,
171                   HandleHash, HandleEqual>
172      deps_;
173  const DisallowGarbageCollection no_gc_;
174};
175
176class InitialMapDependency final : public CompilationDependency {
177 public:
178  InitialMapDependency(JSHeapBroker* broker, const JSFunctionRef& function,
179                       const MapRef& initial_map)
180      : CompilationDependency(kInitialMap),
181        function_(function),
182        initial_map_(initial_map) {}
183
184  bool IsValid() const override {
185    Handle<JSFunction> function = function_.object();
186    return function->has_initial_map() &&
187           function->initial_map() == *initial_map_.object();
188  }
189
190  void Install(PendingDependencies* deps) const override {
191    SLOW_DCHECK(IsValid());
192    deps->Register(initial_map_.object(),
193                   DependentCode::kInitialMapChangedGroup);
194  }
195
196 private:
197  size_t Hash() const override {
198    ObjectRef::Hash h;
199    return base::hash_combine(h(function_), h(initial_map_));
200  }
201
202  bool Equals(const CompilationDependency* that) const override {
203    const InitialMapDependency* const zat = that->AsInitialMap();
204    return function_.equals(zat->function_) &&
205           initial_map_.equals(zat->initial_map_);
206  }
207
208  const JSFunctionRef function_;
209  const MapRef initial_map_;
210};
211
212class PrototypePropertyDependency final : public CompilationDependency {
213 public:
214  PrototypePropertyDependency(JSHeapBroker* broker,
215                              const JSFunctionRef& function,
216                              const ObjectRef& prototype)
217      : CompilationDependency(kPrototypeProperty),
218        function_(function),
219        prototype_(prototype) {
220    DCHECK(function_.has_instance_prototype(broker->dependencies()));
221    DCHECK(!function_.PrototypeRequiresRuntimeLookup(broker->dependencies()));
222    DCHECK(function_.instance_prototype(broker->dependencies())
223               .equals(prototype_));
224  }
225
226  bool IsValid() const override {
227    Handle<JSFunction> function = function_.object();
228    return function->has_prototype_slot() &&
229           function->has_instance_prototype() &&
230           !function->PrototypeRequiresRuntimeLookup() &&
231           function->instance_prototype() == *prototype_.object();
232  }
233
234  void PrepareInstall() const override {
235    SLOW_DCHECK(IsValid());
236    Handle<JSFunction> function = function_.object();
237    if (!function->has_initial_map()) JSFunction::EnsureHasInitialMap(function);
238  }
239
240  void Install(PendingDependencies* deps) const override {
241    SLOW_DCHECK(IsValid());
242    Handle<JSFunction> function = function_.object();
243    CHECK(function->has_initial_map());
244    Handle<Map> initial_map(function->initial_map(), function_.isolate());
245    deps->Register(initial_map, DependentCode::kInitialMapChangedGroup);
246  }
247
248 private:
249  size_t Hash() const override {
250    ObjectRef::Hash h;
251    return base::hash_combine(h(function_), h(prototype_));
252  }
253
254  bool Equals(const CompilationDependency* that) const override {
255    const PrototypePropertyDependency* const zat = that->AsPrototypeProperty();
256    return function_.equals(zat->function_) &&
257           prototype_.equals(zat->prototype_);
258  }
259
260  const JSFunctionRef function_;
261  const ObjectRef prototype_;
262};
263
264class StableMapDependency final : public CompilationDependency {
265 public:
266  explicit StableMapDependency(const MapRef& map)
267      : CompilationDependency(kStableMap), map_(map) {}
268
269  bool IsValid() const override {
270    // TODO(v8:11670): Consider turn this back into a CHECK inside the
271    // constructor and DependOnStableMap, if possible in light of concurrent
272    // heap state modifications.
273    return !map_.object()->is_dictionary_map() && map_.object()->is_stable();
274  }
275  void Install(PendingDependencies* deps) const override {
276    SLOW_DCHECK(IsValid());
277    deps->Register(map_.object(), DependentCode::kPrototypeCheckGroup);
278  }
279
280 private:
281  size_t Hash() const override {
282    ObjectRef::Hash h;
283    return base::hash_combine(h(map_));
284  }
285
286  bool Equals(const CompilationDependency* that) const override {
287    const StableMapDependency* const zat = that->AsStableMap();
288    return map_.equals(zat->map_);
289  }
290
291  const MapRef map_;
292};
293
294class ConstantInDictionaryPrototypeChainDependency final
295    : public CompilationDependency {
296 public:
297  explicit ConstantInDictionaryPrototypeChainDependency(
298      const MapRef receiver_map, const NameRef property_name,
299      const ObjectRef constant, PropertyKind kind)
300      : CompilationDependency(kConstantInDictionaryPrototypeChain),
301        receiver_map_(receiver_map),
302        property_name_{property_name},
303        constant_{constant},
304        kind_{kind} {
305    DCHECK(V8_DICT_PROPERTY_CONST_TRACKING_BOOL);
306  }
307
308  // Checks that |constant_| is still the value of accessing |property_name_|
309  // starting at |receiver_map_|.
310  bool IsValid() const override { return !GetHolderIfValid().is_null(); }
311
312  void Install(PendingDependencies* deps) const override {
313    SLOW_DCHECK(IsValid());
314    Isolate* isolate = receiver_map_.isolate();
315    Handle<JSObject> holder = GetHolderIfValid().ToHandleChecked();
316    Handle<Map> map = receiver_map_.object();
317
318    while (map->prototype() != *holder) {
319      map = handle(map->prototype().map(), isolate);
320      DCHECK(map->IsJSObjectMap());  // Due to IsValid holding.
321      deps->Register(map, DependentCode::kPrototypeCheckGroup);
322    }
323
324    DCHECK(map->prototype().map().IsJSObjectMap());  // Due to IsValid holding.
325    deps->Register(handle(map->prototype().map(), isolate),
326                   DependentCode::kPrototypeCheckGroup);
327  }
328
329 private:
330  // If the dependency is still valid, returns holder of the constant. Otherwise
331  // returns null.
332  // TODO(neis) Currently, invoking IsValid and then Install duplicates the call
333  // to GetHolderIfValid. Instead, consider letting IsValid change the state
334  // (and store the holder), or merge IsValid and Install.
335  MaybeHandle<JSObject> GetHolderIfValid() const {
336    DisallowGarbageCollection no_gc;
337    Isolate* isolate = receiver_map_.isolate();
338
339    Handle<Object> holder;
340    HeapObject prototype = receiver_map_.object()->prototype();
341
342    enum class ValidationResult { kFoundCorrect, kFoundIncorrect, kNotFound };
343    auto try_load = [&](auto dictionary) -> ValidationResult {
344      InternalIndex entry =
345          dictionary.FindEntry(isolate, property_name_.object());
346      if (entry.is_not_found()) {
347        return ValidationResult::kNotFound;
348      }
349
350      PropertyDetails details = dictionary.DetailsAt(entry);
351      if (details.constness() != PropertyConstness::kConst) {
352        return ValidationResult::kFoundIncorrect;
353      }
354
355      Object dictionary_value = dictionary.ValueAt(entry);
356      Object value;
357      // We must be able to detect the case that the property |property_name_|
358      // of |holder_| was originally a plain function |constant_| (when creating
359      // this dependency) and has since become an accessor whose getter is
360      // |constant_|. Therefore, we cannot just look at the property kind of
361      // |details|, because that reflects the current situation, not the one
362      // when creating this dependency.
363      if (details.kind() != kind_) {
364        return ValidationResult::kFoundIncorrect;
365      }
366      if (kind_ == PropertyKind::kAccessor) {
367        if (!dictionary_value.IsAccessorPair()) {
368          return ValidationResult::kFoundIncorrect;
369        }
370        // Only supporting loading at the moment, so we only ever want the
371        // getter.
372        value = AccessorPair::cast(dictionary_value)
373                    .get(AccessorComponent::ACCESSOR_GETTER);
374      } else {
375        value = dictionary_value;
376      }
377      return value == *constant_.object() ? ValidationResult::kFoundCorrect
378                                          : ValidationResult::kFoundIncorrect;
379    };
380
381    while (prototype.IsJSObject()) {
382      // We only care about JSObjects because that's the only type of holder
383      // (and types of prototypes on the chain to the holder) that
384      // AccessInfoFactory::ComputePropertyAccessInfo allows.
385      JSObject object = JSObject::cast(prototype);
386
387      // We only support dictionary mode prototypes on the chain for this kind
388      // of dependency.
389      CHECK(!object.HasFastProperties());
390
391      ValidationResult result =
392          V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL
393              ? try_load(object.property_dictionary_swiss())
394              : try_load(object.property_dictionary());
395
396      if (result == ValidationResult::kFoundCorrect) {
397        return handle(object, isolate);
398      } else if (result == ValidationResult::kFoundIncorrect) {
399        return MaybeHandle<JSObject>();
400      }
401
402      // In case of kNotFound, continue walking up the chain.
403      prototype = object.map().prototype();
404    }
405
406    return MaybeHandle<JSObject>();
407  }
408
409  size_t Hash() const override {
410    ObjectRef::Hash h;
411    return base::hash_combine(h(receiver_map_), h(property_name_), h(constant_),
412                              static_cast<int>(kind_));
413  }
414
415  bool Equals(const CompilationDependency* that) const override {
416    const ConstantInDictionaryPrototypeChainDependency* const zat =
417        that->AsConstantInDictionaryPrototypeChain();
418    return receiver_map_.equals(zat->receiver_map_) &&
419           property_name_.equals(zat->property_name_) &&
420           constant_.equals(zat->constant_) && kind_ == zat->kind_;
421  }
422
423  const MapRef receiver_map_;
424  const NameRef property_name_;
425  const ObjectRef constant_;
426  const PropertyKind kind_;
427};
428
429class OwnConstantDataPropertyDependency final : public CompilationDependency {
430 public:
431  OwnConstantDataPropertyDependency(JSHeapBroker* broker,
432                                    const JSObjectRef& holder,
433                                    const MapRef& map,
434                                    Representation representation,
435                                    FieldIndex index, const ObjectRef& value)
436      : CompilationDependency(kOwnConstantDataProperty),
437        broker_(broker),
438        holder_(holder),
439        map_(map),
440        representation_(representation),
441        index_(index),
442        value_(value) {}
443
444  bool IsValid() const override {
445    if (holder_.object()->map() != *map_.object()) {
446      TRACE_BROKER_MISSING(broker_,
447                           "Map change detected in " << holder_.object());
448      return false;
449    }
450    DisallowGarbageCollection no_heap_allocation;
451    Object current_value = holder_.object()->RawFastPropertyAt(index_);
452    Object used_value = *value_.object();
453    if (representation_.IsDouble()) {
454      // Compare doubles by bit pattern.
455      if (!current_value.IsHeapNumber() || !used_value.IsHeapNumber() ||
456          HeapNumber::cast(current_value).value_as_bits(kRelaxedLoad) !=
457              HeapNumber::cast(used_value).value_as_bits(kRelaxedLoad)) {
458        TRACE_BROKER_MISSING(broker_,
459                             "Constant Double property value changed in "
460                                 << holder_.object() << " at FieldIndex "
461                                 << index_.property_index());
462        return false;
463      }
464    } else if (current_value != used_value) {
465      TRACE_BROKER_MISSING(broker_, "Constant property value changed in "
466                                        << holder_.object() << " at FieldIndex "
467                                        << index_.property_index());
468      return false;
469    }
470    return true;
471  }
472
473  void Install(PendingDependencies* deps) const override {}
474
475 private:
476  size_t Hash() const override {
477    ObjectRef::Hash h;
478    return base::hash_combine(h(holder_), h(map_), representation_.kind(),
479                              index_.bit_field(), h(value_));
480  }
481
482  bool Equals(const CompilationDependency* that) const override {
483    const OwnConstantDataPropertyDependency* const zat =
484        that->AsOwnConstantDataProperty();
485    return holder_.equals(zat->holder_) && map_.equals(zat->map_) &&
486           representation_.Equals(zat->representation_) &&
487           index_ == zat->index_ && value_.equals(zat->value_);
488  }
489
490  JSHeapBroker* const broker_;
491  JSObjectRef const holder_;
492  MapRef const map_;
493  Representation const representation_;
494  FieldIndex const index_;
495  ObjectRef const value_;
496};
497
498class OwnConstantDictionaryPropertyDependency final
499    : public CompilationDependency {
500 public:
501  OwnConstantDictionaryPropertyDependency(JSHeapBroker* broker,
502                                          const JSObjectRef& holder,
503                                          InternalIndex index,
504                                          const ObjectRef& value)
505      : CompilationDependency(kOwnConstantDictionaryProperty),
506        broker_(broker),
507        holder_(holder),
508        map_(holder.map()),
509        index_(index),
510        value_(value) {
511    // We depend on map() being cached.
512    STATIC_ASSERT(ref_traits<JSObject>::ref_serialization_kind !=
513                  RefSerializationKind::kNeverSerialized);
514  }
515
516  bool IsValid() const override {
517    if (holder_.object()->map() != *map_.object()) {
518      TRACE_BROKER_MISSING(broker_,
519                           "Map change detected in " << holder_.object());
520      return false;
521    }
522
523    base::Optional<Object> maybe_value = JSObject::DictionaryPropertyAt(
524        holder_.object(), index_, broker_->isolate()->heap());
525
526    if (!maybe_value) {
527      TRACE_BROKER_MISSING(
528          broker_, holder_.object()
529                       << "has a value that might not safe to read at index "
530                       << index_.as_int());
531      return false;
532    }
533
534    if (*maybe_value != *value_.object()) {
535      TRACE_BROKER_MISSING(broker_, "Constant property value changed in "
536                                        << holder_.object()
537                                        << " at InternalIndex "
538                                        << index_.as_int());
539      return false;
540    }
541    return true;
542  }
543
544  void Install(PendingDependencies* deps) const override {}
545
546 private:
547  size_t Hash() const override {
548    ObjectRef::Hash h;
549    return base::hash_combine(h(holder_), h(map_), index_.raw_value(),
550                              h(value_));
551  }
552
553  bool Equals(const CompilationDependency* that) const override {
554    const OwnConstantDictionaryPropertyDependency* const zat =
555        that->AsOwnConstantDictionaryProperty();
556    return holder_.equals(zat->holder_) && map_.equals(zat->map_) &&
557           index_ == zat->index_ && value_.equals(zat->value_);
558  }
559
560  JSHeapBroker* const broker_;
561  JSObjectRef const holder_;
562  MapRef const map_;
563  InternalIndex const index_;
564  ObjectRef const value_;
565};
566
567class ConsistentJSFunctionViewDependency final : public CompilationDependency {
568 public:
569  explicit ConsistentJSFunctionViewDependency(const JSFunctionRef& function)
570      : CompilationDependency(kConsistentJSFunctionView), function_(function) {}
571
572  bool IsValid() const override {
573    return function_.IsConsistentWithHeapState();
574  }
575
576  void Install(PendingDependencies* deps) const override {}
577
578 private:
579  size_t Hash() const override {
580    ObjectRef::Hash h;
581    return base::hash_combine(h(function_));
582  }
583
584  bool Equals(const CompilationDependency* that) const override {
585    const ConsistentJSFunctionViewDependency* const zat =
586        that->AsConsistentJSFunctionView();
587    return function_.equals(zat->function_);
588  }
589
590  const JSFunctionRef function_;
591};
592
593class TransitionDependency final : public CompilationDependency {
594 public:
595  explicit TransitionDependency(const MapRef& map)
596      : CompilationDependency(kTransition), map_(map) {
597    DCHECK(map_.CanBeDeprecated());
598  }
599
600  bool IsValid() const override { return !map_.object()->is_deprecated(); }
601
602  void Install(PendingDependencies* deps) const override {
603    SLOW_DCHECK(IsValid());
604    deps->Register(map_.object(), DependentCode::kTransitionGroup);
605  }
606
607 private:
608  size_t Hash() const override {
609    ObjectRef::Hash h;
610    return base::hash_combine(h(map_));
611  }
612
613  bool Equals(const CompilationDependency* that) const override {
614    const TransitionDependency* const zat = that->AsTransition();
615    return map_.equals(zat->map_);
616  }
617
618  const MapRef map_;
619};
620
621class PretenureModeDependency final : public CompilationDependency {
622 public:
623  PretenureModeDependency(const AllocationSiteRef& site,
624                          AllocationType allocation)
625      : CompilationDependency(kPretenureMode),
626        site_(site),
627        allocation_(allocation) {}
628
629  bool IsValid() const override {
630    return allocation_ == site_.object()->GetAllocationType();
631  }
632  void Install(PendingDependencies* deps) const override {
633    SLOW_DCHECK(IsValid());
634    deps->Register(site_.object(),
635                   DependentCode::kAllocationSiteTenuringChangedGroup);
636  }
637
638 private:
639  size_t Hash() const override {
640    ObjectRef::Hash h;
641    return base::hash_combine(h(site_), allocation_);
642  }
643
644  bool Equals(const CompilationDependency* that) const override {
645    const PretenureModeDependency* const zat = that->AsPretenureMode();
646    return site_.equals(zat->site_) && allocation_ == zat->allocation_;
647  }
648
649  const AllocationSiteRef site_;
650  const AllocationType allocation_;
651};
652
653class FieldRepresentationDependency final : public CompilationDependency {
654 public:
655  FieldRepresentationDependency(const MapRef& map, InternalIndex descriptor,
656                                Representation representation)
657      : CompilationDependency(kFieldRepresentation),
658        map_(map),
659        descriptor_(descriptor),
660        representation_(representation) {}
661
662  bool IsValid() const override {
663    DisallowGarbageCollection no_heap_allocation;
664    if (map_.object()->is_deprecated()) return false;
665    return representation_.Equals(map_.object()
666                                      ->instance_descriptors(map_.isolate())
667                                      .GetDetails(descriptor_)
668                                      .representation());
669  }
670
671  void Install(PendingDependencies* deps) const override {
672    SLOW_DCHECK(IsValid());
673    Isolate* isolate = map_.isolate();
674    Handle<Map> owner(map_.object()->FindFieldOwner(isolate, descriptor_),
675                      isolate);
676    CHECK(!owner->is_deprecated());
677    CHECK(representation_.Equals(owner->instance_descriptors(isolate)
678                                     .GetDetails(descriptor_)
679                                     .representation()));
680    deps->Register(owner, DependentCode::kFieldRepresentationGroup);
681  }
682
683  bool DependsOn(const Handle<Map>& receiver_map) const {
684    return map_.object().equals(receiver_map);
685  }
686
687 private:
688  size_t Hash() const override {
689    ObjectRef::Hash h;
690    return base::hash_combine(h(map_), descriptor_.as_int(),
691                              representation_.kind());
692  }
693
694  bool Equals(const CompilationDependency* that) const override {
695    const FieldRepresentationDependency* const zat =
696        that->AsFieldRepresentation();
697    return map_.equals(zat->map_) && descriptor_ == zat->descriptor_ &&
698           representation_.Equals(zat->representation_);
699  }
700
701  const MapRef map_;
702  const InternalIndex descriptor_;
703  const Representation representation_;
704};
705
706class FieldTypeDependency final : public CompilationDependency {
707 public:
708  FieldTypeDependency(const MapRef& map, InternalIndex descriptor,
709                      const ObjectRef& type)
710      : CompilationDependency(kFieldType),
711        map_(map),
712        descriptor_(descriptor),
713        type_(type) {}
714
715  bool IsValid() const override {
716    DisallowGarbageCollection no_heap_allocation;
717    if (map_.object()->is_deprecated()) return false;
718    return *type_.object() == map_.object()
719                                  ->instance_descriptors(map_.isolate())
720                                  .GetFieldType(descriptor_);
721  }
722
723  void Install(PendingDependencies* deps) const override {
724    SLOW_DCHECK(IsValid());
725    Isolate* isolate = map_.isolate();
726    Handle<Map> owner(map_.object()->FindFieldOwner(isolate, descriptor_),
727                      isolate);
728    CHECK(!owner->is_deprecated());
729    CHECK_EQ(*type_.object(),
730             owner->instance_descriptors(isolate).GetFieldType(descriptor_));
731    deps->Register(owner, DependentCode::kFieldTypeGroup);
732  }
733
734 private:
735  size_t Hash() const override {
736    ObjectRef::Hash h;
737    return base::hash_combine(h(map_), descriptor_.as_int(), h(type_));
738  }
739
740  bool Equals(const CompilationDependency* that) const override {
741    const FieldTypeDependency* const zat = that->AsFieldType();
742    return map_.equals(zat->map_) && descriptor_ == zat->descriptor_ &&
743           type_.equals(zat->type_);
744  }
745
746  const MapRef map_;
747  const InternalIndex descriptor_;
748  const ObjectRef type_;
749};
750
751class FieldConstnessDependency final : public CompilationDependency {
752 public:
753  FieldConstnessDependency(const MapRef& map, InternalIndex descriptor)
754      : CompilationDependency(kFieldConstness),
755        map_(map),
756        descriptor_(descriptor) {}
757
758  bool IsValid() const override {
759    DisallowGarbageCollection no_heap_allocation;
760    if (map_.object()->is_deprecated()) return false;
761    return PropertyConstness::kConst ==
762           map_.object()
763               ->instance_descriptors(map_.isolate())
764               .GetDetails(descriptor_)
765               .constness();
766  }
767
768  void Install(PendingDependencies* deps) const override {
769    SLOW_DCHECK(IsValid());
770    Isolate* isolate = map_.isolate();
771    Handle<Map> owner(map_.object()->FindFieldOwner(isolate, descriptor_),
772                      isolate);
773    CHECK(!owner->is_deprecated());
774    CHECK_EQ(PropertyConstness::kConst, owner->instance_descriptors(isolate)
775                                            .GetDetails(descriptor_)
776                                            .constness());
777    deps->Register(owner, DependentCode::kFieldConstGroup);
778  }
779
780 private:
781  size_t Hash() const override {
782    ObjectRef::Hash h;
783    return base::hash_combine(h(map_), descriptor_.as_int());
784  }
785
786  bool Equals(const CompilationDependency* that) const override {
787    const FieldConstnessDependency* const zat = that->AsFieldConstness();
788    return map_.equals(zat->map_) && descriptor_ == zat->descriptor_;
789  }
790
791  const MapRef map_;
792  const InternalIndex descriptor_;
793};
794
795class GlobalPropertyDependency final : public CompilationDependency {
796 public:
797  GlobalPropertyDependency(const PropertyCellRef& cell, PropertyCellType type,
798                           bool read_only)
799      : CompilationDependency(kGlobalProperty),
800        cell_(cell),
801        type_(type),
802        read_only_(read_only) {
803    DCHECK_EQ(type_, cell_.property_details().cell_type());
804    DCHECK_EQ(read_only_, cell_.property_details().IsReadOnly());
805  }
806
807  bool IsValid() const override {
808    Handle<PropertyCell> cell = cell_.object();
809    // The dependency is never valid if the cell is 'invalidated'. This is
810    // marked by setting the value to the hole.
811    if (cell->value() == *(cell_.isolate()->factory()->the_hole_value())) {
812      return false;
813    }
814    return type_ == cell->property_details().cell_type() &&
815           read_only_ == cell->property_details().IsReadOnly();
816  }
817  void Install(PendingDependencies* deps) const override {
818    SLOW_DCHECK(IsValid());
819    deps->Register(cell_.object(), DependentCode::kPropertyCellChangedGroup);
820  }
821
822 private:
823  size_t Hash() const override {
824    ObjectRef::Hash h;
825    return base::hash_combine(h(cell_), static_cast<int>(type_), read_only_);
826  }
827
828  bool Equals(const CompilationDependency* that) const override {
829    const GlobalPropertyDependency* const zat = that->AsGlobalProperty();
830    return cell_.equals(zat->cell_) && type_ == zat->type_ &&
831           read_only_ == zat->read_only_;
832  }
833
834  const PropertyCellRef cell_;
835  const PropertyCellType type_;
836  const bool read_only_;
837};
838
839class ProtectorDependency final : public CompilationDependency {
840 public:
841  explicit ProtectorDependency(const PropertyCellRef& cell)
842      : CompilationDependency(kProtector), cell_(cell) {}
843
844  bool IsValid() const override {
845    Handle<PropertyCell> cell = cell_.object();
846    return cell->value() == Smi::FromInt(Protectors::kProtectorValid);
847  }
848  void Install(PendingDependencies* deps) const override {
849    SLOW_DCHECK(IsValid());
850    deps->Register(cell_.object(), DependentCode::kPropertyCellChangedGroup);
851  }
852
853 private:
854  size_t Hash() const override {
855    ObjectRef::Hash h;
856    return base::hash_combine(h(cell_));
857  }
858
859  bool Equals(const CompilationDependency* that) const override {
860    const ProtectorDependency* const zat = that->AsProtector();
861    return cell_.equals(zat->cell_);
862  }
863
864  const PropertyCellRef cell_;
865};
866
867// Check that an object slot will not change during compilation.
868class ObjectSlotValueDependency final : public CompilationDependency {
869 public:
870  explicit ObjectSlotValueDependency(const HeapObjectRef& object, int offset,
871                                     const ObjectRef& value)
872      : CompilationDependency(kObjectSlotValue),
873        object_(object.object()),
874        offset_(offset),
875        value_(value.object()) {}
876
877  bool IsValid() const override {
878    PtrComprCageBase cage_base = GetPtrComprCageBase(*object_);
879    Object current_value =
880        offset_ == HeapObject::kMapOffset
881            ? object_->map()
882            : TaggedField<Object>::Relaxed_Load(cage_base, *object_, offset_);
883    return *value_ == current_value;
884  }
885  void Install(PendingDependencies* deps) const override {}
886
887 private:
888  size_t Hash() const override {
889    return base::hash_combine(object_.address(), offset_, value_.address());
890  }
891
892  bool Equals(const CompilationDependency* that) const override {
893    const ObjectSlotValueDependency* const zat = that->AsObjectSlotValue();
894    return object_->address() == zat->object_->address() &&
895           offset_ == zat->offset_ && value_.address() == zat->value_.address();
896  }
897
898  Handle<HeapObject> object_;
899  int offset_;
900  Handle<Object> value_;
901};
902
903class ElementsKindDependency final : public CompilationDependency {
904 public:
905  ElementsKindDependency(const AllocationSiteRef& site, ElementsKind kind)
906      : CompilationDependency(kElementsKind), site_(site), kind_(kind) {
907    DCHECK(AllocationSite::ShouldTrack(kind_));
908  }
909
910  bool IsValid() const override {
911    Handle<AllocationSite> site = site_.object();
912    ElementsKind kind =
913        site->PointsToLiteral()
914            ? site->boilerplate(kAcquireLoad).map().elements_kind()
915            : site->GetElementsKind();
916    return kind_ == kind;
917  }
918  void Install(PendingDependencies* deps) const override {
919    SLOW_DCHECK(IsValid());
920    deps->Register(site_.object(),
921                   DependentCode::kAllocationSiteTransitionChangedGroup);
922  }
923
924 private:
925  size_t Hash() const override {
926    ObjectRef::Hash h;
927    return base::hash_combine(h(site_), static_cast<int>(kind_));
928  }
929
930  bool Equals(const CompilationDependency* that) const override {
931    const ElementsKindDependency* const zat = that->AsElementsKind();
932    return site_.equals(zat->site_) && kind_ == zat->kind_;
933  }
934
935  const AllocationSiteRef site_;
936  const ElementsKind kind_;
937};
938
939// Only valid if the holder can use direct reads, since validation uses
940// GetOwnConstantElementFromHeap.
941class OwnConstantElementDependency final : public CompilationDependency {
942 public:
943  OwnConstantElementDependency(const JSObjectRef& holder, uint32_t index,
944                               const ObjectRef& element)
945      : CompilationDependency(kOwnConstantElement),
946        holder_(holder),
947        index_(index),
948        element_(element) {}
949
950  bool IsValid() const override {
951    DisallowGarbageCollection no_gc;
952    JSObject holder = *holder_.object();
953    base::Optional<Object> maybe_element =
954        holder_.GetOwnConstantElementFromHeap(holder.elements(),
955                                              holder.GetElementsKind(), index_);
956    if (!maybe_element.has_value()) return false;
957
958    return maybe_element.value() == *element_.object();
959  }
960  void Install(PendingDependencies* deps) const override {}
961
962 private:
963  size_t Hash() const override {
964    ObjectRef::Hash h;
965    return base::hash_combine(h(holder_), index_, h(element_));
966  }
967
968  bool Equals(const CompilationDependency* that) const override {
969    const OwnConstantElementDependency* const zat =
970        that->AsOwnConstantElement();
971    return holder_.equals(zat->holder_) && index_ == zat->index_ &&
972           element_.equals(zat->element_);
973  }
974
975  const JSObjectRef holder_;
976  const uint32_t index_;
977  const ObjectRef element_;
978};
979
980class InitialMapInstanceSizePredictionDependency final
981    : public CompilationDependency {
982 public:
983  InitialMapInstanceSizePredictionDependency(const JSFunctionRef& function,
984                                             int instance_size)
985      : CompilationDependency(kInitialMapInstanceSizePrediction),
986        function_(function),
987        instance_size_(instance_size) {}
988
989  bool IsValid() const override {
990    // The dependency is valid if the prediction is the same as the current
991    // slack tracking result.
992    if (!function_.object()->has_initial_map()) return false;
993    int instance_size = function_.object()->ComputeInstanceSizeWithMinSlack(
994        function_.isolate());
995    return instance_size == instance_size_;
996  }
997
998  void PrepareInstall() const override {
999    SLOW_DCHECK(IsValid());
1000    function_.object()->CompleteInobjectSlackTrackingIfActive();
1001  }
1002
1003  void Install(PendingDependencies* deps) const override {
1004    SLOW_DCHECK(IsValid());
1005    DCHECK(
1006        !function_.object()->initial_map().IsInobjectSlackTrackingInProgress());
1007  }
1008
1009 private:
1010  size_t Hash() const override {
1011    ObjectRef::Hash h;
1012    return base::hash_combine(h(function_), instance_size_);
1013  }
1014
1015  bool Equals(const CompilationDependency* that) const override {
1016    const InitialMapInstanceSizePredictionDependency* const zat =
1017        that->AsInitialMapInstanceSizePrediction();
1018    return function_.equals(zat->function_) &&
1019           instance_size_ == zat->instance_size_;
1020  }
1021
1022  const JSFunctionRef function_;
1023  const int instance_size_;
1024};
1025
1026}  // namespace
1027
1028void CompilationDependencies::RecordDependency(
1029    CompilationDependency const* dependency) {
1030  if (dependency != nullptr) dependencies_.insert(dependency);
1031}
1032
1033MapRef CompilationDependencies::DependOnInitialMap(
1034    const JSFunctionRef& function) {
1035  MapRef map = function.initial_map(this);
1036  RecordDependency(zone_->New<InitialMapDependency>(broker_, function, map));
1037  return map;
1038}
1039
1040ObjectRef CompilationDependencies::DependOnPrototypeProperty(
1041    const JSFunctionRef& function) {
1042  ObjectRef prototype = function.instance_prototype(this);
1043  RecordDependency(
1044      zone_->New<PrototypePropertyDependency>(broker_, function, prototype));
1045  return prototype;
1046}
1047
1048void CompilationDependencies::DependOnStableMap(const MapRef& map) {
1049  if (map.CanTransition()) {
1050    RecordDependency(zone_->New<StableMapDependency>(map));
1051  }
1052}
1053
1054void CompilationDependencies::DependOnConstantInDictionaryPrototypeChain(
1055    const MapRef& receiver_map, const NameRef& property_name,
1056    const ObjectRef& constant, PropertyKind kind) {
1057  RecordDependency(zone_->New<ConstantInDictionaryPrototypeChainDependency>(
1058      receiver_map, property_name, constant, kind));
1059}
1060
1061AllocationType CompilationDependencies::DependOnPretenureMode(
1062    const AllocationSiteRef& site) {
1063  if (!FLAG_allocation_site_pretenuring) return AllocationType::kYoung;
1064  AllocationType allocation = site.GetAllocationType();
1065  RecordDependency(zone_->New<PretenureModeDependency>(site, allocation));
1066  return allocation;
1067}
1068
1069PropertyConstness CompilationDependencies::DependOnFieldConstness(
1070    const MapRef& map, InternalIndex descriptor) {
1071  PropertyConstness constness = map.GetPropertyDetails(descriptor).constness();
1072  if (constness == PropertyConstness::kMutable) return constness;
1073
1074  // If the map can have fast elements transitions, then the field can be only
1075  // considered constant if the map does not transition.
1076  if (Map::CanHaveFastTransitionableElementsKind(map.instance_type())) {
1077    // If the map can already transition away, let us report the field as
1078    // mutable.
1079    if (!map.is_stable()) {
1080      return PropertyConstness::kMutable;
1081    }
1082    DependOnStableMap(map);
1083  }
1084
1085  DCHECK_EQ(constness, PropertyConstness::kConst);
1086  RecordDependency(zone_->New<FieldConstnessDependency>(map, descriptor));
1087  return PropertyConstness::kConst;
1088}
1089
1090void CompilationDependencies::DependOnGlobalProperty(
1091    const PropertyCellRef& cell) {
1092  PropertyCellType type = cell.property_details().cell_type();
1093  bool read_only = cell.property_details().IsReadOnly();
1094  RecordDependency(zone_->New<GlobalPropertyDependency>(cell, type, read_only));
1095}
1096
1097bool CompilationDependencies::DependOnProtector(const PropertyCellRef& cell) {
1098  cell.CacheAsProtector();
1099  if (cell.value().AsSmi() != Protectors::kProtectorValid) return false;
1100  RecordDependency(zone_->New<ProtectorDependency>(cell));
1101  return true;
1102}
1103
1104bool CompilationDependencies::DependOnArrayBufferDetachingProtector() {
1105  return DependOnProtector(MakeRef(
1106      broker_,
1107      broker_->isolate()->factory()->array_buffer_detaching_protector()));
1108}
1109
1110bool CompilationDependencies::DependOnArrayIteratorProtector() {
1111  return DependOnProtector(MakeRef(
1112      broker_, broker_->isolate()->factory()->array_iterator_protector()));
1113}
1114
1115bool CompilationDependencies::DependOnArraySpeciesProtector() {
1116  return DependOnProtector(MakeRef(
1117      broker_, broker_->isolate()->factory()->array_species_protector()));
1118}
1119
1120bool CompilationDependencies::DependOnNoElementsProtector() {
1121  return DependOnProtector(
1122      MakeRef(broker_, broker_->isolate()->factory()->no_elements_protector()));
1123}
1124
1125bool CompilationDependencies::DependOnPromiseHookProtector() {
1126  return DependOnProtector(MakeRef(
1127      broker_, broker_->isolate()->factory()->promise_hook_protector()));
1128}
1129
1130bool CompilationDependencies::DependOnPromiseSpeciesProtector() {
1131  return DependOnProtector(MakeRef(
1132      broker_, broker_->isolate()->factory()->promise_species_protector()));
1133}
1134
1135bool CompilationDependencies::DependOnPromiseThenProtector() {
1136  return DependOnProtector(MakeRef(
1137      broker_, broker_->isolate()->factory()->promise_then_protector()));
1138}
1139
1140void CompilationDependencies::DependOnElementsKind(
1141    const AllocationSiteRef& site) {
1142  ElementsKind kind = site.PointsToLiteral()
1143                          ? site.boilerplate().value().map().elements_kind()
1144                          : site.GetElementsKind();
1145  if (AllocationSite::ShouldTrack(kind)) {
1146    RecordDependency(zone_->New<ElementsKindDependency>(site, kind));
1147  }
1148}
1149
1150void CompilationDependencies::DependOnObjectSlotValue(
1151    const HeapObjectRef& object, int offset, const ObjectRef& value) {
1152  RecordDependency(
1153      zone_->New<ObjectSlotValueDependency>(object, offset, value));
1154}
1155
1156void CompilationDependencies::DependOnOwnConstantElement(
1157    const JSObjectRef& holder, uint32_t index, const ObjectRef& element) {
1158  RecordDependency(
1159      zone_->New<OwnConstantElementDependency>(holder, index, element));
1160}
1161
1162void CompilationDependencies::DependOnOwnConstantDataProperty(
1163    const JSObjectRef& holder, const MapRef& map, Representation representation,
1164    FieldIndex index, const ObjectRef& value) {
1165  RecordDependency(zone_->New<OwnConstantDataPropertyDependency>(
1166      broker_, holder, map, representation, index, value));
1167}
1168
1169void CompilationDependencies::DependOnOwnConstantDictionaryProperty(
1170    const JSObjectRef& holder, InternalIndex index, const ObjectRef& value) {
1171  RecordDependency(zone_->New<OwnConstantDictionaryPropertyDependency>(
1172      broker_, holder, index, value));
1173}
1174
1175V8_INLINE void TraceInvalidCompilationDependency(
1176    const CompilationDependency* d) {
1177  DCHECK(FLAG_trace_compilation_dependencies);
1178  DCHECK(!d->IsValid());
1179  PrintF("Compilation aborted due to invalid dependency: %s\n", d->ToString());
1180}
1181
1182bool CompilationDependencies::Commit(Handle<Code> code) {
1183  if (!PrepareInstall()) return false;
1184
1185  {
1186    PendingDependencies pending_deps(zone_);
1187    DisallowCodeDependencyChange no_dependency_change;
1188    for (const CompilationDependency* dep : dependencies_) {
1189      // Check each dependency's validity again right before installing it,
1190      // because the first iteration above might have invalidated some
1191      // dependencies. For example, PrototypePropertyDependency::PrepareInstall
1192      // can call EnsureHasInitialMap, which can invalidate a
1193      // StableMapDependency on the prototype object's map.
1194      if (!dep->IsValid()) {
1195        if (FLAG_trace_compilation_dependencies) {
1196          TraceInvalidCompilationDependency(dep);
1197        }
1198        dependencies_.clear();
1199        return false;
1200      }
1201      dep->Install(&pending_deps);
1202    }
1203    pending_deps.InstallAll(broker_->isolate(), code);
1204  }
1205
1206  // It is even possible that a GC during the above installations invalidated
1207  // one of the dependencies. However, this should only affect
1208  //
1209  // 1. pretenure mode dependencies, or
1210  // 2. function consistency dependencies,
1211  //
1212  // which we assert below. It is safe to return successfully in these cases,
1213  // because
1214  //
1215  // 1. once the code gets executed it will do a stack check that triggers its
1216  //    deoptimization.
1217  // 2. since the function state was deemed consistent above, that means the
1218  //    compilation saw a self-consistent state of the jsfunction.
1219  if (FLAG_stress_gc_during_compilation) {
1220    broker_->isolate()->heap()->PreciseCollectAllGarbage(
1221        Heap::kForcedGC, GarbageCollectionReason::kTesting, kNoGCCallbackFlags);
1222  }
1223#ifdef DEBUG
1224  for (auto dep : dependencies_) {
1225    CHECK_IMPLIES(!dep->IsValid(),
1226                  dep->IsPretenureMode() || dep->IsConsistentJSFunctionView());
1227  }
1228#endif
1229
1230  dependencies_.clear();
1231  return true;
1232}
1233
1234bool CompilationDependencies::PrepareInstall() {
1235  if (V8_UNLIKELY(FLAG_predictable)) {
1236    return PrepareInstallPredictable();
1237  }
1238
1239  for (auto dep : dependencies_) {
1240    if (!dep->IsValid()) {
1241      if (FLAG_trace_compilation_dependencies) {
1242        TraceInvalidCompilationDependency(dep);
1243      }
1244      dependencies_.clear();
1245      return false;
1246    }
1247    dep->PrepareInstall();
1248  }
1249  return true;
1250}
1251
1252bool CompilationDependencies::PrepareInstallPredictable() {
1253  CHECK(FLAG_predictable);
1254
1255  std::vector<const CompilationDependency*> deps(dependencies_.begin(),
1256                                                 dependencies_.end());
1257  std::sort(deps.begin(), deps.end());
1258
1259  for (auto dep : deps) {
1260    if (!dep->IsValid()) {
1261      if (FLAG_trace_compilation_dependencies) {
1262        TraceInvalidCompilationDependency(dep);
1263      }
1264      dependencies_.clear();
1265      return false;
1266    }
1267    dep->PrepareInstall();
1268  }
1269  return true;
1270}
1271
1272namespace {
1273
1274// This function expects to never see a JSProxy.
1275void DependOnStablePrototypeChain(CompilationDependencies* deps, MapRef map,
1276                                  base::Optional<JSObjectRef> last_prototype) {
1277  while (true) {
1278    HeapObjectRef proto = map.prototype();
1279    if (!proto.IsJSObject()) {
1280      CHECK_EQ(proto.map().oddball_type(), OddballType::kNull);
1281      break;
1282    }
1283    map = proto.map();
1284    deps->DependOnStableMap(map);
1285    if (last_prototype.has_value() && proto.equals(*last_prototype)) break;
1286  }
1287}
1288
1289}  // namespace
1290
1291#define V(Name)                                                     \
1292  const Name##Dependency* CompilationDependency::As##Name() const { \
1293    DCHECK(Is##Name());                                             \
1294    return static_cast<const Name##Dependency*>(this);              \
1295  }
1296DEPENDENCY_LIST(V)
1297#undef V
1298
1299void CompilationDependencies::DependOnStablePrototypeChains(
1300    ZoneVector<MapRef> const& receiver_maps, WhereToStart start,
1301    base::Optional<JSObjectRef> last_prototype) {
1302  for (MapRef receiver_map : receiver_maps) {
1303    if (receiver_map.IsPrimitiveMap()) {
1304      // Perform the implicit ToObject for primitives here.
1305      // Implemented according to ES6 section 7.3.2 GetV (V, P).
1306      // Note: Keep sync'd with AccessInfoFactory::ComputePropertyAccessInfo.
1307      base::Optional<JSFunctionRef> constructor =
1308          broker_->target_native_context().GetConstructorFunction(receiver_map);
1309      receiver_map = constructor.value().initial_map(this);
1310    }
1311    if (start == kStartAtReceiver) DependOnStableMap(receiver_map);
1312    DependOnStablePrototypeChain(this, receiver_map, last_prototype);
1313  }
1314}
1315
1316void CompilationDependencies::DependOnElementsKinds(
1317    const AllocationSiteRef& site) {
1318  AllocationSiteRef current = site;
1319  while (true) {
1320    DependOnElementsKind(current);
1321    if (!current.nested_site().IsAllocationSite()) break;
1322    current = current.nested_site().AsAllocationSite();
1323  }
1324  CHECK_EQ(current.nested_site().AsSmi(), 0);
1325}
1326
1327void CompilationDependencies::DependOnConsistentJSFunctionView(
1328    const JSFunctionRef& function) {
1329  RecordDependency(zone_->New<ConsistentJSFunctionViewDependency>(function));
1330}
1331
1332SlackTrackingPrediction::SlackTrackingPrediction(MapRef initial_map,
1333                                                 int instance_size)
1334    : instance_size_(instance_size),
1335      inobject_property_count_(
1336          (instance_size >> kTaggedSizeLog2) -
1337          initial_map.GetInObjectPropertiesStartInWords()) {}
1338
1339SlackTrackingPrediction
1340CompilationDependencies::DependOnInitialMapInstanceSizePrediction(
1341    const JSFunctionRef& function) {
1342  MapRef initial_map = DependOnInitialMap(function);
1343  int instance_size = function.InitialMapInstanceSizeWithMinSlack(this);
1344  // Currently, we always install the prediction dependency. If this turns out
1345  // to be too expensive, we can only install the dependency if slack
1346  // tracking is active.
1347  RecordDependency(zone_->New<InitialMapInstanceSizePredictionDependency>(
1348      function, instance_size));
1349  CHECK_LE(instance_size, function.initial_map(this).instance_size());
1350  return SlackTrackingPrediction(initial_map, instance_size);
1351}
1352
1353CompilationDependency const*
1354CompilationDependencies::TransitionDependencyOffTheRecord(
1355    const MapRef& target_map) const {
1356  if (target_map.CanBeDeprecated()) {
1357    return zone_->New<TransitionDependency>(target_map);
1358  } else {
1359    DCHECK(!target_map.is_deprecated());
1360    return nullptr;
1361  }
1362}
1363
1364CompilationDependency const*
1365CompilationDependencies::FieldRepresentationDependencyOffTheRecord(
1366    const MapRef& map, InternalIndex descriptor,
1367    Representation representation) const {
1368  return zone_->New<FieldRepresentationDependency>(map, descriptor,
1369                                                   representation);
1370}
1371
1372CompilationDependency const*
1373CompilationDependencies::FieldTypeDependencyOffTheRecord(
1374    const MapRef& map, InternalIndex descriptor, const ObjectRef& type) const {
1375  return zone_->New<FieldTypeDependency>(map, descriptor, type);
1376}
1377
1378#ifdef DEBUG
1379// static
1380bool CompilationDependencies::IsFieldRepresentationDependencyOnMap(
1381    const CompilationDependency* dep, const Handle<Map>& receiver_map) {
1382  return dep->IsFieldRepresentation() &&
1383         dep->AsFieldRepresentation()->DependsOn(receiver_map);
1384}
1385#endif  // DEBUG
1386
1387#undef DEPENDENCY_LIST
1388
1389}  // namespace compiler
1390}  // namespace internal
1391}  // namespace v8
1392