5 #include "src/compiler/compilation-dependencies.h" 7 #include "src/handles-inl.h" 8 #include "src/objects-inl.h" 14 CompilationDependencies::CompilationDependencies(Isolate* isolate, Zone* zone)
15 : zone_(zone), dependencies_(zone) {}
19 virtual bool IsValid()
const = 0;
20 virtual void PrepareInstall() {}
29 : function_(
function), initial_map_(initial_map) {
30 DCHECK(function_.has_initial_map());
31 DCHECK(function_.initial_map().equals(initial_map_));
34 bool IsValid()
const override {
36 return function->has_initial_map() &&
37 function->initial_map() == *initial_map_.object();
41 SLOW_DCHECK(IsValid());
42 DependentCode::InstallDependency(function_.isolate(), code,
43 initial_map_.object(),
44 DependentCode::kInitialMapChangedGroup);
59 : function_(
function), prototype_(prototype) {
60 DCHECK(function_.has_prototype());
61 DCHECK(!function_.PrototypeRequiresRuntimeLookup());
62 DCHECK(function_.prototype().equals(prototype_));
65 bool IsValid()
const override {
67 return function->has_prototype_slot() &&
function->has_prototype() &&
68 !
function->PrototypeRequiresRuntimeLookup() &&
69 function->prototype() == *prototype_.object();
72 void PrepareInstall()
override {
73 SLOW_DCHECK(IsValid());
75 if (!function->has_initial_map()) JSFunction::EnsureHasInitialMap(
function);
79 SLOW_DCHECK(IsValid());
81 DCHECK(function->has_initial_map());
82 Handle<Map> initial_map(function->initial_map(), function_.isolate());
83 DependentCode::InstallDependency(function_.isolate(), code, initial_map,
84 DependentCode::kInitialMapChangedGroup);
95 DCHECK(map_.is_stable());
98 bool IsValid()
const override {
return map_.object()->is_stable(); }
101 SLOW_DCHECK(IsValid());
102 DependentCode::InstallDependency(map_.isolate(), code, map_.object(),
103 DependentCode::kPrototypeCheckGroup);
113 DCHECK(!map_.is_deprecated());
116 bool IsValid()
const override {
return !map_.object()->is_deprecated(); }
119 SLOW_DCHECK(IsValid());
120 DependentCode::InstallDependency(map_.isolate(), code, map_.object(),
121 DependentCode::kTransitionGroup);
134 : site_(site), mode_(mode) {
135 DCHECK_EQ(mode_, site_.GetPretenureMode());
138 bool IsValid()
const override {
139 return mode_ == site_.object()->GetPretenureMode();
143 SLOW_DCHECK(IsValid());
144 DependentCode::InstallDependency(
145 site_.isolate(), code, site_.object(),
146 DependentCode::kAllocationSiteTenuringChangedGroup);
161 descriptor_(descriptor),
163 constness_(constness) {
164 DCHECK(owner_.equals(owner_.FindFieldOwner(descriptor_)));
165 DCHECK(type_.equals(owner_.GetFieldType(descriptor_)));
166 DCHECK_EQ(constness_, owner_.GetPropertyDetails(descriptor_).constness());
169 bool IsValid()
const override {
173 return *
type == owner->instance_descriptors()->GetFieldType(descriptor_) &&
174 constness_ == owner->instance_descriptors()
175 ->GetDetails(descriptor_)
180 SLOW_DCHECK(IsValid());
181 DependentCode::InstallDependency(owner_.isolate(), code, owner_.object(),
182 DependentCode::kFieldOwnerGroup);
189 PropertyConstness constness_;
199 : cell_(cell), type_(
type), read_only_(read_only) {
200 DCHECK_EQ(type_, cell_.property_details().cell_type());
201 DCHECK_EQ(read_only_, cell_.property_details().IsReadOnly());
204 bool IsValid()
const override {
208 if (cell->value() == *(cell_.isolate()->factory()->the_hole_value())) {
209 DCHECK(cell->property_details().cell_type() ==
210 PropertyCellType::kInvalidated ||
211 cell->property_details().cell_type() ==
212 PropertyCellType::kUninitialized);
215 return type_ == cell->property_details().cell_type() &&
216 read_only_ == cell->property_details().IsReadOnly();
220 SLOW_DCHECK(IsValid());
221 DependentCode::InstallDependency(cell_.isolate(), code, cell_.object(),
222 DependentCode::kPropertyCellChangedGroup);
227 PropertyCellType type_;
234 DCHECK_EQ(cell_.value().AsSmi(), Isolate::kProtectorValid);
237 bool IsValid()
const override {
239 return cell->value() == Smi::FromInt(Isolate::kProtectorValid);
243 SLOW_DCHECK(IsValid());
244 DependentCode::InstallDependency(cell_.isolate(), code, cell_.object(),
245 DependentCode::kPropertyCellChangedGroup);
258 : site_(site), kind_(kind) {
259 DCHECK(AllocationSite::ShouldTrack(kind_));
260 DCHECK_EQ(kind_, site_.PointsToLiteral()
261 ? site_.boilerplate().value().GetElementsKind()
262 : site_.GetElementsKind());
265 bool IsValid()
const override {
267 ElementsKind kind = site->PointsToLiteral()
268 ? site->boilerplate()->GetElementsKind()
269 : site->GetElementsKind();
270 return kind_ == kind;
274 SLOW_DCHECK(IsValid());
275 DependentCode::InstallDependency(
276 site_.isolate(), code, site_.object(),
277 DependentCode::kAllocationSiteTransitionChangedGroup);
290 : function_(
function), instance_size_(instance_size) {}
292 bool IsValid()
const override {
295 if (!function_.object()->has_initial_map())
return false;
296 int instance_size = function_.object()->ComputeInstanceSizeWithMinSlack(
297 function_.isolate());
298 return instance_size == instance_size_;
301 void PrepareInstall()
override {
302 SLOW_DCHECK(IsValid());
303 function_.object()->CompleteInobjectSlackTrackingIfActive();
307 SLOW_DCHECK(IsValid());
308 DCHECK(!function_.object()
310 ->IsInobjectSlackTrackingInProgress());
318 MapRef CompilationDependencies::DependOnInitialMap(
320 MapRef map =
function.initial_map();
325 ObjectRef CompilationDependencies::DependOnPrototypeProperty(
326 const JSFunctionRef&
function) {
327 ObjectRef prototype =
function.prototype();
328 dependencies_.push_front(
329 new (zone_) PrototypePropertyDependency(
function, prototype));
333 void CompilationDependencies::DependOnStableMap(
const MapRef& map) {
334 if (map.CanTransition()) {
335 dependencies_.push_front(
new (zone_) StableMapDependency(map));
337 DCHECK(map.is_stable());
341 void CompilationDependencies::DependOnTransition(
const MapRef& target_map) {
342 if (target_map.CanBeDeprecated()) {
343 dependencies_.push_front(
new (zone_) TransitionDependency(target_map));
345 DCHECK(!target_map.is_deprecated());
349 PretenureFlag CompilationDependencies::DependOnPretenureMode(
350 const AllocationSiteRef& site) {
351 PretenureFlag mode = site.GetPretenureMode();
352 dependencies_.push_front(
new (zone_) PretenureModeDependency(site, mode));
356 void CompilationDependencies::DependOnFieldType(
const MapRef& map,
358 MapRef owner = map.FindFieldOwner(descriptor);
359 ObjectRef type = owner.GetFieldType(descriptor);
360 PropertyConstness constness =
361 owner.GetPropertyDetails(descriptor).constness();
362 DCHECK(type.equals(map.GetFieldType(descriptor)));
363 dependencies_.push_front(
364 new (zone_) FieldTypeDependency(owner, descriptor, type, constness));
367 void CompilationDependencies::DependOnGlobalProperty(
368 const PropertyCellRef& cell) {
369 PropertyCellType type = cell.property_details().cell_type();
370 bool read_only = cell.property_details().IsReadOnly();
371 dependencies_.push_front(
new (zone_)
372 GlobalPropertyDependency(cell, type, read_only));
375 void CompilationDependencies::DependOnProtector(
const PropertyCellRef& cell) {
376 dependencies_.push_front(
new (zone_) ProtectorDependency(cell));
379 void CompilationDependencies::DependOnElementsKind(
380 const AllocationSiteRef& site) {
382 ElementsKind kind = site.PointsToLiteral()
383 ? site.boilerplate().value().GetElementsKind()
384 : site.GetElementsKind();
385 if (AllocationSite::ShouldTrack(kind)) {
386 dependencies_.push_front(
new (zone_) ElementsKindDependency(site, kind));
390 bool CompilationDependencies::AreValid()
const {
391 for (
auto dep : dependencies_) {
392 if (!dep->IsValid())
return false;
397 bool CompilationDependencies::Commit(Handle<Code> code) {
398 for (
auto dep : dependencies_) {
399 if (!dep->IsValid()) {
400 dependencies_.clear();
403 dep->PrepareInstall();
406 DisallowCodeDependencyChange no_dependency_change;
407 for (
auto dep : dependencies_) {
413 if (!dep->IsValid()) {
414 dependencies_.clear();
417 dep->Install(MaybeObjectHandle::Weak(code));
419 SLOW_DCHECK(AreValid());
421 dependencies_.clear();
427 void DependOnStablePrototypeChain(JSHeapBroker* broker,
428 CompilationDependencies* deps, MapRef map,
429 const JSObjectRef& last_prototype) {
431 map.SerializePrototype();
432 JSObjectRef proto = map.prototype().AsJSObject();
434 deps->DependOnStableMap(map);
435 if (proto.equals(last_prototype))
break;
440 void CompilationDependencies::DependOnStablePrototypeChains(
441 JSHeapBroker* broker, std::vector<Handle<Map>>
const& receiver_maps,
442 const JSObjectRef& holder) {
444 for (
auto map : receiver_maps) {
445 MapRef receiver_map(broker, map);
446 if (receiver_map.IsPrimitiveMap()) {
449 base::Optional<JSFunctionRef> constructor =
450 broker->native_context().GetConstructorFunction(receiver_map);
451 if (constructor.has_value()) receiver_map = constructor->initial_map();
453 DependOnStablePrototypeChain(broker,
this, receiver_map, holder);
457 void CompilationDependencies::DependOnElementsKinds(
458 const AllocationSiteRef& site) {
459 AllocationSiteRef current = site;
461 DependOnElementsKind(current);
462 if (!current.nested_site().IsAllocationSite())
break;
463 current = current.nested_site().AsAllocationSite();
465 CHECK_EQ(current.nested_site().AsSmi(), 0);
468 SlackTrackingPrediction::SlackTrackingPrediction(MapRef initial_map,
470 : instance_size_(instance_size),
471 inobject_property_count_(
472 (instance_size >> kPointerSizeLog2) -
473 initial_map.GetInObjectPropertiesStartInWords()) {}
475 SlackTrackingPrediction
476 CompilationDependencies::DependOnInitialMapInstanceSizePrediction(
477 const JSFunctionRef&
function) {
478 MapRef initial_map = DependOnInitialMap(
function);
479 int instance_size =
function.InitialMapInstanceSizeWithMinSlack();
483 dependencies_.push_front(
485 InitialMapInstanceSizePredictionDependency(
function, instance_size));
486 DCHECK_LE(instance_size,
function.initial_map().instance_size());
487 return SlackTrackingPrediction(initial_map, instance_size);