OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/value-numbering-reducer.h" | 5 #include "src/compiler/value-numbering-reducer.h" |
6 | 6 |
7 #include <cstring> | 7 #include <cstring> |
8 | 8 |
9 #include "src/base/functional.h" | 9 #include "src/base/functional.h" |
| 10 #include "src/compiler/node-properties.h" |
10 #include "src/compiler/node.h" | 11 #include "src/compiler/node.h" |
11 | 12 |
12 namespace v8 { | 13 namespace v8 { |
13 namespace internal { | 14 namespace internal { |
14 namespace compiler { | 15 namespace compiler { |
15 | 16 |
16 namespace { | 17 namespace { |
17 | 18 |
18 size_t HashCode(Node* node) { | 19 size_t HashCode(Node* node) { |
19 size_t h = base::hash_combine(node->op()->HashCode(), node->InputCount()); | 20 size_t h = base::hash_combine(node->op()->HashCode(), node->InputCount()); |
(...skipping 14 matching lines...) Expand all Loading... |
34 for (int j = 0; j < a->InputCount(); ++j) { | 35 for (int j = 0; j < a->InputCount(); ++j) { |
35 DCHECK_NOT_NULL(a->InputAt(j)); | 36 DCHECK_NOT_NULL(a->InputAt(j)); |
36 DCHECK_NOT_NULL(b->InputAt(j)); | 37 DCHECK_NOT_NULL(b->InputAt(j)); |
37 if (a->InputAt(j)->id() != b->InputAt(j)->id()) return false; | 38 if (a->InputAt(j)->id() != b->InputAt(j)->id()) return false; |
38 } | 39 } |
39 return true; | 40 return true; |
40 } | 41 } |
41 | 42 |
42 } // namespace | 43 } // namespace |
43 | 44 |
44 | 45 ValueNumberingReducer::ValueNumberingReducer(Zone* temp_zone, Zone* graph_zone) |
45 ValueNumberingReducer::ValueNumberingReducer(Zone* zone) | 46 : entries_(nullptr), |
46 : entries_(nullptr), capacity_(0), size_(0), zone_(zone) {} | 47 capacity_(0), |
47 | 48 size_(0), |
| 49 temp_zone_(temp_zone), |
| 50 graph_zone_(graph_zone) {} |
48 | 51 |
49 ValueNumberingReducer::~ValueNumberingReducer() {} | 52 ValueNumberingReducer::~ValueNumberingReducer() {} |
50 | 53 |
51 | 54 |
52 Reduction ValueNumberingReducer::Reduce(Node* node) { | 55 Reduction ValueNumberingReducer::Reduce(Node* node) { |
53 if (!node->op()->HasProperty(Operator::kIdempotent)) return NoChange(); | 56 if (!node->op()->HasProperty(Operator::kIdempotent)) return NoChange(); |
54 | 57 |
55 const size_t hash = HashCode(node); | 58 const size_t hash = HashCode(node); |
56 if (!entries_) { | 59 if (!entries_) { |
57 DCHECK(size_ == 0); | 60 DCHECK(size_ == 0); |
58 DCHECK(capacity_ == 0); | 61 DCHECK(capacity_ == 0); |
59 // Allocate the initial entries and insert the first entry. | 62 // Allocate the initial entries and insert the first entry. |
60 capacity_ = kInitialCapacity; | 63 capacity_ = kInitialCapacity; |
61 entries_ = zone()->NewArray<Node*>(kInitialCapacity); | 64 entries_ = temp_zone()->NewArray<Node*>(kInitialCapacity); |
62 memset(entries_, 0, sizeof(*entries_) * kInitialCapacity); | 65 memset(entries_, 0, sizeof(*entries_) * kInitialCapacity); |
63 entries_[hash & (kInitialCapacity - 1)] = node; | 66 entries_[hash & (kInitialCapacity - 1)] = node; |
64 size_ = 1; | 67 size_ = 1; |
65 return NoChange(); | 68 return NoChange(); |
66 } | 69 } |
67 | 70 |
68 DCHECK(size_ < capacity_); | 71 DCHECK(size_ < capacity_); |
69 DCHECK(size_ * kCapacityToSizeRatio < capacity_); | 72 DCHECK(size_ * kCapacityToSizeRatio < capacity_); |
70 | 73 |
71 const size_t mask = capacity_ - 1; | 74 const size_t mask = capacity_ - 1; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
116 } | 119 } |
117 } | 120 } |
118 } | 121 } |
119 | 122 |
120 // Skip dead entries, but remember their indices so we can reuse them. | 123 // Skip dead entries, but remember their indices so we can reuse them. |
121 if (entry->IsDead()) { | 124 if (entry->IsDead()) { |
122 dead = i; | 125 dead = i; |
123 continue; | 126 continue; |
124 } | 127 } |
125 if (Equals(entry, node)) { | 128 if (Equals(entry, node)) { |
| 129 // Make sure the replacement has at least as good type as the original |
| 130 // node. |
| 131 if (NodeProperties::IsTyped(entry) && NodeProperties::IsTyped(node)) { |
| 132 Type* entry_type = NodeProperties::GetType(entry); |
| 133 Type* node_type = NodeProperties::GetType(node); |
| 134 if (!entry_type->Is(node_type)) { |
| 135 NodeProperties::SetType( |
| 136 entry, Type::Intersect(entry_type, node_type, graph_zone())); |
| 137 } |
| 138 } |
126 return Replace(entry); | 139 return Replace(entry); |
127 } | 140 } |
128 } | 141 } |
129 } | 142 } |
130 | 143 |
131 | 144 |
132 void ValueNumberingReducer::Grow() { | 145 void ValueNumberingReducer::Grow() { |
133 // Allocate a new block of entries kCapacityToSizeRatio times the previous | 146 // Allocate a new block of entries kCapacityToSizeRatio times the previous |
134 // capacity. | 147 // capacity. |
135 Node** const old_entries = entries_; | 148 Node** const old_entries = entries_; |
136 size_t const old_capacity = capacity_; | 149 size_t const old_capacity = capacity_; |
137 capacity_ *= kCapacityToSizeRatio; | 150 capacity_ *= kCapacityToSizeRatio; |
138 entries_ = zone()->NewArray<Node*>(capacity_); | 151 entries_ = temp_zone()->NewArray<Node*>(capacity_); |
139 memset(entries_, 0, sizeof(*entries_) * capacity_); | 152 memset(entries_, 0, sizeof(*entries_) * capacity_); |
140 size_ = 0; | 153 size_ = 0; |
141 size_t const mask = capacity_ - 1; | 154 size_t const mask = capacity_ - 1; |
142 | 155 |
143 // Insert the old entries into the new block (skipping dead nodes). | 156 // Insert the old entries into the new block (skipping dead nodes). |
144 for (size_t i = 0; i < old_capacity; ++i) { | 157 for (size_t i = 0; i < old_capacity; ++i) { |
145 Node* const old_entry = old_entries[i]; | 158 Node* const old_entry = old_entries[i]; |
146 if (!old_entry || old_entry->IsDead()) continue; | 159 if (!old_entry || old_entry->IsDead()) continue; |
147 for (size_t j = HashCode(old_entry) & mask;; j = (j + 1) & mask) { | 160 for (size_t j = HashCode(old_entry) & mask;; j = (j + 1) & mask) { |
148 Node* const entry = entries_[j]; | 161 Node* const entry = entries_[j]; |
149 if (entry == old_entry) { | 162 if (entry == old_entry) { |
150 // Skip duplicate of the old entry. | 163 // Skip duplicate of the old entry. |
151 break; | 164 break; |
152 } | 165 } |
153 if (!entry) { | 166 if (!entry) { |
154 entries_[j] = old_entry; | 167 entries_[j] = old_entry; |
155 size_++; | 168 size_++; |
156 break; | 169 break; |
157 } | 170 } |
158 } | 171 } |
159 } | 172 } |
160 } | 173 } |
161 | 174 |
162 } // namespace compiler | 175 } // namespace compiler |
163 } // namespace internal | 176 } // namespace internal |
164 } // namespace v8 | 177 } // namespace v8 |
OLD | NEW |