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 1479378 : DependentCode* CompilationDependencies::Get(Handle<Object> object) const {
17 1479378 : if (object->IsMap()) {
18 : return Handle<Map>::cast(object)->dependent_code();
19 1039610 : } else if (object->IsPropertyCell()) {
20 : return Handle<PropertyCell>::cast(object)->dependent_code();
21 16954 : } else if (object->IsAllocationSite()) {
22 : return Handle<AllocationSite>::cast(object)->dependent_code();
23 : }
24 0 : UNREACHABLE();
25 : }
26 :
27 :
28 242586 : void CompilationDependencies::Set(Handle<Object> object,
29 : Handle<DependentCode> dep) {
30 242586 : if (object->IsMap()) {
31 81271 : Handle<Map>::cast(object)->set_dependent_code(*dep);
32 161315 : } else if (object->IsPropertyCell()) {
33 153157 : Handle<PropertyCell>::cast(object)->set_dependent_code(*dep);
34 8158 : } else if (object->IsAllocationSite()) {
35 8158 : Handle<AllocationSite>::cast(object)->set_dependent_code(*dep);
36 : } else {
37 0 : UNREACHABLE();
38 : }
39 242586 : }
40 :
41 :
42 739697 : void CompilationDependencies::Insert(DependentCode::DependencyGroup group,
43 : Handle<HeapObject> object) {
44 739697 : if (groups_[group] == nullptr) {
45 258947 : groups_[group] = new (zone_->New(sizeof(ZoneVector<Handle<HeapObject>>)))
46 517894 : ZoneVector<Handle<HeapObject>>(zone_);
47 : }
48 739697 : groups_[group]->push_back(object);
49 :
50 739697 : if (object_wrapper_.is_null()) {
51 : // Allocate the wrapper if necessary.
52 : object_wrapper_ =
53 182293 : isolate_->factory()->NewForeign(reinterpret_cast<Address>(this));
54 : }
55 :
56 : // Get the old dependent code list.
57 : Handle<DependentCode> old_dependent_code =
58 2219091 : Handle<DependentCode>(Get(object), isolate_);
59 : Handle<DependentCode> new_dependent_code =
60 : DependentCode::InsertCompilationDependencies(old_dependent_code, group,
61 739697 : object_wrapper_);
62 :
63 : // Set the new dependent code list if the head of the list changed.
64 739697 : if (!new_dependent_code.is_identical_to(old_dependent_code)) {
65 242586 : Set(object, new_dependent_code);
66 : }
67 739697 : }
68 :
69 :
70 439767 : void CompilationDependencies::Commit(Handle<Code> code) {
71 698703 : if (IsEmpty()) return;
72 :
73 : DCHECK(!object_wrapper_.is_null());
74 180831 : Handle<WeakCell> cell = Code::WeakCellFor(code);
75 : AllowDeferredHandleDereference get_wrapper;
76 1627479 : for (int i = 0; i < DependentCode::kGroupCount; i++) {
77 1446648 : ZoneVector<Handle<HeapObject>>* group_objects = groups_[i];
78 1446648 : if (group_objects == nullptr) continue;
79 : DependentCode::DependencyGroup group =
80 256999 : static_cast<DependentCode::DependencyGroup>(i);
81 1976110 : for (size_t j = 0; j < group_objects->size(); j++) {
82 1719111 : DependentCode* dependent_code = Get(group_objects->at(j));
83 731056 : dependent_code->UpdateToFinishedCode(group, *object_wrapper_, *cell);
84 : }
85 256999 : groups_[i] = nullptr; // Zone-allocated, no need to delete.
86 : }
87 : }
88 :
89 :
90 3797342 : void CompilationDependencies::Rollback() {
91 7594684 : if (IsEmpty()) return;
92 :
93 : AllowDeferredHandleDereference get_wrapper;
94 : // Unregister from all dependent maps if not yet committed.
95 11664 : for (int i = 0; i < DependentCode::kGroupCount; i++) {
96 11664 : ZoneVector<Handle<HeapObject>>* group_objects = groups_[i];
97 11664 : if (group_objects == nullptr) continue;
98 : DependentCode::DependencyGroup group =
99 1941 : static_cast<DependentCode::DependencyGroup>(i);
100 21132 : for (size_t j = 0; j < group_objects->size(); j++) {
101 19191 : DependentCode* dependent_code = Get(group_objects->at(j));
102 8625 : dependent_code->RemoveCompilationDependencies(group, *object_wrapper_);
103 : }
104 1941 : groups_[i] = nullptr; // Zone-allocated, no need to delete.
105 : }
106 : }
107 :
108 :
109 20434 : void CompilationDependencies::AssumeMapNotDeprecated(Handle<Map> map) {
110 : DCHECK(!map->is_deprecated());
111 : // Do nothing if the map cannot be deprecated.
112 20434 : if (map->CanBeDeprecated()) {
113 11425 : Insert(DependentCode::kTransitionGroup, map);
114 : }
115 20434 : }
116 :
117 :
118 157465 : void CompilationDependencies::AssumeMapStable(Handle<Map> map) {
119 : DCHECK(map->is_stable());
120 : // Do nothing if the map cannot transition.
121 157465 : if (map->CanTransition()) {
122 155642 : Insert(DependentCode::kPrototypeCheckGroup, map);
123 : }
124 157465 : }
125 :
126 :
127 42809 : void CompilationDependencies::AssumePrototypeMapsStable(
128 : Handle<Map> map, MaybeHandle<JSReceiver> prototype) {
129 78672 : for (PrototypeIterator i(map); !i.IsAtEnd(); i.Advance()) {
130 : Handle<JSReceiver> const current =
131 : PrototypeIterator::GetCurrent<JSReceiver>(i);
132 77026 : AssumeMapStable(handle(current->map()));
133 : Handle<JSReceiver> last;
134 150760 : if (prototype.ToHandle(&last) && last.is_identical_to(current)) {
135 : break;
136 : }
137 : }
138 42809 : }
139 :
140 :
141 6515 : void CompilationDependencies::AssumeTransitionStable(
142 : Handle<AllocationSite> site) {
143 : // Do nothing if the object doesn't have any useful element transitions left.
144 : ElementsKind kind = site->PointsToLiteral()
145 : ? site->boilerplate()->GetElementsKind()
146 6515 : : site->GetElementsKind();
147 6515 : if (AllocationSite::ShouldTrack(kind)) {
148 2627 : Insert(DependentCode::kAllocationSiteTransitionChangedGroup, site);
149 : }
150 6515 : }
151 :
152 : } // namespace internal
153 : } // namespace v8
|