OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 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 | 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/js-native-context-specialization.h" | 5 #include "src/compiler/js-native-context-specialization.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 208 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
209 receiver, effect, control); | 209 receiver, effect, control); |
210 | 210 |
211 // Generate code for the various different property access patterns. | 211 // Generate code for the various different property access patterns. |
212 Node* fallthrough_control = control; | 212 Node* fallthrough_control = control; |
213 for (size_t j = 0; j < access_infos.size(); ++j) { | 213 for (size_t j = 0; j < access_infos.size(); ++j) { |
214 PropertyAccessInfo const& access_info = access_infos[j]; | 214 PropertyAccessInfo const& access_info = access_infos[j]; |
215 Node* this_value = value; | 215 Node* this_value = value; |
216 Node* this_receiver = receiver; | 216 Node* this_receiver = receiver; |
217 Node* this_effect = effect; | 217 Node* this_effect = effect; |
218 Node* this_control; | 218 Node* this_control = fallthrough_control; |
219 | 219 |
220 // Perform map check on {receiver}. | 220 // Perform map check on {receiver}. |
221 MapList const& receiver_maps = access_info.receiver_maps(); | 221 MapList const& receiver_maps = access_info.receiver_maps(); |
222 { | 222 { |
223 // Emit a (sequence of) map checks for other {receiver}s. | 223 // Emit a (sequence of) map checks for other {receiver}s. |
224 ZoneVector<Node*> this_controls(zone()); | 224 ZoneVector<Node*> this_controls(zone()); |
225 ZoneVector<Node*> this_effects(zone()); | 225 ZoneVector<Node*> this_effects(zone()); |
226 size_t num_classes = receiver_maps.size(); | 226 if (j == access_infos.size() - 1) { |
227 for (auto map : receiver_maps) { | 227 // Last map check on the fallthrough control path, do a |
228 DCHECK_LT(0u, num_classes); | 228 // conditional eager deoptimization exit here. |
229 Node* check = | 229 this_effect = BuildCheckMaps(receiver, this_effect, this_control, |
230 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map, | 230 receiver_maps); |
231 jsgraph()->Constant(map)); | 231 this_effects.push_back(this_effect); |
232 if (--num_classes == 0 && j == access_infos.size() - 1) { | 232 this_controls.push_back(fallthrough_control); |
233 check = graph()->NewNode(simplified()->CheckIf(), check, | 233 fallthrough_control = nullptr; |
234 this_effect, fallthrough_control); | 234 } else { |
235 this_controls.push_back(fallthrough_control); | 235 for (auto map : receiver_maps) { |
236 this_effects.push_back(check); | 236 Node* check = |
237 fallthrough_control = nullptr; | 237 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map, |
238 } else { | 238 jsgraph()->Constant(map)); |
239 Node* branch = graph()->NewNode(common()->Branch(), check, | 239 Node* branch = graph()->NewNode(common()->Branch(), check, |
240 fallthrough_control); | 240 fallthrough_control); |
241 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); | 241 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); |
242 this_controls.push_back( | 242 this_controls.push_back( |
243 graph()->NewNode(common()->IfTrue(), branch)); | 243 graph()->NewNode(common()->IfTrue(), branch)); |
244 this_effects.push_back(this_effect); | 244 this_effects.push_back(this_effect); |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 // The Number case requires special treatment to also deal with Smis. | 248 // The Number case requires special treatment to also deal with Smis. |
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
572 this_control); | 572 this_control); |
573 } | 573 } |
574 | 574 |
575 // Load the {receiver} map. | 575 // Load the {receiver} map. |
576 Node* receiver_map = this_effect = | 576 Node* receiver_map = this_effect = |
577 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 577 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
578 receiver, this_effect, this_control); | 578 receiver, this_effect, this_control); |
579 | 579 |
580 // Perform map check(s) on {receiver}. | 580 // Perform map check(s) on {receiver}. |
581 MapList const& receiver_maps = access_info.receiver_maps(); | 581 MapList const& receiver_maps = access_info.receiver_maps(); |
582 { | 582 if (j == access_infos.size() - 1) { |
| 583 // Last map check on the fallthrough control path, do a |
| 584 // conditional eager deoptimization exit here. |
| 585 this_effect = BuildCheckMaps(receiver, this_effect, this_control, |
| 586 receiver_maps); |
| 587 fallthrough_control = nullptr; |
| 588 } else { |
583 ZoneVector<Node*> this_controls(zone()); | 589 ZoneVector<Node*> this_controls(zone()); |
584 ZoneVector<Node*> this_effects(zone()); | 590 ZoneVector<Node*> this_effects(zone()); |
585 size_t num_classes = receiver_maps.size(); | |
586 for (Handle<Map> map : receiver_maps) { | 591 for (Handle<Map> map : receiver_maps) { |
587 DCHECK_LT(0u, num_classes); | |
588 Node* check = | 592 Node* check = |
589 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map, | 593 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map, |
590 jsgraph()->Constant(map)); | 594 jsgraph()->Constant(map)); |
591 if (--num_classes == 0 && j == access_infos.size() - 1) { | 595 Node* branch = graph()->NewNode(common()->Branch(), check, |
592 // Last map check on the fallthrough control path, do a | 596 fallthrough_control); |
593 // conditional eager deoptimization exit here. | 597 this_controls.push_back( |
594 // TODO(turbofan): This is ugly as hell! We should probably | 598 graph()->NewNode(common()->IfTrue(), branch)); |
595 // introduce macro-ish operators for property access that | 599 this_effects.push_back(this_effect); |
596 // encapsulate this whole mess. | 600 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); |
597 check = graph()->NewNode(simplified()->CheckIf(), check, | |
598 this_effect, this_control); | |
599 this_controls.push_back(this_control); | |
600 this_effects.push_back(check); | |
601 fallthrough_control = nullptr; | |
602 } else { | |
603 Node* branch = graph()->NewNode(common()->Branch(), check, | |
604 fallthrough_control); | |
605 this_controls.push_back( | |
606 graph()->NewNode(common()->IfTrue(), branch)); | |
607 this_effects.push_back(this_effect); | |
608 fallthrough_control = | |
609 graph()->NewNode(common()->IfFalse(), branch); | |
610 } | |
611 } | 601 } |
612 | 602 |
613 // Create single chokepoint for the control. | 603 // Create single chokepoint for the control. |
614 int const this_control_count = static_cast<int>(this_controls.size()); | 604 int const this_control_count = static_cast<int>(this_controls.size()); |
615 if (this_control_count == 1) { | 605 if (this_control_count == 1) { |
616 this_control = this_controls.front(); | 606 this_control = this_controls.front(); |
617 this_effect = this_effects.front(); | 607 this_effect = this_effects.front(); |
618 } else { | 608 } else { |
619 this_control = | 609 this_control = |
620 graph()->NewNode(common()->Merge(this_control_count), | 610 graph()->NewNode(common()->Merge(this_control_count), |
(...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1503 return jsgraph()->javascript(); | 1493 return jsgraph()->javascript(); |
1504 } | 1494 } |
1505 | 1495 |
1506 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 1496 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
1507 return jsgraph()->simplified(); | 1497 return jsgraph()->simplified(); |
1508 } | 1498 } |
1509 | 1499 |
1510 } // namespace compiler | 1500 } // namespace compiler |
1511 } // namespace internal | 1501 } // namespace internal |
1512 } // namespace v8 | 1502 } // namespace v8 |
OLD | NEW |