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 1810909 : DependentCode* CompilationDependencies::Get(Handle<Object> object) const {
17 1810909 : if (object->IsMap()) {
18 : return Handle<Map>::cast(object)->dependent_code();
19 1545310 : } else if (object->IsPropertyCell()) {
20 : return Handle<PropertyCell>::cast(object)->dependent_code();
21 79143 : } else if (object->IsAllocationSite()) {
22 : return Handle<AllocationSite>::cast(object)->dependent_code();
23 : }
24 0 : UNREACHABLE();
25 : return nullptr;
26 : }
27 :
28 :
29 281155 : void CompilationDependencies::Set(Handle<Object> object,
30 : Handle<DependentCode> dep) {
31 281155 : if (object->IsMap()) {
32 43528 : Handle<Map>::cast(object)->set_dependent_code(*dep);
33 237627 : } else if (object->IsPropertyCell()) {
34 205630 : Handle<PropertyCell>::cast(object)->set_dependent_code(*dep);
35 31997 : } else if (object->IsAllocationSite()) {
36 31997 : Handle<AllocationSite>::cast(object)->set_dependent_code(*dep);
37 : } else {
38 0 : UNREACHABLE();
39 : }
40 281155 : }
41 :
42 :
43 905459 : void CompilationDependencies::Insert(DependentCode::DependencyGroup group,
44 : Handle<HeapObject> object) {
45 905459 : if (groups_[group] == nullptr) {
46 683636 : groups_[group] = new (zone_) ZoneList<Handle<HeapObject>>(2, zone_);
47 : }
48 905458 : groups_[group]->Add(object, zone_);
49 :
50 905458 : if (object_wrapper_.is_null()) {
51 : // Allocate the wrapper if necessary.
52 : object_wrapper_ =
53 267426 : isolate_->factory()->NewForeign(reinterpret_cast<Address>(this));
54 : }
55 :
56 : // Get the old dependent code list.
57 : Handle<DependentCode> old_dependent_code =
58 2716377 : Handle<DependentCode>(Get(object), isolate_);
59 : Handle<DependentCode> new_dependent_code =
60 : DependentCode::InsertCompilationDependencies(old_dependent_code, group,
61 905459 : object_wrapper_);
62 :
63 : // Set the new dependent code list if the head of the list changed.
64 905459 : if (!new_dependent_code.is_identical_to(old_dependent_code)) {
65 281155 : Set(object, new_dependent_code);
66 : }
67 905459 : }
68 :
69 :
70 644102 : void CompilationDependencies::Commit(Handle<Code> code) {
71 1028320 : if (IsEmpty()) return;
72 :
73 : DCHECK(!object_wrapper_.is_null());
74 259884 : Handle<WeakCell> cell = Code::WeakCellFor(code);
75 : AllowDeferredHandleDereference get_wrapper;
76 2338955 : for (int i = 0; i < DependentCode::kGroupCount; i++) {
77 2079071 : ZoneList<Handle<HeapObject>>* group_objects = groups_[i];
78 2079071 : if (group_objects == nullptr) continue;
79 : DependentCode::DependencyGroup group =
80 332563 : static_cast<DependentCode::DependencyGroup>(i);
81 2407022 : for (int j = 0; j < group_objects->length(); j++) {
82 2074459 : DependentCode* dependent_code = Get(group_objects->at(j));
83 870948 : dependent_code->UpdateToFinishedCode(group, *object_wrapper_, *cell);
84 : }
85 332563 : groups_[i] = nullptr; // Zone-allocated, no need to delete.
86 : }
87 : }
88 :
89 :
90 4835747 : void CompilationDependencies::Rollback() {
91 9671494 : if (IsEmpty()) return;
92 :
93 : AllowDeferredHandleDereference get_wrapper;
94 : // Unregister from all dependent maps if not yet committed.
95 60296 : for (int i = 0; i < DependentCode::kGroupCount; i++) {
96 60296 : ZoneList<Handle<HeapObject>>* group_objects = groups_[i];
97 60296 : if (group_objects == nullptr) continue;
98 : DependentCode::DependencyGroup group =
99 9246 : static_cast<DependentCode::DependencyGroup>(i);
100 87496 : for (int j = 0; j < group_objects->length(); j++) {
101 78250 : DependentCode* dependent_code = Get(group_objects->at(j));
102 34502 : dependent_code->RemoveCompilationDependencies(group, *object_wrapper_);
103 : }
104 9246 : groups_[i] = nullptr; // Zone-allocated, no need to delete.
105 : }
106 : }
107 :
108 :
109 4517 : void CompilationDependencies::AssumeMapNotDeprecated(Handle<Map> map) {
110 : DCHECK(!map->is_deprecated());
111 : // Do nothing if the map cannot be deprecated.
112 4517 : if (map->CanBeDeprecated()) {
113 4492 : Insert(DependentCode::kTransitionGroup, map);
114 : }
115 4517 : }
116 :
117 :
118 108273 : void CompilationDependencies::AssumeMapStable(Handle<Map> map) {
119 : DCHECK(map->is_stable());
120 : // Do nothing if the map cannot transition.
121 108273 : if (map->CanTransition()) {
122 106599 : Insert(DependentCode::kPrototypeCheckGroup, map);
123 : }
124 108273 : }
125 :
126 :
127 24406 : void CompilationDependencies::AssumePrototypeMapsStable(
128 : Handle<Map> map, MaybeHandle<JSReceiver> prototype) {
129 34292 : for (PrototypeIterator i(map); !i.IsAtEnd(); i.Advance()) {
130 : Handle<JSReceiver> const current =
131 : PrototypeIterator::GetCurrent<JSReceiver>(i);
132 33291 : AssumeMapStable(handle(current->map()));
133 : Handle<JSReceiver> last;
134 64580 : if (prototype.ToHandle(&last) && last.is_identical_to(current)) {
135 : break;
136 : }
137 : }
138 24406 : }
139 :
140 :
141 15946 : 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 15946 : site->SitePointsToLiteral()
146 : ? JSObject::cast(site->transition_info())->GetElementsKind()
147 15946 : : site->GetElementsKind();
148 15946 : if (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) {
149 4779 : Insert(DependentCode::kAllocationSiteTransitionChangedGroup, site);
150 : }
151 15946 : }
152 :
153 : } // namespace internal
154 : } // namespace v8
|