Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(144)

Side by Side Diff: src/compiler/load-elimination.cc

Issue 2279213002: [turbofan] Introduce a dedicated ArrayBufferWasNeutered operator. (Closed)
Patch Set: Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/load-elimination.h ('k') | src/compiler/opcodes.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 the V8 project authors. All rights reserved. 1 // Copyright 2016 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/load-elimination.h" 5 #include "src/compiler/load-elimination.h"
6 6
7 #include "src/compiler/js-graph.h" 7 #include "src/compiler/js-graph.h"
8 #include "src/compiler/node-properties.h" 8 #include "src/compiler/node-properties.h"
9 #include "src/compiler/simplified-operator.h" 9 #include "src/compiler/simplified-operator.h"
10 10
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 } 48 }
49 49
50 bool MayAlias(Node* a, Node* b) { return QueryAlias(a, b) != kNoAlias; } 50 bool MayAlias(Node* a, Node* b) { return QueryAlias(a, b) != kNoAlias; }
51 51
52 bool MustAlias(Node* a, Node* b) { return QueryAlias(a, b) == kMustAlias; } 52 bool MustAlias(Node* a, Node* b) { return QueryAlias(a, b) == kMustAlias; }
53 53
54 } // namespace 54 } // namespace
55 55
56 Reduction LoadElimination::Reduce(Node* node) { 56 Reduction LoadElimination::Reduce(Node* node) {
57 switch (node->opcode()) { 57 switch (node->opcode()) {
58 case IrOpcode::kArrayBufferWasNeutered:
59 return ReduceArrayBufferWasNeutered(node);
58 case IrOpcode::kCheckMaps: 60 case IrOpcode::kCheckMaps:
59 return ReduceCheckMaps(node); 61 return ReduceCheckMaps(node);
60 case IrOpcode::kEnsureWritableFastElements: 62 case IrOpcode::kEnsureWritableFastElements:
61 return ReduceEnsureWritableFastElements(node); 63 return ReduceEnsureWritableFastElements(node);
62 case IrOpcode::kMaybeGrowFastElements: 64 case IrOpcode::kMaybeGrowFastElements:
63 return ReduceMaybeGrowFastElements(node); 65 return ReduceMaybeGrowFastElements(node);
64 case IrOpcode::kTransitionElementsKind: 66 case IrOpcode::kTransitionElementsKind:
65 return ReduceTransitionElementsKind(node); 67 return ReduceTransitionElementsKind(node);
66 case IrOpcode::kLoadField: 68 case IrOpcode::kLoadField:
67 return ReduceLoadField(node); 69 return ReduceLoadField(node);
(...skipping 10 matching lines...) Expand all
78 case IrOpcode::kDead: 80 case IrOpcode::kDead:
79 break; 81 break;
80 case IrOpcode::kStart: 82 case IrOpcode::kStart:
81 return ReduceStart(node); 83 return ReduceStart(node);
82 default: 84 default:
83 return ReduceOtherNode(node); 85 return ReduceOtherNode(node);
84 } 86 }
85 return NoChange(); 87 return NoChange();
86 } 88 }
87 89
90 namespace {
91
92 bool IsCompatibleCheck(Node const* a, Node const* b) {
93 if (a->op() != b->op()) return false;
94 for (int i = a->op()->ValueInputCount(); --i >= 0;) {
95 if (!MustAlias(a->InputAt(i), b->InputAt(i))) return false;
96 }
97 return true;
98 }
99
100 } // namespace
101
102 Node* LoadElimination::AbstractChecks::Lookup(Node* node) const {
103 for (Node* const check : nodes_) {
104 if (check && IsCompatibleCheck(check, node)) {
105 return check;
106 }
107 }
108 return nullptr;
109 }
110
111 bool LoadElimination::AbstractChecks::Equals(AbstractChecks const* that) const {
112 if (this == that) return true;
113 for (size_t i = 0; i < arraysize(nodes_); ++i) {
114 if (Node* this_node = this->nodes_[i]) {
115 for (size_t j = 0;; ++j) {
116 if (j == arraysize(nodes_)) return false;
117 if (that->nodes_[j] == this_node) break;
118 }
119 }
120 }
121 for (size_t i = 0; i < arraysize(nodes_); ++i) {
122 if (Node* that_node = that->nodes_[i]) {
123 for (size_t j = 0;; ++j) {
124 if (j == arraysize(nodes_)) return false;
125 if (this->nodes_[j] == that_node) break;
126 }
127 }
128 }
129 return true;
130 }
131
132 LoadElimination::AbstractChecks const* LoadElimination::AbstractChecks::Merge(
133 AbstractChecks const* that, Zone* zone) const {
134 if (this->Equals(that)) return this;
135 AbstractChecks* copy = new (zone) AbstractChecks(zone);
136 for (Node* const this_node : this->nodes_) {
137 if (this_node == nullptr) continue;
138 for (Node* const that_node : that->nodes_) {
139 if (this_node == that_node) {
140 copy->nodes_[copy->next_index_++] = this_node;
141 break;
142 }
143 }
144 }
145 copy->next_index_ %= arraysize(nodes_);
146 return copy;
147 }
148
88 Node* LoadElimination::AbstractElements::Lookup(Node* object, 149 Node* LoadElimination::AbstractElements::Lookup(Node* object,
89 Node* index) const { 150 Node* index) const {
90 for (Element const element : elements_) { 151 for (Element const element : elements_) {
91 if (element.object == nullptr) continue; 152 if (element.object == nullptr) continue;
92 DCHECK_NOT_NULL(element.index); 153 DCHECK_NOT_NULL(element.index);
93 DCHECK_NOT_NULL(element.value); 154 DCHECK_NOT_NULL(element.value);
94 if (MustAlias(object, element.object) && MustAlias(index, element.index)) { 155 if (MustAlias(object, element.object) && MustAlias(index, element.index)) {
95 return element.value; 156 return element.value;
96 } 157 }
97 } 158 }
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 Zone* zone) const { 219 Zone* zone) const {
159 if (this->Equals(that)) return this; 220 if (this->Equals(that)) return this;
160 AbstractElements* copy = new (zone) AbstractElements(zone); 221 AbstractElements* copy = new (zone) AbstractElements(zone);
161 for (Element const this_element : this->elements_) { 222 for (Element const this_element : this->elements_) {
162 if (this_element.object == nullptr) continue; 223 if (this_element.object == nullptr) continue;
163 for (Element const that_element : that->elements_) { 224 for (Element const that_element : that->elements_) {
164 if (this_element.object == that_element.object && 225 if (this_element.object == that_element.object &&
165 this_element.index == that_element.index && 226 this_element.index == that_element.index &&
166 this_element.value == that_element.value) { 227 this_element.value == that_element.value) {
167 copy->elements_[copy->next_index_++] = this_element; 228 copy->elements_[copy->next_index_++] = this_element;
229 break;
168 } 230 }
169 } 231 }
170 } 232 }
171 copy->next_index_ %= arraysize(elements_); 233 copy->next_index_ %= arraysize(elements_);
172 return copy; 234 return copy;
173 } 235 }
174 236
175 Node* LoadElimination::AbstractField::Lookup(Node* object) const { 237 Node* LoadElimination::AbstractField::Lookup(Node* object) const {
176 for (auto pair : info_for_node_) { 238 for (auto pair : info_for_node_) {
177 if (MustAlias(object, pair.first)) return pair.second; 239 if (MustAlias(object, pair.first)) return pair.second;
178 } 240 }
179 return nullptr; 241 return nullptr;
180 } 242 }
181 243
182 LoadElimination::AbstractField const* LoadElimination::AbstractField::Kill( 244 LoadElimination::AbstractField const* LoadElimination::AbstractField::Kill(
183 Node* object, Zone* zone) const { 245 Node* object, Zone* zone) const {
184 for (auto pair : this->info_for_node_) { 246 for (auto pair : this->info_for_node_) {
185 if (MayAlias(object, pair.first)) { 247 if (MayAlias(object, pair.first)) {
186 AbstractField* that = new (zone) AbstractField(zone); 248 AbstractField* that = new (zone) AbstractField(zone);
187 for (auto pair : this->info_for_node_) { 249 for (auto pair : this->info_for_node_) {
188 if (!MayAlias(object, pair.first)) that->info_for_node_.insert(pair); 250 if (!MayAlias(object, pair.first)) that->info_for_node_.insert(pair);
189 } 251 }
190 return that; 252 return that;
191 } 253 }
192 } 254 }
193 return this; 255 return this;
194 } 256 }
195 257
196 bool LoadElimination::AbstractState::Equals(AbstractState const* that) const { 258 bool LoadElimination::AbstractState::Equals(AbstractState const* that) const {
259 if (this->checks_) {
260 if (!that->checks_ || !that->checks_->Equals(this->checks_)) {
261 return false;
262 }
263 } else if (that->checks_) {
264 return false;
265 }
197 if (this->elements_) { 266 if (this->elements_) {
198 if (!that->elements_ || !that->elements_->Equals(this->elements_)) { 267 if (!that->elements_ || !that->elements_->Equals(this->elements_)) {
199 return false; 268 return false;
200 } 269 }
201 } else if (that->elements_) { 270 } else if (that->elements_) {
202 return false; 271 return false;
203 } 272 }
204 for (size_t i = 0u; i < arraysize(fields_); ++i) { 273 for (size_t i = 0u; i < arraysize(fields_); ++i) {
205 AbstractField const* this_field = this->fields_[i]; 274 AbstractField const* this_field = this->fields_[i];
206 AbstractField const* that_field = that->fields_[i]; 275 AbstractField const* that_field = that->fields_[i];
207 if (this_field) { 276 if (this_field) {
208 if (!that_field || !that_field->Equals(this_field)) return false; 277 if (!that_field || !that_field->Equals(this_field)) return false;
209 } else if (that_field) { 278 } else if (that_field) {
210 return false; 279 return false;
211 } 280 }
212 } 281 }
213 return true; 282 return true;
214 } 283 }
215 284
216 void LoadElimination::AbstractState::Merge(AbstractState const* that, 285 void LoadElimination::AbstractState::Merge(AbstractState const* that,
217 Zone* zone) { 286 Zone* zone) {
287 // Merge the information we have about the checks.
288 if (this->checks_) {
289 this->checks_ =
290 that->checks_ ? that->checks_->Merge(this->checks_, zone) : nullptr;
291 }
292
218 // Merge the information we have about the elements. 293 // Merge the information we have about the elements.
219 if (this->elements_) { 294 if (this->elements_) {
220 this->elements_ = that->elements_ 295 this->elements_ = that->elements_
221 ? that->elements_->Merge(this->elements_, zone) 296 ? that->elements_->Merge(this->elements_, zone)
222 : nullptr; 297 : nullptr;
223 } 298 }
224 299
225 // Merge the information we have about the fields. 300 // Merge the information we have about the fields.
226 for (size_t i = 0; i < arraysize(fields_); ++i) { 301 for (size_t i = 0; i < arraysize(fields_); ++i) {
227 if (this->fields_[i]) { 302 if (this->fields_[i]) {
228 if (that->fields_[i]) { 303 if (that->fields_[i]) {
229 this->fields_[i] = this->fields_[i]->Merge(that->fields_[i], zone); 304 this->fields_[i] = this->fields_[i]->Merge(that->fields_[i], zone);
230 } else { 305 } else {
231 this->fields_[i] = nullptr; 306 this->fields_[i] = nullptr;
232 } 307 }
233 } 308 }
234 } 309 }
235 } 310 }
236 311
312 Node* LoadElimination::AbstractState::LookupCheck(Node* node) const {
313 return this->checks_ ? this->checks_->Lookup(node) : nullptr;
314 }
315
316 LoadElimination::AbstractState const* LoadElimination::AbstractState::AddCheck(
317 Node* node, Zone* zone) const {
318 AbstractState* that = new (zone) AbstractState(*this);
319 if (that->checks_) {
320 that->checks_ = that->checks_->Extend(node, zone);
321 } else {
322 that->checks_ = new (zone) AbstractChecks(node, zone);
323 }
324 return that;
325 }
326
237 Node* LoadElimination::AbstractState::LookupElement(Node* object, 327 Node* LoadElimination::AbstractState::LookupElement(Node* object,
238 Node* index) const { 328 Node* index) const {
239 if (this->elements_) { 329 if (this->elements_) {
240 return this->elements_->Lookup(object, index); 330 return this->elements_->Lookup(object, index);
241 } 331 }
242 return nullptr; 332 return nullptr;
243 } 333 }
244 334
245 LoadElimination::AbstractState const* 335 LoadElimination::AbstractState const*
246 LoadElimination::AbstractState::AddElement(Node* object, Node* index, 336 LoadElimination::AbstractState::AddElement(Node* object, Node* index,
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
308 return nullptr; 398 return nullptr;
309 } 399 }
310 400
311 void LoadElimination::AbstractStateForEffectNodes::Set( 401 void LoadElimination::AbstractStateForEffectNodes::Set(
312 Node* node, AbstractState const* state) { 402 Node* node, AbstractState const* state) {
313 size_t const id = node->id(); 403 size_t const id = node->id();
314 if (id >= info_for_node_.size()) info_for_node_.resize(id + 1, nullptr); 404 if (id >= info_for_node_.size()) info_for_node_.resize(id + 1, nullptr);
315 info_for_node_[id] = state; 405 info_for_node_[id] = state;
316 } 406 }
317 407
408 Reduction LoadElimination::ReduceArrayBufferWasNeutered(Node* node) {
409 Node* const effect = NodeProperties::GetEffectInput(node);
410 AbstractState const* state = node_states_.Get(effect);
411 if (state == nullptr) return NoChange();
412 if (Node* const check = state->LookupCheck(node)) {
413 ReplaceWithValue(node, check, effect);
414 return Replace(check);
415 }
416 state = state->AddCheck(node, zone());
417 return UpdateState(node, state);
418 }
419
318 Reduction LoadElimination::ReduceCheckMaps(Node* node) { 420 Reduction LoadElimination::ReduceCheckMaps(Node* node) {
319 Node* const object = NodeProperties::GetValueInput(node, 0); 421 Node* const object = NodeProperties::GetValueInput(node, 0);
320 Node* const effect = NodeProperties::GetEffectInput(node); 422 Node* const effect = NodeProperties::GetEffectInput(node);
321 AbstractState const* state = node_states_.Get(effect); 423 AbstractState const* state = node_states_.Get(effect);
322 if (state == nullptr) return NoChange(); 424 if (state == nullptr) return NoChange();
323 int const map_input_count = node->op()->ValueInputCount() - 1; 425 int const map_input_count = node->op()->ValueInputCount() - 1;
324 if (Node* const object_map = state->LookupField(object, 0)) { 426 if (Node* const object_map = state->LookupField(object, 0)) {
325 for (int i = 0; i < map_input_count; ++i) { 427 for (int i = 0; i < map_input_count; ++i) {
326 Node* map = NodeProperties::GetValueInput(node, 1 + i); 428 Node* map = NodeProperties::GetValueInput(node, 1 + i);
327 if (map == object_map) return Replace(effect); 429 if (map == object_map) return Replace(effect);
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 DCHECK_EQ(kTaggedBase, access.base_is_tagged); 801 DCHECK_EQ(kTaggedBase, access.base_is_tagged);
700 DCHECK_EQ(0, access.offset % kPointerSize); 802 DCHECK_EQ(0, access.offset % kPointerSize);
701 int field_index = access.offset / kPointerSize; 803 int field_index = access.offset / kPointerSize;
702 if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1; 804 if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1;
703 return field_index; 805 return field_index;
704 } 806 }
705 807
706 } // namespace compiler 808 } // namespace compiler
707 } // namespace internal 809 } // namespace internal
708 } // namespace v8 810 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/load-elimination.h ('k') | src/compiler/opcodes.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698