| 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 |