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-properties.h" |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
105 // do is return Replace(node2) instead. | 105 // do is return Replace(node2) instead. |
106 for (size_t j = (i + 1) & mask;; j = (j + 1) & mask) { | 106 for (size_t j = (i + 1) & mask;; j = (j + 1) & mask) { |
107 Node* entry = entries_[j]; | 107 Node* entry = entries_[j]; |
108 if (!entry) { | 108 if (!entry) { |
109 // No collision, {node} is fine. | 109 // No collision, {node} is fine. |
110 return NoChange(); | 110 return NoChange(); |
111 } | 111 } |
112 if (entry->IsDead()) { | 112 if (entry->IsDead()) { |
113 continue; | 113 continue; |
114 } | 114 } |
| 115 if (entry == node) { |
| 116 // Collision with ourselves, doesn't count as a real collision. |
| 117 // Opportunistically clean-up the duplicate entry if we're at the end |
| 118 // of a bucket. |
| 119 if (!entries_[(j + 1) & mask]) { |
| 120 entries_[j] = nullptr; |
| 121 size_--; |
| 122 return NoChange(); |
| 123 } |
| 124 // Otherwise, keep searching for another collision. |
| 125 continue; |
| 126 } |
115 if (Equals(entry, node)) { | 127 if (Equals(entry, node)) { |
116 // Overwrite the colliding entry with the actual entry. | 128 Reduction reduction = ReplaceIfTypesMatch(node, entry); |
117 entries_[i] = entry; | 129 if (reduction.Changed()) { |
118 return Replace(entry); | 130 // Overwrite the colliding entry with the actual entry. |
| 131 entries_[i] = entry; |
| 132 // Opportunistically clean-up the duplicate entry if we're at the |
| 133 // end of a bucket. |
| 134 if (!entries_[(j + 1) & mask]) { |
| 135 entries_[j] = nullptr; |
| 136 size_--; |
| 137 } |
| 138 } |
| 139 return reduction; |
119 } | 140 } |
120 } | 141 } |
121 } | 142 } |
122 | 143 |
123 // Skip dead entries, but remember their indices so we can reuse them. | 144 // Skip dead entries, but remember their indices so we can reuse them. |
124 if (entry->IsDead()) { | 145 if (entry->IsDead()) { |
125 dead = i; | 146 dead = i; |
126 continue; | 147 continue; |
127 } | 148 } |
128 if (Equals(entry, node)) { | 149 if (Equals(entry, node)) { |
129 // Make sure the replacement has at least as good type as the original | 150 return ReplaceIfTypesMatch(node, entry); |
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 // Ideally, we would set an intersection of {entry_type} and | |
136 // {node_type} here. However, typing of NumberConstants assigns | |
137 // different types to constants with the same value (it creates | |
138 // a fresh heap number), which would make the intersection empty. | |
139 // To be safe, we use the smaller type if the types are comparable. | |
140 if (node_type->Is(entry_type)) { | |
141 NodeProperties::SetType(entry, node_type); | |
142 } else { | |
143 // Types are not comparable => do not replace. | |
144 return NoChange(); | |
145 } | |
146 } | |
147 } | |
148 return Replace(entry); | |
149 } | 151 } |
150 } | 152 } |
151 } | 153 } |
152 | 154 |
| 155 Reduction ValueNumberingReducer::ReplaceIfTypesMatch(Node* node, |
| 156 Node* replacement) { |
| 157 // Make sure the replacement has at least as good type as the original node. |
| 158 if (NodeProperties::IsTyped(replacement) && NodeProperties::IsTyped(node)) { |
| 159 Type* replacement_type = NodeProperties::GetType(replacement); |
| 160 Type* node_type = NodeProperties::GetType(node); |
| 161 if (!replacement_type->Is(node_type)) { |
| 162 // Ideally, we would set an intersection of {replacement_type} and |
| 163 // {node_type} here. However, typing of NumberConstants assigns different |
| 164 // types to constants with the same value (it creates a fresh heap |
| 165 // number), which would make the intersection empty. To be safe, we use |
| 166 // the smaller type if the types are comparable. |
| 167 if (node_type->Is(replacement_type)) { |
| 168 NodeProperties::SetType(replacement, node_type); |
| 169 } else { |
| 170 // Types are not comparable => do not replace. |
| 171 return NoChange(); |
| 172 } |
| 173 } |
| 174 } |
| 175 return Replace(replacement); |
| 176 } |
153 | 177 |
| 178 |
154 void ValueNumberingReducer::Grow() { | 179 void ValueNumberingReducer::Grow() { |
155 // Allocate a new block of entries double the previous capacity. | 180 // Allocate a new block of entries double the previous capacity. |
156 Node** const old_entries = entries_; | 181 Node** const old_entries = entries_; |
157 size_t const old_capacity = capacity_; | 182 size_t const old_capacity = capacity_; |
158 capacity_ *= 2; | 183 capacity_ *= 2; |
159 entries_ = temp_zone()->NewArray<Node*>(capacity_); | 184 entries_ = temp_zone()->NewArray<Node*>(capacity_); |
160 memset(entries_, 0, sizeof(*entries_) * capacity_); | 185 memset(entries_, 0, sizeof(*entries_) * capacity_); |
161 size_ = 0; | 186 size_ = 0; |
162 size_t const mask = capacity_ - 1; | 187 size_t const mask = capacity_ - 1; |
163 | 188 |
(...skipping 12 matching lines...) Expand all Loading... |
176 size_++; | 201 size_++; |
177 break; | 202 break; |
178 } | 203 } |
179 } | 204 } |
180 } | 205 } |
181 } | 206 } |
182 | 207 |
183 } // namespace compiler | 208 } // namespace compiler |
184 } // namespace internal | 209 } // namespace internal |
185 } // namespace v8 | 210 } // namespace v8 |
OLD | NEW |