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