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/compilation-dependencies.h" 6 7 #include "src/factory.h" 8 #include "src/handles-inl.h" 9 #include "src/isolate.h" 10 #include "src/objects-inl.h" 11 #include "src/zone/zone.h" 12 13 namespace v8 { 14 namespace internal { 15 16 DependentCode* CompilationDependencies::Get(Handle<Object> object) { 17 if (object->IsMap()) { 18 return Handle<Map>::cast(object)->dependent_code(); 19 } else if (object->IsPropertyCell()) { 20 return Handle<PropertyCell>::cast(object)->dependent_code(); 21 } else if (object->IsAllocationSite()) { 22 return Handle<AllocationSite>::cast(object)->dependent_code(); 23 } 24 UNREACHABLE(); 25 return nullptr; 26 } 27 28 29 void CompilationDependencies::Set(Handle<Object> object, 30 Handle<DependentCode> dep) { 31 if (object->IsMap()) { 32 Handle<Map>::cast(object)->set_dependent_code(*dep); 33 } else if (object->IsPropertyCell()) { 34 Handle<PropertyCell>::cast(object)->set_dependent_code(*dep); 35 } else if (object->IsAllocationSite()) { 36 Handle<AllocationSite>::cast(object)->set_dependent_code(*dep); 37 } else { 38 UNREACHABLE(); 39 } 40 } 41 42 43 void CompilationDependencies::Insert(DependentCode::DependencyGroup group, 44 Handle<HeapObject> object) { 45 if (groups_[group] == nullptr) { 46 groups_[group] = new (zone_) ZoneList<Handle<HeapObject>>(2, zone_); 47 } 48 groups_[group]->Add(object, zone_); 49 50 if (object_wrapper_.is_null()) { 51 // Allocate the wrapper if necessary. 52 object_wrapper_ = 53 isolate_->factory()->NewForeign(reinterpret_cast<Address>(this)); 54 } 55 56 // Get the old dependent code list. 57 Handle<DependentCode> old_dependent_code = 58 Handle<DependentCode>(Get(object), isolate_); 59 Handle<DependentCode> new_dependent_code = 60 DependentCode::InsertCompilationDependencies(old_dependent_code, group, 61 object_wrapper_); 62 63 // Set the new dependent code list if the head of the list changed. 64 if (!new_dependent_code.is_identical_to(old_dependent_code)) { 65 Set(object, new_dependent_code); 66 } 67 } 68 69 70 void CompilationDependencies::Commit(Handle<Code> code) { 71 if (IsEmpty()) return; 72 73 DCHECK(!object_wrapper_.is_null()); 74 Handle<WeakCell> cell = Code::WeakCellFor(code); 75 AllowDeferredHandleDereference get_wrapper; 76 for (int i = 0; i < DependentCode::kGroupCount; i++) { 77 ZoneList<Handle<HeapObject>>* group_objects = groups_[i]; 78 if (group_objects == nullptr) continue; 79 DependentCode::DependencyGroup group = 80 static_cast<DependentCode::DependencyGroup>(i); 81 for (int j = 0; j < group_objects->length(); j++) { 82 DependentCode* dependent_code = Get(group_objects->at(j)); 83 dependent_code->UpdateToFinishedCode(group, *object_wrapper_, *cell); 84 } 85 groups_[i] = nullptr; // Zone-allocated, no need to delete. 86 } 87 } 88 89 90 void CompilationDependencies::Rollback() { 91 if (IsEmpty()) return; 92 93 AllowDeferredHandleDereference get_wrapper; 94 // Unregister from all dependent maps if not yet committed. 95 for (int i = 0; i < DependentCode::kGroupCount; i++) { 96 ZoneList<Handle<HeapObject>>* group_objects = groups_[i]; 97 if (group_objects == nullptr) continue; 98 DependentCode::DependencyGroup group = 99 static_cast<DependentCode::DependencyGroup>(i); 100 for (int j = 0; j < group_objects->length(); j++) { 101 DependentCode* dependent_code = Get(group_objects->at(j)); 102 dependent_code->RemoveCompilationDependencies(group, *object_wrapper_); 103 } 104 groups_[i] = nullptr; // Zone-allocated, no need to delete. 105 } 106 } 107 108 109 void CompilationDependencies::AssumeMapNotDeprecated(Handle<Map> map) { 110 DCHECK(!map->is_deprecated()); 111 // Do nothing if the map cannot be deprecated. 112 if (map->CanBeDeprecated()) { 113 Insert(DependentCode::kTransitionGroup, map); 114 } 115 } 116 117 118 void CompilationDependencies::AssumeMapStable(Handle<Map> map) { 119 DCHECK(map->is_stable()); 120 // Do nothing if the map cannot transition. 121 if (map->CanTransition()) { 122 Insert(DependentCode::kPrototypeCheckGroup, map); 123 } 124 } 125 126 127 void CompilationDependencies::AssumePrototypeMapsStable( 128 Handle<Map> map, MaybeHandle<JSReceiver> prototype) { 129 for (PrototypeIterator i(map); !i.IsAtEnd(); i.Advance()) { 130 Handle<JSReceiver> const current = 131 PrototypeIterator::GetCurrent<JSReceiver>(i); 132 AssumeMapStable(handle(current->map())); 133 Handle<JSReceiver> last; 134 if (prototype.ToHandle(&last) && last.is_identical_to(current)) { 135 break; 136 } 137 } 138 } 139 140 141 void CompilationDependencies::AssumeTransitionStable( 142 Handle<AllocationSite> site) { 143 // Do nothing if the object doesn't have any useful element transitions left. 144 ElementsKind kind = 145 site->SitePointsToLiteral() 146 ? JSObject::cast(site->transition_info())->GetElementsKind() 147 : site->GetElementsKind(); 148 if (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) { 149 Insert(DependentCode::kAllocationSiteTransitionChangedGroup, site); 150 } 151 } 152 153 } // namespace internal 154 } // namespace v8 155