// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/compilation-dependencies.h" #include "src/factory.h" #include "src/handles-inl.h" #include "src/isolate.h" #include "src/objects-inl.h" #include "src/zone.h" namespace v8 { namespace internal { DependentCode* CompilationDependencies::Get(Handle object) { if (object->IsMap()) { return Handle::cast(object)->dependent_code(); } else if (object->IsPropertyCell()) { return Handle::cast(object)->dependent_code(); } else if (object->IsAllocationSite()) { return Handle::cast(object)->dependent_code(); } UNREACHABLE(); return nullptr; } void CompilationDependencies::Set(Handle object, Handle dep) { if (object->IsMap()) { Handle::cast(object)->set_dependent_code(*dep); } else if (object->IsPropertyCell()) { Handle::cast(object)->set_dependent_code(*dep); } else if (object->IsAllocationSite()) { Handle::cast(object)->set_dependent_code(*dep); } else { UNREACHABLE(); } } void CompilationDependencies::Insert(DependentCode::DependencyGroup group, Handle object) { if (groups_[group] == nullptr) { groups_[group] = new (zone_) ZoneList>(2, zone_); } groups_[group]->Add(object, zone_); if (object_wrapper_.is_null()) { // Allocate the wrapper if necessary. object_wrapper_ = isolate_->factory()->NewForeign(reinterpret_cast
(this)); } // Get the old dependent code list. Handle old_dependent_code = Handle(Get(object), isolate_); Handle new_dependent_code = DependentCode::InsertCompilationDependencies(old_dependent_code, group, object_wrapper_); // Set the new dependent code list if the head of the list changed. if (!new_dependent_code.is_identical_to(old_dependent_code)) { Set(object, new_dependent_code); } } void CompilationDependencies::Commit(Handle code) { if (IsEmpty()) return; DCHECK(!object_wrapper_.is_null()); Handle cell = Code::WeakCellFor(code); AllowDeferredHandleDereference get_wrapper; for (int i = 0; i < DependentCode::kGroupCount; i++) { ZoneList>* group_objects = groups_[i]; if (group_objects == nullptr) continue; DependentCode::DependencyGroup group = static_cast(i); for (int j = 0; j < group_objects->length(); j++) { DependentCode* dependent_code = Get(group_objects->at(j)); dependent_code->UpdateToFinishedCode(group, *object_wrapper_, *cell); } groups_[i] = nullptr; // Zone-allocated, no need to delete. } } void CompilationDependencies::Rollback() { if (IsEmpty()) return; AllowDeferredHandleDereference get_wrapper; // Unregister from all dependent maps if not yet committed. for (int i = 0; i < DependentCode::kGroupCount; i++) { ZoneList>* group_objects = groups_[i]; if (group_objects == nullptr) continue; DependentCode::DependencyGroup group = static_cast(i); for (int j = 0; j < group_objects->length(); j++) { DependentCode* dependent_code = Get(group_objects->at(j)); dependent_code->RemoveCompilationDependencies(group, *object_wrapper_); } groups_[i] = nullptr; // Zone-allocated, no need to delete. } } void CompilationDependencies::AssumeMapNotDeprecated(Handle map) { DCHECK(!map->is_deprecated()); // Do nothing if the map cannot be deprecated. if (map->CanBeDeprecated()) { Insert(DependentCode::kTransitionGroup, map); } } void CompilationDependencies::AssumeMapStable(Handle map) { DCHECK(map->is_stable()); // Do nothing if the map cannot transition. if (map->CanTransition()) { Insert(DependentCode::kPrototypeCheckGroup, map); } } void CompilationDependencies::AssumeTransitionStable( Handle site) { // Do nothing if the object doesn't have any useful element transitions left. ElementsKind kind = site->SitePointsToLiteral() ? JSObject::cast(site->transition_info())->GetElementsKind() : site->GetElementsKind(); if (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) { Insert(DependentCode::kAllocationSiteTransitionChangedGroup, site); } } } // namespace internal } // namespace v8