Line data Source code
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 1808810 : DependentCode* CompilationDependencies::Get(Handle<Object> object) const {
17 1808813 : if (object->IsMap()) {
18 : return Handle<Map>::cast(object)->dependent_code();
19 1543844 : } else if (object->IsPropertyCell()) {
20 : return Handle<PropertyCell>::cast(object)->dependent_code();
21 78955 : } else if (object->IsAllocationSite()) {
22 : return Handle<AllocationSite>::cast(object)->dependent_code();
23 : }
24 0 : UNREACHABLE();
25 : return nullptr;
26 : }
27 :
28 :
29 280581 : void CompilationDependencies::Set(Handle<Object> object,
30 : Handle<DependentCode> dep) {
31 280581 : if (object->IsMap()) {
32 43443 : Handle<Map>::cast(object)->set_dependent_code(*dep);
33 237138 : } else if (object->IsPropertyCell()) {
34 205217 : Handle<PropertyCell>::cast(object)->set_dependent_code(*dep);
35 31921 : } else if (object->IsAllocationSite()) {
36 31921 : Handle<AllocationSite>::cast(object)->set_dependent_code(*dep);
37 : } else {
38 0 : UNREACHABLE();
39 : }
40 280581 : }
41 :
42 :
43 904414 : void CompilationDependencies::Insert(DependentCode::DependencyGroup group,
44 : Handle<HeapObject> object) {
45 904414 : if (groups_[group] == nullptr) {
46 681953 : groups_[group] = new (zone_) ZoneList<Handle<HeapObject>>(2, zone_);
47 : }
48 904413 : groups_[group]->Add(object, zone_);
49 :
50 904413 : if (object_wrapper_.is_null()) {
51 : // Allocate the wrapper if necessary.
52 : object_wrapper_ =
53 266902 : isolate_->factory()->NewForeign(reinterpret_cast<Address>(this));
54 : }
55 :
56 : // Get the old dependent code list.
57 : Handle<DependentCode> old_dependent_code =
58 2713240 : Handle<DependentCode>(Get(object), isolate_);
59 : Handle<DependentCode> new_dependent_code =
60 : DependentCode::InsertCompilationDependencies(old_dependent_code, group,
61 904414 : object_wrapper_);
62 :
63 : // Set the new dependent code list if the head of the list changed.
64 904414 : if (!new_dependent_code.is_identical_to(old_dependent_code)) {
65 280581 : Set(object, new_dependent_code);
66 : }
67 904414 : }
68 :
69 :
70 643616 : void CompilationDependencies::Commit(Handle<Code> code) {
71 1027677 : if (IsEmpty()) return;
72 :
73 : DCHECK(!object_wrapper_.is_null());
74 259555 : Handle<WeakCell> cell = Code::WeakCellFor(code);
75 : AllowDeferredHandleDereference get_wrapper;
76 2336008 : for (int i = 0; i < DependentCode::kGroupCount; i++) {
77 2076451 : ZoneList<Handle<HeapObject>>* group_objects = groups_[i];
78 2076451 : if (group_objects == nullptr) continue;
79 : DependentCode::DependencyGroup group =
80 331915 : static_cast<DependentCode::DependencyGroup>(i);
81 2403720 : for (int j = 0; j < group_objects->length(); j++) {
82 2071807 : DependentCode* dependent_code = Get(group_objects->at(j));
83 869947 : dependent_code->UpdateToFinishedCode(group, *object_wrapper_, *cell);
84 : }
85 331913 : groups_[i] = nullptr; // Zone-allocated, no need to delete.
86 : }
87 : }
88 :
89 :
90 4832039 : void CompilationDependencies::Rollback() {
91 9664078 : if (IsEmpty()) return;
92 :
93 : AllowDeferredHandleDereference get_wrapper;
94 : // Unregister from all dependent maps if not yet committed.
95 58712 : for (int i = 0; i < DependentCode::kGroupCount; i++) {
96 58712 : ZoneList<Handle<HeapObject>>* group_objects = groups_[i];
97 58712 : if (group_objects == nullptr) continue;
98 : DependentCode::DependencyGroup group =
99 9052 : static_cast<DependentCode::DependencyGroup>(i);
100 87010 : for (int j = 0; j < group_objects->length(); j++) {
101 77958 : DependentCode* dependent_code = Get(group_objects->at(j));
102 34453 : dependent_code->RemoveCompilationDependencies(group, *object_wrapper_);
103 : }
104 9052 : groups_[i] = nullptr; // Zone-allocated, no need to delete.
105 : }
106 : }
107 :
108 :
109 4495 : void CompilationDependencies::AssumeMapNotDeprecated(Handle<Map> map) {
110 : DCHECK(!map->is_deprecated());
111 : // Do nothing if the map cannot be deprecated.
112 4495 : if (map->CanBeDeprecated()) {
113 4473 : Insert(DependentCode::kTransitionGroup, map);
114 : }
115 4495 : }
116 :
117 :
118 108035 : void CompilationDependencies::AssumeMapStable(Handle<Map> map) {
119 : DCHECK(map->is_stable());
120 : // Do nothing if the map cannot transition.
121 108035 : if (map->CanTransition()) {
122 106346 : Insert(DependentCode::kPrototypeCheckGroup, map);
123 : }
124 108035 : }
125 :
126 :
127 24373 : void CompilationDependencies::AssumePrototypeMapsStable(
128 : Handle<Map> map, MaybeHandle<JSReceiver> prototype) {
129 34254 : for (PrototypeIterator i(map); !i.IsAtEnd(); i.Advance()) {
130 : Handle<JSReceiver> const current =
131 : PrototypeIterator::GetCurrent<JSReceiver>(i);
132 33226 : AssumeMapStable(handle(current->map()));
133 : Handle<JSReceiver> last;
134 64396 : if (prototype.ToHandle(&last) && last.is_identical_to(current)) {
135 : break;
136 : }
137 : }
138 24373 : }
139 :
140 :
141 15927 : 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 15927 : site->SitePointsToLiteral()
146 : ? JSObject::cast(site->transition_info())->GetElementsKind()
147 15927 : : site->GetElementsKind();
148 15927 : if (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) {
149 4731 : Insert(DependentCode::kAllocationSiteTransitionChangedGroup, site);
150 : }
151 15927 : }
152 :
153 : } // namespace internal
154 : } // namespace v8
|